diff --git a/.idea/misc.xml b/.idea/misc.xml index a52e9fd..b6581c9 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -4,10 +4,11 @@ diff --git a/app/src/main/java/it/danieleverducci/ojo/entities/Camera.java b/app/src/main/java/it/danieleverducci/ojo/entities/Camera.java index 3a1512f..dbee900 100644 --- a/app/src/main/java/it/danieleverducci/ojo/entities/Camera.java +++ b/app/src/main/java/it/danieleverducci/ojo/entities/Camera.java @@ -11,6 +11,14 @@ public class Camera implements Serializable { this.rtspUrl = rtspUrl; } + public void setName(String name) { + this.name = name; + } + + public void setRtspUrl(String rtspUrl) { + this.rtspUrl = rtspUrl; + } + public String getName() { return name; } diff --git a/app/src/main/java/it/danieleverducci/ojo/ui/MainActivity.java b/app/src/main/java/it/danieleverducci/ojo/ui/MainActivity.java index 1f4b5c8..157826c 100644 --- a/app/src/main/java/it/danieleverducci/ojo/ui/MainActivity.java +++ b/app/src/main/java/it/danieleverducci/ojo/ui/MainActivity.java @@ -44,11 +44,18 @@ public class MainActivity extends AppCompatActivity { } public void navigateToFragment(int actionId) { + navigateToFragment(actionId, null); + } + + public void navigateToFragment(int actionId, Bundle bundle) { if (navController == null) { Log.e(TAG, "Not initialized"); return; } - navController.navigate(actionId); + if (bundle != null) + navController.navigate(actionId, bundle); + else + navController.navigate(actionId); } } \ No newline at end of file diff --git a/app/src/main/java/it/danieleverducci/ojo/ui/SettingsFragment.java b/app/src/main/java/it/danieleverducci/ojo/ui/SettingsFragment.java index f542a94..ed4f8d8 100644 --- a/app/src/main/java/it/danieleverducci/ojo/ui/SettingsFragment.java +++ b/app/src/main/java/it/danieleverducci/ojo/ui/SettingsFragment.java @@ -3,6 +3,8 @@ package it.danieleverducci.ojo.ui; import android.content.Context; import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.ItemTouchHelper; @@ -10,6 +12,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; @@ -17,6 +20,7 @@ import java.util.List; import it.danieleverducci.ojo.R; import it.danieleverducci.ojo.Settings; +import it.danieleverducci.ojo.databinding.FragmentSettingsItemListBinding; import it.danieleverducci.ojo.entities.Camera; import it.danieleverducci.ojo.ui.adapters.SettingsRecyclerViewAdapter; import it.danieleverducci.ojo.utils.ItemMoveCallback; @@ -26,43 +30,51 @@ import it.danieleverducci.ojo.utils.ItemMoveCallback; */ public class SettingsFragment extends Fragment { - public SettingsFragment() { - } - - public static SettingsFragment newInstance() { - SettingsFragment fragment = new SettingsFragment(); - return fragment; - } + private FragmentSettingsItemListBinding binding; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.fragment_settings_item_list, container, false); + binding = FragmentSettingsItemListBinding.inflate(inflater, container, false); // Load cameras Settings settings = Settings.fromDisk(getContext()); List cams = settings.getCameras(); // Set the adapter - if (view instanceof RecyclerView) { - Context context = view.getContext(); - RecyclerView recyclerView = (RecyclerView) view; - recyclerView.setLayoutManager(new LinearLayoutManager(context)); - SettingsRecyclerViewAdapter adapter = new SettingsRecyclerViewAdapter(cams); - ItemTouchHelper.Callback callback = - new ItemMoveCallback(adapter); - ItemTouchHelper touchHelper = new ItemTouchHelper(callback); - touchHelper.attachToRecyclerView(recyclerView); - adapter.setOnDragListener(touchHelper::startDrag); - recyclerView.setAdapter(adapter); - // Onclick listener - adapter.setOnClickListener(new SettingsRecyclerViewAdapter.OnClickListener() { - @Override - public void onItemClick(Camera c) { - ((MainActivity)getActivity()).navigateToFragment(R.id.action_homeToSettings); - } - }); + RecyclerView recyclerView = binding.list; + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + SettingsRecyclerViewAdapter adapter = new SettingsRecyclerViewAdapter(cams); + ItemTouchHelper.Callback callback = + new ItemMoveCallback(adapter); + ItemTouchHelper touchHelper = new ItemTouchHelper(callback); + touchHelper.attachToRecyclerView(recyclerView); + adapter.setOnDragListener(touchHelper::startDrag); + recyclerView.setAdapter(adapter); + // Onclick listener + adapter.setOnClickListener(new SettingsRecyclerViewAdapter.OnClickListener() { + @Override + public void onItemClick(int pos) { + Bundle b = new Bundle(); + b.putInt(StreamUrlFragment.ARG_CAMERA, pos); + ((MainActivity)getActivity()).navigateToFragment(R.id.action_settingsToCameraUrl, b); + } + }); + + return binding.getRoot(); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + binding.settingsToolbar.inflateMenu(R.menu.settings_menu); + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if (item.getItemId() == R.id.menuitem_add_camera) { + ((MainActivity)getActivity()).navigateToFragment(R.id.action_settingsToCameraUrl); + return true; } - return view; + return super.onOptionsItemSelected(item); } } \ No newline at end of file diff --git a/app/src/main/java/it/danieleverducci/ojo/ui/AddStreamFragment.java b/app/src/main/java/it/danieleverducci/ojo/ui/StreamUrlFragment.java similarity index 55% rename from app/src/main/java/it/danieleverducci/ojo/ui/AddStreamFragment.java rename to app/src/main/java/it/danieleverducci/ojo/ui/StreamUrlFragment.java index 6a66925..75a2a27 100644 --- a/app/src/main/java/it/danieleverducci/ojo/ui/AddStreamFragment.java +++ b/app/src/main/java/it/danieleverducci/ojo/ui/StreamUrlFragment.java @@ -6,6 +6,7 @@ import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.navigation.fragment.NavHostFragment; @@ -16,9 +17,20 @@ import it.danieleverducci.ojo.Settings; import it.danieleverducci.ojo.databinding.FragmentAddStreamBinding; import it.danieleverducci.ojo.entities.Camera; -public class AddStreamFragment extends Fragment { +public class StreamUrlFragment extends Fragment { + public static final String ARG_CAMERA = "arg_camera"; private FragmentAddStreamBinding binding; + private Settings settings; + private Integer selectedCamera = null; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Load existing settings (if any) + settings = Settings.fromDisk(getContext()); + } @Override public View onCreateView( @@ -27,6 +39,18 @@ public class AddStreamFragment extends Fragment { ) { binding = FragmentAddStreamBinding.inflate(inflater, container, false); + + // If passed an url, fill the details + Bundle args = getArguments(); + if (args != null && args.containsKey(ARG_CAMERA)) { + this.selectedCamera = args.getInt(ARG_CAMERA); + + Camera c = settings.getCameras().get(this.selectedCamera); + binding.streamName.setText(c.getName()); + binding.streamName.setHint(getContext().getString(R.string.stream_list_default_camera_name).replace("{camNo}", (this.selectedCamera+1)+"")); + binding.streamUrl.setText(c.getRtspUrl()); + } + return binding.getRoot(); } @@ -45,10 +69,19 @@ public class AddStreamFragment extends Fragment { return; } - // Load existing settings (if any) - Settings settings = Settings.fromDisk(getContext()); - // Add stream to list - settings.addCamera(new Camera("", url)); + // Name can be empty + String name = binding.streamName.getText().toString(); + + if (StreamUrlFragment.this.selectedCamera != null) { + // Update camera + Camera c = settings.getCameras().get(StreamUrlFragment.this.selectedCamera); + c.setName(name); + c.setRtspUrl(url); + } else { + // Add stream to list + settings.addCamera(new Camera(name, url)); + } + // Save if (!settings.save()) { Snackbar.make(view, R.string.add_stream_error_saving, Snackbar.LENGTH_LONG).show(); @@ -56,7 +89,7 @@ public class AddStreamFragment extends Fragment { } // Back to first fragment - NavHostFragment.findNavController(AddStreamFragment.this) + NavHostFragment.findNavController(StreamUrlFragment.this) .popBackStack(); } }); diff --git a/app/src/main/java/it/danieleverducci/ojo/ui/adapters/SettingsRecyclerViewAdapter.java b/app/src/main/java/it/danieleverducci/ojo/ui/adapters/SettingsRecyclerViewAdapter.java index 0211aa3..c5dacbe 100644 --- a/app/src/main/java/it/danieleverducci/ojo/ui/adapters/SettingsRecyclerViewAdapter.java +++ b/app/src/main/java/it/danieleverducci/ojo/ui/adapters/SettingsRecyclerViewAdapter.java @@ -39,12 +39,6 @@ public class SettingsRecyclerViewAdapter extends RecyclerView.Adapter + + + + - \ No newline at end of file + android:orientation="vertical"> + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_surveillance.xml b/app/src/main/res/layout/fragment_surveillance.xml index a70f98e..513c984 100644 --- a/app/src/main/res/layout/fragment_surveillance.xml +++ b/app/src/main/res/layout/fragment_surveillance.xml @@ -6,7 +6,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" - tools:context=".ui.AddStreamFragment" + tools:context=".ui.StreamUrlFragment" android:background="@color/purple_500"> diff --git a/app/src/main/res/menu/settings_menu.xml b/app/src/main/res/menu/settings_menu.xml new file mode 100644 index 0000000..d9ab9f2 --- /dev/null +++ b/app/src/main/res/menu/settings_menu.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 11b6d44..9ee6946 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -17,7 +17,7 @@ First Fragment Second Fragment - Videocamera n°{camNo} + Videocamera senza nome n°{camNo} rtsp://username:password@192.168.1.123:554 + Nome della IP Camera Inserisci l\'url dello stream RTSP della tua IP Camera. Nota che questo differisce tra un modello e l\'altro. Consulta il pannello di configurazione o il manuale della tua IP Camera. Salva L\'URL RTSP non è valido Chiudi Si è verificato un errore durante il salvataggio della configurazione. + Aggiungi + Informazioni su Ojo Creato da Daniele Verducci. Questa app è rilasciata sotto licenza GNU GENERAL PUBLIC LICENSE v3+. Puoi ottenerne una copia qui: https://raw.githubusercontent.com/penguin86/ojo/master/LICENSE diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a7bdbb7..6758831 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -4,15 +4,18 @@ First Fragment Second Fragment - Camera {camNo} + Unnamed camera {camNo} rtsp://username:password@192.168.1.123:554 + Camera name Please insert your camera\'s RTSP stream. Note that the URL differs from camera to camera: you can find the complete URL in your camera\'s settings or user manual. Save Invalid RTSP url Dismiss An error has occurred while saving configuration + Add + About Ojo Created by Daniele Verducci. This application is licensed under the GNU GENERAL PUBLIC LICENSE v3+. You can obtain a copy here: https://raw.githubusercontent.com/penguin86/ojo/master/LICENSE diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 7ce18d5..31f47b3 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -14,4 +14,6 @@ @color/white + + \ No newline at end of file