diff --git a/.idea/misc.xml b/.idea/misc.xml index b82c61c..6395638 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -4,6 +4,7 @@ diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000..2e9b1d7 Binary files /dev/null and b/app/src/main/ic_launcher-playstore.png differ diff --git a/app/src/main/java/it/danieleverducci/ojo/Settings.java b/app/src/main/java/it/danieleverducci/ojo/Settings.java new file mode 100644 index 0000000..c0599a0 --- /dev/null +++ b/app/src/main/java/it/danieleverducci/ojo/Settings.java @@ -0,0 +1,74 @@ +package it.danieleverducci.ojo; + +import android.content.Context; +import android.util.Log; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import it.danieleverducci.ojo.entities.Camera; + +/** + * Manages the settings persistence + */ +public class Settings { + private static final String FILENAME = "settings.bin"; + private static final String TAG = "Settings"; + + private volatile String settingsFilePath; + private List cameras = new ArrayList<>(); + + public static Settings fromDisk(Context context) { + String filePath = context.getFilesDir() + File.separator + FILENAME; + Settings s = new Settings(); + try { + FileInputStream fin = new FileInputStream(filePath); + ObjectInputStream ois = new ObjectInputStream(fin); + s = (Settings) ois.readObject(); + } catch (FileNotFoundException e) { + Log.d(TAG, "No saved settings found, will create a new one"); + } catch (IOException e) { + Log.e(TAG, "Unable to load settings from disk: " + e.toString()); + } catch (ClassNotFoundException e) { + Log.e(TAG, e.toString()); + } + s.settingsFilePath = filePath; + return s; + } + + public List getCameras() { + return cameras; + } + + public void setCameras(List cameras) { + this.cameras = cameras; + } + + public void addCamera(Camera camera) { + this.cameras.add(camera); + } + + public boolean save() { + try { + FileOutputStream fout = new FileOutputStream(settingsFilePath); + ObjectOutputStream oos = new ObjectOutputStream(fout); + oos.writeObject(this); + fout.close(); + oos.close(); + return true; + } catch (FileNotFoundException e) { + Log.e(TAG, "Unable to create file " + settingsFilePath + ": " + e.toString()); + } catch (IOException e) { + Log.e(TAG, "Unable to save settings: " + e.toString()); + } + return false; + } +} diff --git a/app/src/main/java/it/danieleverducci/ojo/ui/AddStreamFragment.java b/app/src/main/java/it/danieleverducci/ojo/ui/AddStreamFragment.java index 2da7994..d8e63cd 100644 --- a/app/src/main/java/it/danieleverducci/ojo/ui/AddStreamFragment.java +++ b/app/src/main/java/it/danieleverducci/ojo/ui/AddStreamFragment.java @@ -9,7 +9,12 @@ import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.navigation.fragment.NavHostFragment; +import com.google.android.material.snackbar.Snackbar; + +import it.danieleverducci.ojo.R; +import it.danieleverducci.ojo.Settings; import it.danieleverducci.ojo.databinding.FragmentAddStreamBinding; +import it.danieleverducci.ojo.entities.Camera; public class AddStreamFragment extends Fragment { @@ -29,13 +34,32 @@ public class AddStreamFragment extends Fragment { public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); -// binding.buttonSecond.setOnClickListener(new View.OnClickListener() { -// @Override -// public void onClick(View view) { -// NavHostFragment.findNavController(AddStreamFragment.this) -// .navigate(R.id.action_SecondFragment_to_FirstFragment); -// } -// }); + binding.save.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + // Check the field is filled + String url = binding.streamUrl.getText().toString(); + if (!url.startsWith("rtsp://")) { + Snackbar.make(view, R.string.add_stream_invalid_url, Snackbar.LENGTH_LONG) + .setAction(R.string.add_stream_invalid_url_dismiss, null).show(); + return; + } + + // Load existing settings (if any) + Settings settings = Settings.fromDisk(getContext()); + // Add stream to list + settings.addCamera(new Camera("", url)); + // Save + if (!settings.save()) { + Snackbar.make(view, R.string.add_stream_error_saving, Snackbar.LENGTH_LONG).show(); + return; + } + + // Back to first fragment + NavHostFragment.findNavController(AddStreamFragment.this) + .navigate(R.id.action_SecondFragment_to_FirstFragment); + } + }); } @Override 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 4b9e923..1542681 100644 --- a/app/src/main/java/it/danieleverducci/ojo/ui/MainActivity.java +++ b/app/src/main/java/it/danieleverducci/ojo/ui/MainActivity.java @@ -30,13 +30,19 @@ public class MainActivity extends AppCompatActivity { binding = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); + // Show FAB only on first fragment NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main); + navController.addOnDestinationChangedListener((controller, destination, arguments) -> { + if (destination.getId() == R.id.FirstFragment) + binding.fab.show(); + else + binding.fab.hide(); + }); binding.fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); + navController.navigate(R.id.action_FirstFragment_to_SecondFragment); } }); } diff --git a/app/src/main/java/it/danieleverducci/ojo/ui/SurveillanceFragment.java b/app/src/main/java/it/danieleverducci/ojo/ui/SurveillanceFragment.java index 3c8f974..ac04e90 100644 --- a/app/src/main/java/it/danieleverducci/ojo/ui/SurveillanceFragment.java +++ b/app/src/main/java/it/danieleverducci/ojo/ui/SurveillanceFragment.java @@ -28,6 +28,7 @@ import java.util.Arrays; import java.util.List; import it.danieleverducci.ojo.R; +import it.danieleverducci.ojo.Settings; import it.danieleverducci.ojo.databinding.FragmentSurveillanceBinding; import it.danieleverducci.ojo.entities.Camera; @@ -70,18 +71,19 @@ public class SurveillanceFragment extends Fragment implements MediaPlayer.EventL // Start stream on surface view 1 + Settings settings = Settings.fromDisk(getContext()); + List cc = settings.getCameras(); - - List cc = new ArrayList<>(); - String rtspUrl = "rtsp://admin:Du4gdtPmXGCWT29@192.168.1.200:554/Streaming/Channels/101"; - Camera camera = new Camera("Camera 1", rtspUrl); - cc.add(camera); - rtspUrl = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"; - camera = new Camera("Bunny", rtspUrl); - cc.add(camera); - rtspUrl = "rtsp://demo:demo@ipvmdemo.dyndns.org:5541/onvif-media/media.amp?profile=profile_1_h264&sessiontimeout=60&streamtype=unicast"; - camera = new Camera("Ipvm Demo", rtspUrl); - cc.add(camera); +// List cc = new ArrayList<>(); +// String rtspUrl = "rtsp://admin:Du4gdtPmXGCWT29@192.168.1.200:554/Streaming/Channels/101"; +// Camera camera = new Camera("Camera 1", rtspUrl); +// cc.add(camera); +// rtspUrl = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"; +// camera = new Camera("Bunny", rtspUrl); +// cc.add(camera); +// rtspUrl = "rtsp://demo:demo@ipvmdemo.dyndns.org:5541/onvif-media/media.amp?profile=profile_1_h264&sessiontimeout=60&streamtype=unicast"; +// camera = new Camera("Ipvm Demo", rtspUrl); +// cc.add(camera); int elemsPerSide = calcGridSideElements(cc.size()); diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index 2b068d1..0000000 --- a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 07d5da9..0000000 --- a/app/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..8c276c2 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/layout/fragment_add_stream.xml b/app/src/main/res/layout/fragment_add_stream.xml index a2587d0..68b5ce4 100644 --- a/app/src/main/res/layout/fragment_add_stream.xml +++ b/app/src/main/res/layout/fragment_add_stream.xml @@ -1,28 +1,23 @@ - - - + android:text="@string/add_stream_placeholder_url"/>