Closed aykutuludag closed 10 months ago
Hi again! Before releasing new version of my app with v3.0.3 I notice something on Google Play.
It basically suggest switch to inExactAlarm which I used in the past in Native Android (java). Literally no difference between inExact and exact in most situations. In this way, you can reduce permissions in the manifest too. Also it is battery friendly method comparing exactAlarm.
To get rid of errors/crash on runtime, I found temporary solution. It asks scheduleExactAlarm permission to user Android >=14. If user won't give permission, app will crash most probably either setting alarms or receiving alarm intent.
// TEMPORARY
if (Platform.isAndroid && await Permission.scheduleExactAlarm.status.isGranted == false) {
await Permission.scheduleExactAlarm.request();
}
// TEMPORARY
Some early bug reports dropped to Firebase Crashlytics. This error is about vibration in older android versions.
Fatal Exception: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/os/VibrationEffect;
at com.gdelataillade.alarm.services.VibrationService.startVibrating(VibrationService.java:1)
at com.gdelataillade.alarm.alarm.AlarmService.onStartCommand(AlarmService.java)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3455)
at android.app.ActivityThread.-wrap21(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1651)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6351)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:896)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:786)
Bug seems to be appear on Android 5, 6 and 7.
Another bug only appear in Android >= 14.
java.lang.SecurityException: Starting FGS with type mediaPlayback
Fatal Exception: java.lang.RuntimeException: Unable to start service com.gdelataillade.alarm.alarm.AlarmService@efecfc5 with Intent { cmp=app.packagename/com.gdelataillade.alarm.alarm.AlarmService (has extras) }: java.lang.SecurityException: Starting FGS with type mediaPlayback callerApp=ProcessRecord{a25e887 31559:app.packagename/u0a351} targetSDK=34 requires permissions: all of the permissions allOf=true [android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK]
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:5089)
at android.app.ActivityThread.-$$Nest$mhandleServiceArgs()
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2458)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:222)
at android.os.Looper.loop(Looper.java:314)
at android.app.ActivityThread.main(ActivityThread.java:8663)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:565)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
My guess is adding following permission to manifest (addition to android.permission.FOREGROUND_SERVICE) may prevent this error.
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
Appear in Android 12, 13 and 14.
android.app.ForegroundServiceStartNotAllowedException: Service.startForeground() not allowed due to mAllowStartForeground false
Fatal Exception: java.lang.RuntimeException: Unable to start service com.gdelataillade.alarm.alarm.AlarmService@a4b147 with Intent { cmp=app.packagename/com.gdelataillade.alarm.alarm.AlarmService (has extras) }: android.app.ForegroundServiceStartNotAllowedException: Service.startForeground() not allowed due to mAllowStartForeground false: service app.packagename/com.gdelataillade.alarm.alarm.AlarmService
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:5248)
at android.app.ActivityThread.-$$Nest$mhandleServiceArgs()
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2444)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8741)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
This error may be related with previous one.
In some phones, notification is sending I saw it but after a few seconds notification disappear. It is cancelling notification by itself i dont know why. I encountered more than one phones. Happened in Android 14 and Android 9 but possibilitiy to encounter other versions, too.
In the beginning of the notification it is clearly see that it opens turn up of phone's sound (soundbar shown) and sound starting with notification. When notification ends, it is turn down the volume (soundbar shown again) and notification will disappear.
My alarm code is below. This code is calling after Alarm.init. I want to send notification and stayed it there. In iOS, it's working notification not disappear until user clicked or dismissed it. In Android, I guess it's not working all the time or all devices/versions. I'm still investigating but I saw this happen with my own eyes that notification is disappearing after a few seconds.
Future<void> createAlarm(int alarmId, DateTime dateTime, String title, String body) async {
final alarmSettings = AlarmSettings(
id: alarmId,
dateTime: dateTime,
assetAudioPath: 'assets/notification.mp3',
loopAudio: false,
vibrate: true,
volume: 1,
notificationTitle: title,
notificationBody: body,
enableNotificationOnKill: false,
);
await Alarm.set(alarmSettings: alarmSettings);
}
Hi @aykutuludag
Thanks again for this valuable feedback.
loopAudio
is false, when your audio provided by assetAudioPath
ends, I consider that alarm is finished then I stop it (which dismiss the notification). Maybe it's not the best I don't know. What is your use case ? What is the behavior you expect exactly ?Hi @gdelataillade
About your questions:
Extra: Also you are using gradle 7.x.x versions. Most plugins upgraded to gradle 8.x.x versions and transfer packagename variable in AndroidManifest.xml to gradle file. Normally it wont work, you cant run but I have a method to achieve that (https://stackoverflow.com/questions/76108428/how-do-i-fix-namespace-not-specified-error-in-android-studio/77738936#77738936) to handle your package because I'm using gradle 8.1.2. Not biggy, but my recommendation upgrade your gradle versions soon.
Extra2: Some developer may prefer (including me) to not provide assetAudioPath and prefer phone's default notification sound. Not a biggy but in future releases maybe you can include it. Have a nice day.
Best regards.
@aykutuludag Understood. I'll let you know when I'll make a new release. Thank you.
Owner
Thank you for your hard-work. I see that you released v3.0.4 but I desperately need last feature that is notifications should not auto dismissible/disappear. Currently user can't understand or see notifications. So I'm waiting v3.0.5 to release new version of my app and I will create bug file for that version, too.
Have a nice day.
Same issue about notification auto-dismiss: https://github.com/gdelataillade/alarm/issues/121
This issue is about setExactAlarm >>> https://github.com/gdelataillade/alarm/issues/102
This is about my suggestion above named as Extra2 https://github.com/gdelataillade/alarm/issues/84
Hi @aykutuludag
inexactAlarm
? You used it before ? For long durations ?3.0.5
with the android notification that stays even if loopAudio
is false. I did some research and it seems that there is no way to make persistent notifications on iOS.Extra 1: I'm having some trouble when upgrading to Gradle 8.x.x. Someone opened a PR #130 but I was not able to make alarm ring with this configuration. Also, when I increment Gradle version in my build.gradle
after updating my JDK, I have build errors.
Extra 2: I added a comment in the issue to answer your request: https://github.com/gdelataillade/alarm/issues/84#issuecomment-1892429045
Hi @aykutuludag
- Do you experience significant battery drain ? Are you sure about
inexactAlarm
? You used it before ? For long durations ?- Which one is the extra permission ?
- I just release version
3.0.5
with the android notification that stays even ifloopAudio
is false. I did some research and it seems that there is no way to make persistent notifications on iOS.Extra 1: I'm having some trouble when upgrading to Gradle 8.x.x. Someone opened a PR #130 but I was not able to make alarm ring with this configuration. Also, when I increment Gradle version in my
build.gradle
after updating my JDK, I have build errors.Extra 2: I added a comment in the issue to answer your request: #84 (comment)
Extra1: I will check it when I have a free time. But in general, use AGP (https://developer.android.com/build/agp-upgrade-assistant) it fix many problems automatically. Extra2: I read your code especially Android side. You are playing sound in service, showing notification in service etc. However, notification has default sound. I am adding some code in your NotificationService.kt at below:
notificationBuilder
.setSmallIcon(iconResId)
.setContentTitle(title)
.setContentText(body)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setCategory(NotificationCompat.CATEGORY_ALARM)
.setAutoCancel(false)
.setOngoing(true)
.setContentIntent(notificationPendingIntent)
.setSound(null)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
If you declare setSound like following (java code), we can use system's default notification sound.
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
builder.setSound(alarmSound);
There should be some equivalent code in iOS. Of course, some user prefer the sound they provide. If they didn't provide, use notification sound, if provide use that sound. I believe that this logic will work. Also it's a good habit setAutoCancel true at this scenerio because we are wanting close the notification either user clicked or dismissed. I didn't try it but I guess notification never dismissed now. Best regards.
PS: If you use the method above, you also don't need background MediaPlayback and related permissions, too.
PS2: https://github.com/gdelataillade/alarm/issues/54 this issue may be related with setLargeIcon. I'm sharing my java code which I used in Android to createNotification. Maybe that will help because I was able to see notification icon without problem.
private void generateNotification(Context context, int requestCode) {
Intent intentLauncher = new Intent(context, MainActivity.class);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
pIntent = PendingIntent.getActivity(context, 0, intentLauncher, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
} else {
pIntent = PendingIntent.getActivity(context, 0, intentLauncher, PendingIntent.FLAG_UPDATE_CURRENT);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelName = "Daily notification";
String channelDesc = "It notifies you about new reviews on a daily basis.";
NotificationChannel mChannel = new NotificationChannel(String.valueOf(0), channelName, NotificationManager.IMPORTANCE_HIGH);
mChannel.setDescription(channelDesc);
mChannel.enableVibration(true);
mChannel.setVibrationPattern(new long[]{500, 500, 500, 500});
notificationManager.createNotificationChannel(mChannel);
builder = new NotificationCompat.Builder(context, String.valueOf(0));
} else {
builder = new NotificationCompat.Builder(context);
}
notificationBuild(context, requestCode);
//Send notification
Notification notification = builder.build();
notificationManager.notify(0, notification);
}
private void notificationBuild(Context context, int requestCode) {
Bitmap bm = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
SimpleDateFormat sdf = new SimpleDateFormat("d MMMM yyyy EEEE", Locale.getDefault());
SimpleDateFormat sdfWeekly = new SimpleDateFormat("d MMMM", Locale.getDefault());
String notificationContext;
switch (requestCode) {
case 100:
default:
notificationContext = sdf.format(new Date()) + ": " + context.getString(R.string.dailyNotificationSuffix);
break;
case 200:
notificationContext = sdfWeekly.format(new Date()) + "-" + sdfWeekly.format(getDateWithOffset(7, new Date())) + ": " + context.getString(R.string.weeklyNotificationSuffix);
break;
}
builder.setContentTitle(context.getString(R.string.app_name))
.setContentText(notificationContext)
.setSmallIcon(R.mipmap.ic_launcher)
.setAutoCancel(true)
.setContentIntent(pIntent)
.setLargeIcon(bm)
.setSmallIcon(R.mipmap.ic_launcher)
.setVibrate(new long[]{500, 500, 500, 500});
}
PS3: The java code which create alarm daily 10am using InexactRepeating OR Inexact as one bullet alarm.
public static void createDailyAlarm(AlarmManager alarmManager, PendingIntent pendingIntent) {
Calendar currentTime = Calendar.getInstance();
int alarmHour = prefs.getInt("alarmHour", 10);
int alarmMinute = prefs.getInt("alarmMinute", 0);
Calendar calendar2 = Calendar.getInstance();
calendar2.set(Calendar.HOUR_OF_DAY, alarmHour);
calendar2.set(Calendar.MINUTE, alarmMinute);
if (currentTime.getTimeInMillis() < calendar2.getTimeInMillis()) {
alarmManager.setInexactRepeating(AlarmManager.RTC, calendar2.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
} else {
alarmManager.setInexactRepeating(AlarmManager.RTC, 1000 * 60 * 60 * 24 + calendar2.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
}
}
Final PS: These codes are not new/recent but the points I made above are still valid and solution of bugs are in there.
Now I'm releasing new version with 3.0.5 for Android. I will release new version for iOS when u fix the bugs. I suppose those bugs are still waiting to fix. Have a nice week.
Note: I can verify that there is no crash with your library right now in Android. Bugs are fixed, but feature and suggestions are waiting your interest.
Hey @aykutuludag
assetAudioPath
optional and use notification default sound if not provided. I just need to do some tests because Android's foreground service might be expecting some media playing, and something similar for iOS.Thank you so much for sharing your code and all this valuable feedback. I'll keep you updated. I'm mostly working alone on this project and during my free time, so that's why it can take some time for me to release new features and fixes. Have a nice week too !
Btw, Android app updated with Alarm 3.0.5 today. Only remaining error in android is following. I couldn't understand why it gives error:
Fatal Exception: java.lang.RuntimeException: Unable to start service com.gdelataillade.alarm.alarm.AlarmService@2b3568 with Intent { cmp=com.appname/com.gdelataillade.alarm.alarm.AlarmService (has extras) }: android.app.ForegroundServiceStartNotAllowedException: Service.startForeground() not allowed due to mAllowStartForeground false: service com.appname/com.gdelataillade.alarm.alarm.AlarmService
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:5261)
at android.app.ActivityThread.-$$Nest$mhandleServiceArgs()
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2447)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8762)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
Caused by android.app.ForegroundServiceStartNotAllowedException: Service.startForeground() not allowed due to mAllowStartForeground false: service com.appname/com.gdelataillade.alarm.alarm.AlarmService
at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:54)
at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:50)
at android.os.Parcel.readParcelableInternal(Parcel.java:4787)
at android.os.Parcel.readParcelable(Parcel.java:4755)
at android.os.Parcel.createExceptionOrNull(Parcel.java:3018)
at android.os.Parcel.createException(Parcel.java:3007)
at android.os.Parcel.readException(Parcel.java:2990)
at android.os.Parcel.readException(Parcel.java:2932)
at android.app.IActivityManager$Stub$Proxy.setServiceForeground(IActivityManager.java:6991)
at android.app.Service.startForeground(Service.java:743)
at com.gdelataillade.alarm.alarm.AlarmService.onStartCommand(AlarmService.java:152)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:5243)
at android.app.ActivityThread.-$$Nest$mhandleServiceArgs()
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2447)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8762)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
I couldn't see any error beside this. Thank you for your effort, have a nice day.
Note: I guess this error is about https://developer.android.com/develop/background-work/services/foreground-services. You added this permission to Manifest in previous versions, maybe it requires runtime request permission.
Btw, Android app updated with Alarm 3.0.5 today. Only remaining error in android is following. I couldn't understand why it gives error:
Fatal Exception: java.lang.RuntimeException: Unable to start service com.gdelataillade.alarm.alarm.AlarmService@2b3568 with Intent { cmp=com.appname/com.gdelataillade.alarm.alarm.AlarmService (has extras) }: android.app.ForegroundServiceStartNotAllowedException: Service.startForeground() not allowed due to mAllowStartForeground false: service com.appname/com.gdelataillade.alarm.alarm.AlarmService at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:5261) at android.app.ActivityThread.-$$Nest$mhandleServiceArgs() at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2447) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:226) at android.os.Looper.loop(Looper.java:313) at android.app.ActivityThread.main(ActivityThread.java:8762) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
Caused by android.app.ForegroundServiceStartNotAllowedException: Service.startForeground() not allowed due to mAllowStartForeground false: service com.appname/com.gdelataillade.alarm.alarm.AlarmService at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:54) at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:50) at android.os.Parcel.readParcelableInternal(Parcel.java:4787) at android.os.Parcel.readParcelable(Parcel.java:4755) at android.os.Parcel.createExceptionOrNull(Parcel.java:3018) at android.os.Parcel.createException(Parcel.java:3007) at android.os.Parcel.readException(Parcel.java:2990) at android.os.Parcel.readException(Parcel.java:2932) at android.app.IActivityManager$Stub$Proxy.setServiceForeground(IActivityManager.java:6991) at android.app.Service.startForeground(Service.java:743) at com.gdelataillade.alarm.alarm.AlarmService.onStartCommand(AlarmService.java:152) at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:5243) at android.app.ActivityThread.-$$Nest$mhandleServiceArgs() at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2447) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:226) at android.os.Looper.loop(Looper.java:313) at android.app.ActivityThread.main(ActivityThread.java:8762) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
I couldn't see any error beside this. Thank you for your effort, have a nice day.
Note: I guess this error is about https://developer.android.com/develop/background-work/services/foreground-services. You added this permission to Manifest in previous versions, maybe it requires runtime request permission.
This error occurring on Android 12, 13 and 14. I suppose this crash is about this: https://stackoverflow.com/a/70666991/4606368
I'm checking everything and releasing new version with 3.0.5 again. I updated flutter and dart sdk, too. I'm closing this issue now, if anything happens on new version, I will create new bug file for Android. For ios current bugs are still valid, no need to open new one. Kind regards.
Alarm plugin version v3.0.3
Describe the bug Native crash in Android
To Reproduce Nothing. Plugin implemented regularly.
Expected behavior Working without crash.
Screenshots In the comments