diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/SCNApp.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/SCNApp.java index a487f97..51086d6 100644 --- a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/SCNApp.java +++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/SCNApp.java @@ -103,7 +103,7 @@ public class SCNApp extends Application implements LifecycleObserver ==TODO== [ ] - test notification channels - +[ ] - startup time [ ] - Delete single message (swipe right) [ ] - Query non-ack-ed messages in app [ ] - periodically get non-ack (option - even when not in-app) diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/BroadcastReceiverService.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/BroadcastReceiverService.java index 8181504..9a75b90 100644 --- a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/BroadcastReceiverService.java +++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/BroadcastReceiverService.java @@ -5,9 +5,12 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; +import com.blackforestbytes.simplecloudnotifier.view.MainActivity; + public class BroadcastReceiverService extends BroadcastReceiver { - public static final int STOP_NOTIFICATION_SOUND = 10022; + public static final int NOTIF_SHOW_MAIN = 10021; + public static final int NOTIF_STOP_SOUND = 10022; public static final String ID_KEY = "com.blackforestbytes.simplecloudnotifier.BroadcastID"; @Override @@ -18,12 +21,22 @@ public class BroadcastReceiverService extends BroadcastReceiver if (extras == null) return; int notificationId = extras.getInt(ID_KEY, 0); - if (notificationId == 10022) stopNotificationSound(); + if (notificationId == 0) return; + else if (notificationId == NOTIF_SHOW_MAIN) showMain(context); + else if (notificationId == NOTIF_STOP_SOUND) stopNotificationSound(); else return; } private void stopNotificationSound() { - SoundService.stopPlaying(); + SoundService.stop(); + } + + private void showMain(Context ctxt) + { + SoundService.stop(); + + Intent intent = new Intent(ctxt, MainActivity.class); + ctxt.startActivity(intent); } } diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/NotificationService.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/NotificationService.java index b1b4164..40df6ae 100644 --- a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/NotificationService.java +++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/NotificationService.java @@ -108,7 +108,7 @@ public class NotificationService case HIGH: ns = SCNSettings.inst().PriorityHigh; break; } - SoundService.playForegroundNoLooping(ns.EnableSound, ns.SoundSource, ns.ForceVolume, ns.ForceVolumeValue); + SoundService.play(ns.EnableSound, ns.SoundSource, ns.ForceVolume, ns.ForceVolumeValue, false); if (ns.EnableVibration) { @@ -162,7 +162,8 @@ public class NotificationService } } - private void showBackground_old(CMessage msg, Context ctxt, NotificationSettings ns, PriorityEnum prio) { + private void showBackground_old(CMessage msg, Context ctxt, NotificationSettings ns, PriorityEnum prio) + { NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(ctxt, getChannel(prio)); mBuilder.setSmallIcon(R.drawable.ic_bfb); mBuilder.setContentTitle(msg.Title); @@ -177,21 +178,32 @@ public class NotificationService if (ns.EnableVibration) mBuilder.setVibrate(new long[]{500}); if (ns.EnableLED) mBuilder.setLights(ns.LEDColor, 500, 500); - if (ns.EnableSound && !ns.SoundSource.isEmpty()) mBuilder.setSound(Uri.parse(ns.SoundSource), AudioManager.STREAM_NOTIFICATION); + if (ns.EnableSound && !ns.SoundSource.isEmpty() && !ns.RepeatSound) mBuilder.setSound(Uri.parse(ns.SoundSource), AudioManager.STREAM_NOTIFICATION); Intent intent = new Intent(ctxt, MainActivity.class); PendingIntent pi = PendingIntent.getActivity(ctxt, 0, intent, 0); mBuilder.setContentIntent(pi); NotificationManager mNotificationManager = (NotificationManager) ctxt.getSystemService(Context.NOTIFICATION_SERVICE); + if (ns.EnableSound && !ns.SoundSource.isEmpty() && ns.RepeatSound) + { + Intent intnt_stop = new Intent(SCNApp.getContext(), BroadcastReceiverService.class); + intnt_stop.putExtra(BroadcastReceiverService.ID_KEY, BroadcastReceiverService.NOTIF_STOP_SOUND); + PendingIntent pi_stop = PendingIntent.getBroadcast(SCNApp.getContext().getApplicationContext(), BroadcastReceiverService.NOTIF_STOP_SOUND, intnt_stop, 0); + mBuilder.addAction(new NotificationCompat.Action(-1, "Stop", pi_stop)); + mBuilder.setDeleteIntent(pi_stop); + + SoundService.play(ns.EnableSound, ns.SoundSource, ns.ForceVolume, ns.ForceVolumeValue, ns.RepeatSound); + } + Notification n = mBuilder.build(); - if (ns.EnableSound && !ns.SoundSource.isEmpty() && ns.RepeatSound) n.flags |= Notification.FLAG_INSISTENT; if (mNotificationManager != null) mNotificationManager.notify(0, n); } @RequiresApi(api = Build.VERSION_CODES.O) - private void showBackground_new(CMessage msg, Context ctxt, NotificationSettings ns, PriorityEnum prio) { + private void showBackground_new(CMessage msg, Context ctxt, NotificationSettings ns, PriorityEnum prio) + { NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(ctxt, getChannel(prio)); mBuilder.setSmallIcon(R.drawable.ic_bfb); mBuilder.setContentTitle(msg.Title); @@ -206,15 +218,9 @@ public class NotificationService if (msg.Priority == PriorityEnum.NORMAL) mBuilder.setPriority(NotificationCompat.PRIORITY_DEFAULT); if (msg.Priority == PriorityEnum.HIGH) mBuilder.setPriority(NotificationCompat.PRIORITY_HIGH); - if (ns.ForceVolume) - { - AudioManager aman = (AudioManager) SCNApp.getContext().getSystemService(Context.AUDIO_SERVICE); - int maxVolume = aman.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION); - aman.setStreamVolume(AudioManager.STREAM_MUSIC, (int)(maxVolume * (ns.ForceVolumeValue / 100.0)), 0); - } - - Intent intent = new Intent(ctxt, MainActivity.class); - PendingIntent pi = PendingIntent.getActivity(ctxt, 0, intent, 0); + Intent intnt_click = new Intent(SCNApp.getContext(), BroadcastReceiverService.class); + intnt_click.putExtra(BroadcastReceiverService.ID_KEY, BroadcastReceiverService.NOTIF_SHOW_MAIN); + PendingIntent pi = PendingIntent.getBroadcast(ctxt, 0, intnt_click, 0); mBuilder.setContentIntent(pi); NotificationManager mNotificationManager = (NotificationManager) ctxt.getSystemService(Context.NOTIFICATION_SERVICE); if (mNotificationManager == null) return; @@ -224,17 +230,13 @@ public class NotificationService if (ns.RepeatSound) { Intent intnt_stop = new Intent(SCNApp.getContext(), BroadcastReceiverService.class); - intnt_stop.putExtra(BroadcastReceiverService.ID_KEY, BroadcastReceiverService.STOP_NOTIFICATION_SOUND); - PendingIntent pi_stop = PendingIntent.getBroadcast(SCNApp.getContext().getApplicationContext(), BroadcastReceiverService.STOP_NOTIFICATION_SOUND, intnt_stop, 0); + intnt_stop.putExtra(BroadcastReceiverService.ID_KEY, BroadcastReceiverService.NOTIF_STOP_SOUND); + PendingIntent pi_stop = PendingIntent.getBroadcast(ctxt, BroadcastReceiverService.NOTIF_STOP_SOUND, intnt_stop, 0); mBuilder.addAction(new NotificationCompat.Action(-1, "Stop", pi_stop)); mBuilder.setDeleteIntent(pi_stop); + } - SoundService.playForegroundWithLooping(ns.EnableSound, ns.SoundSource, ns.ForceVolume, ns.ForceVolumeValue); - } - else - { - SoundService.playForegroundNoLooping(ns.EnableSound, ns.SoundSource, ns.ForceVolume, ns.ForceVolumeValue); - } + SoundService.play(ns.EnableSound, ns.SoundSource, ns.ForceVolume, ns.ForceVolumeValue, ns.RepeatSound); } Notification n = mBuilder.build(); diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/SoundService.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/SoundService.java index d6a079e..155eec1 100644 --- a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/SoundService.java +++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/service/SoundService.java @@ -1,66 +1,55 @@ package com.blackforestbytes.simplecloudnotifier.service; import android.content.Context; +import android.media.AudioAttributes; import android.media.AudioManager; import android.media.MediaPlayer; -import android.media.Ringtone; -import android.media.RingtoneManager; import android.net.Uri; -import android.os.Build; +import android.util.Log; import com.blackforestbytes.simplecloudnotifier.SCNApp; -import com.blackforestbytes.simplecloudnotifier.lib.android.ThreadUtils; import com.blackforestbytes.simplecloudnotifier.lib.string.Str; +import java.io.IOException; + public class SoundService { private static MediaPlayer mpLast = null; - public static void playForegroundNoLooping(boolean enableSound, String soundSource, boolean forceVolume, int forceVolumeValue) + public static void play(boolean enableSound, String soundSource, boolean forceVolume, int forceVolumeValue, boolean loop) { if (!enableSound) return; if (Str.isNullOrWhitespace(soundSource)) return; - stopPlaying(); + stop(); if (forceVolume) { AudioManager aman = (AudioManager) SCNApp.getContext().getSystemService(Context.AUDIO_SERVICE); - int maxVolume = aman.getStreamMaxVolume(AudioManager.STREAM_MUSIC); - aman.setStreamVolume(AudioManager.STREAM_MUSIC, (int)(maxVolume * (forceVolumeValue / 100.0)), 0); + int maxVolume = aman.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION); + aman.setStreamVolume(AudioManager.STREAM_NOTIFICATION, (int)(maxVolume * (forceVolumeValue / 100.0)), 0); } - MediaPlayer player = MediaPlayer.create(SCNApp.getMainActivity(), Uri.parse(soundSource)); - player.setLooping(false); - player.setOnCompletionListener( mp -> { mp.stop(); mp.release(); }); - player.setOnSeekCompleteListener(mp -> { mp.stop(); mp.release(); }); - player.start(); - mpLast = player; - } - - public static void playForegroundWithLooping(boolean enableSound, String soundSource, boolean forceVolume, int forceVolumeValue) - { - if (!enableSound) return; - if (Str.isNullOrWhitespace(soundSource)) return; - - stopPlaying(); - - if (forceVolume) + try { - AudioManager aman = (AudioManager) SCNApp.getContext().getSystemService(Context.AUDIO_SERVICE); - int maxVolume = aman.getStreamMaxVolume(AudioManager.STREAM_MUSIC); - aman.setStreamVolume(AudioManager.STREAM_MUSIC, (int)(maxVolume * (forceVolumeValue / 100.0)), 0); + MediaPlayer player = new MediaPlayer(); + player.setAudioAttributes(new AudioAttributes.Builder().setLegacyStreamType(AudioManager.STREAM_NOTIFICATION).build()); + player.setAudioStreamType(AudioManager.STREAM_NOTIFICATION); + player.setDataSource(SCNApp.getContext(), Uri.parse(soundSource)); + player.setLooping(loop); + player.setOnCompletionListener( mp -> { mp.stop(); mp.release(); }); + player.setOnSeekCompleteListener(mp -> { mp.stop(); mp.release(); }); + player.prepare(); + player.start(); + mpLast = player; + } + catch (IOException e) + { + Log.e("Sound::play", e.toString()); } - - MediaPlayer player = MediaPlayer.create(SCNApp.getMainActivity(), Uri.parse(soundSource)); - player.setLooping(true); - player.setOnCompletionListener( mp -> { mp.stop(); mp.release(); }); - player.setOnSeekCompleteListener(mp -> { mp.stop(); mp.release(); }); - player.start(); - mpLast = player; } - public static void stopPlaying() + public static void stop() { if (mpLast != null && mpLast.isPlaying()) { mpLast.stop(); mpLast.release(); mpLast = null; } } diff --git a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/SettingsFragment.java b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/SettingsFragment.java index c8c3401..cdb747d 100644 --- a/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/SettingsFragment.java +++ b/android/app/src/main/java/com/blackforestbytes/simplecloudnotifier/view/SettingsFragment.java @@ -2,6 +2,7 @@ package com.blackforestbytes.simplecloudnotifier.view; import android.content.Context; import android.graphics.Color; +import android.media.AudioAttributes; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.Ringtone; @@ -9,6 +10,7 @@ import android.media.RingtoneManager; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -32,6 +34,8 @@ import com.blackforestbytes.simplecloudnotifier.service.IABService; import org.jetbrains.annotations.NotNull; +import java.io.IOException; + import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import top.defaults.colorpicker.ColorPickerPopup; @@ -258,8 +262,8 @@ public class SettingsFragment extends Fragment implements MusicPickerListener if (mPlayers[idx] != null && mPlayers[idx].isPlaying()) { AudioManager aman = (AudioManager) SCNApp.getContext().getSystemService(Context.AUDIO_SERVICE); - int maxVolume = aman.getStreamMaxVolume(AudioManager.STREAM_MUSIC); - aman.setStreamVolume(AudioManager.STREAM_MUSIC, (int)(maxVolume * (volume / 100.0)), 0); + int maxVolume = aman.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION); + aman.setStreamVolume(AudioManager.STREAM_NOTIFICATION, (int)(maxVolume * (volume / 100.0)), 0); } } @@ -288,17 +292,32 @@ public class SettingsFragment extends Fragment implements MusicPickerListener if (Str.isNullOrWhitespace(src)) return; if (volume == 0) return; + Context ctxt = getContext(); + if (ctxt == null) return; + iv.setImageResource(R.drawable.ic_pause); AudioManager aman = (AudioManager) SCNApp.getContext().getSystemService(Context.AUDIO_SERVICE); - int maxVolume = aman.getStreamMaxVolume(AudioManager.STREAM_MUSIC); - aman.setStreamVolume(AudioManager.STREAM_MUSIC, (int)(maxVolume * (volume / 100.0)), 0); + int maxVolume = aman.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION); + aman.setStreamVolume(AudioManager.STREAM_NOTIFICATION, (int)(maxVolume * (volume / 100.0)), 0); - MediaPlayer player = mPlayers[idx] = MediaPlayer.create(getActivity(), Uri.parse(src)); - player.setLooping(false); - player.setOnCompletionListener( mp -> SCNApp.runOnUiThread(() -> { mp.stop(); iv.setImageResource(R.drawable.ic_play); mPlayers[idx]=null; mp.release(); })); - player.setOnSeekCompleteListener(mp -> SCNApp.runOnUiThread(() -> { mp.stop(); iv.setImageResource(R.drawable.ic_play); mPlayers[idx]=null; mp.release(); })); - player.start(); + MediaPlayer player = mPlayers[idx] = new MediaPlayer(); + player.setAudioAttributes(new AudioAttributes.Builder().setLegacyStreamType(AudioManager.STREAM_NOTIFICATION).build()); + player.setAudioStreamType(AudioManager.STREAM_NOTIFICATION); + + try + { + player.setDataSource(ctxt, Uri.parse(src)); + player.setLooping(false); + player.setOnCompletionListener( mp -> SCNApp.runOnUiThread(() -> { mp.stop(); iv.setImageResource(R.drawable.ic_play); mPlayers[idx]=null; mp.release(); })); + player.setOnSeekCompleteListener(mp -> SCNApp.runOnUiThread(() -> { mp.stop(); iv.setImageResource(R.drawable.ic_play); mPlayers[idx]=null; mp.release(); })); + player.prepare(); + player.start(); + } + catch (IOException e) + { + Log.e("SFRAG:play", e.toString()); + } } private void saveAndUpdate() @@ -336,7 +355,7 @@ public class SettingsFragment extends Fragment implements MusicPickerListener UltimateMusicPicker ump = new UltimateMusicPicker(); ump.windowTitle("Choose notification sound"); ump.removeSilent(); - ump.streamType(AudioManager.STREAM_ALARM); + ump.streamType(AudioManager.STREAM_NOTIFICATION); ump.ringtone(); ump.notification(); ump.alarm(); @@ -351,7 +370,7 @@ public class SettingsFragment extends Fragment implements MusicPickerListener UltimateMusicPicker ump = new UltimateMusicPicker(); ump.windowTitle("Choose notification sound"); ump.removeSilent(); - ump.streamType(AudioManager.STREAM_ALARM); + ump.streamType(AudioManager.STREAM_NOTIFICATION); ump.ringtone(); ump.notification(); ump.alarm(); @@ -366,7 +385,7 @@ public class SettingsFragment extends Fragment implements MusicPickerListener UltimateMusicPicker ump = new UltimateMusicPicker(); ump.windowTitle("Choose notification sound"); ump.removeSilent(); - ump.streamType(AudioManager.STREAM_ALARM); + ump.streamType(AudioManager.STREAM_NOTIFICATION); ump.ringtone(); ump.notification(); ump.alarm();