thudugala / Plugin.LocalNotification

The local notification plugin provides a way to show local notifications from .Net MAUI and Xamarin Forms apps .
MIT License
401 stars 66 forks source link

Android.Util.AndroidException - java.lang.SecurityException #462

Closed LeoJHarris closed 4 months ago

LeoJHarris commented 6 months ago

Not sure if this is an issue on our end, maybe some missing configuration but having an issue on a Pixel 7 Pro running android OS 14:

java.lang.SecurityException: Caller ###### needs to hold android.permission.SCHEDULE_EXACT_ALARM or android.permission.USE_EXACT_ALARM to set exact alarms.

We already have one of these permissions in our app i.e. <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" /> and my understanding is only certain apps such as calendar apps should be using the permission USE_EXACT_ALARM so not sure why we are having the issue, its crashing the app when trying to set alarms and possibly on this call: SetExactAndAllowWhileIdle within NotificationServiceImpl.ShowLater (Plugin.LocalNotification.NotificationRequest request)

The fill stack trace is:

JniEnvironment+InstanceMethods.CallVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args)
JniPeerMembers+JniInstanceMethods.InvokeVirtualVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters)
AlarmManager.SetExactAndAllowWhileIdle (Android.App.AlarmType type, System.Int64 triggerAtMillis, Android.App.PendingIntent operation)
NotificationServiceImpl.ShowLater (Plugin.LocalNotification.NotificationRequest request)
NotificationServiceImpl.Show (Plugin.LocalNotification.NotificationRequest request)
INotificationScheduleService.ScheduleAlarmsAsync (XamApp.Models.Customer customer, XamApp.Models.CustomerOptions customerOptions, System.Int32 scheduledCount)
UserManagementService.fetchCustomerRelatedDataAsync (XamApp.Models.Customer customer, Xamarin.Essentials.PermissionStatus status)
UserManagementService.RetrieveCustomerDataAsync (System.Int64 customerId, System.Boolean staySignedIn, System.Boolean goToDoseReminders, System.Boolean goToMedications, System.Nullable`1[T] cartOrderTarget, System.Nullable`1[T] conversationTarget, System.Nullable`1[T] announcementTarget, System.Nullable`1[T] deepLinkToRetrieveEScript, System.Boolean shouldNavigateAfterLogin)
HomePageViewModel.refreshPageAsync (Prism.Navigation.INavigationParameters navigationParameters)
BaseAsyncCommand`2[TExecute,TCanExecute].ExecuteAsync (TExecute parameter)
SafeFireAndForgetExtensions.HandleSafeFireAndForget[TException] (System.Threading.Tasks.Task task, System.Boolean continueOnCapturedContext, System.Action`1[T] onException)
AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_0 (System.Object state)
SyncContext+<>c__DisplayClass2_0.<Post>b__0 ()
Thread+RunnableImplementor.Run ()
IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this)
JNINativeWrapper.Wrap_JniMarshal_PP_V (_JniMarshal_PP_V callback, System.IntPtr jnienv, System.IntPtr klazz)
java.lang.SecurityException: Caller ###### needs to hold android.permission.SCHEDULE_EXACT_ALARM or android.permission.USE_EXACT_ALARM to set exact alarms.
android.os.Parcel.createExceptionOrNull Parcel.java:3057
android.os.Parcel.createException Parcel.java:3041
android.os.Parcel.readException Parcel.java:3024
android.os.Parcel.readException Parcel.java:2966
android.app.IAlarmManager$Stub$Proxy.set IAlarmManager.java:311
android.app.AlarmManager.setImpl AlarmManager.java:1084
android.app.AlarmManager.setImpl AlarmManager.java:1044
android.app.AlarmManager.setExactAndAllowWhileIdle AlarmManager.java:1312
Caused by: android.os.RemoteException: Remote stack trace:
com.android.server.alarm.AlarmManagerService$5.set AlarmManagerService.java:2981
android.app.IAlarmManager$Stub.onTransact IAlarmManager.java:181
android.os.Binder.execTransactInternal Binder.java:1339
android.os.Binder.execTransact Binder.java:1275

Anybody else having this issue?

cagriy commented 5 months ago

Having exactly the same problem on a Pixel 6 physical device as well as a Pixel 7 emulator. Wondering if something has changed with .NET8

cagriy commented 5 months ago

In my case, the issue is resolved after adding USE_EXACT_ALARM, and it works on its own as well without SCHEDULE_EXACT_ALARM.

StevilKnevil commented 5 months ago

This is reproducible by creating a clean Maui project, and adding the following test function to App.xaml.cs. (Project attached in zip)

        protected async void TestNotifications()
        {
            if (await LocalNotificationCenter.Current.AreNotificationsEnabled() == false)
            {
                await LocalNotificationCenter.Current.RequestNotificationPermission();
            }

            var notification = new NotificationRequest
            {
                Schedule =
                {
                    NotifyTime = DateTime.Now.AddSeconds(60),
                    RepeatType = NotificationRepeat.TimeInterval,
                    NotifyRepeatInterval = TimeSpan.FromHours(6)
                }
            };

            [MauiApp1.zip](https://github.com/thudugala/Plugin.LocalNotification/files/13846174/MauiApp1.zip)
            await LocalNotificationCenter.Current.Show(notification);
        }

Note that the exception is thrown only if the app is set to not allow alarms and reminders in the app settings.

Note that building against the latest code on Master doesn't reproduce the problem, so it looks like this will be fixed in the next release.

Until then: either build against the source code rather than the nuget package, or use a try/catch to inform/lead users to allow Alarms & Reminders so that the SCHEDULE_EXACT_ALARMS permission is enabled.

   Android.Net.Uri uri = Android.Net.Uri.Parse("package:" + Android.App.Application.Context.ApplicationInfo.PackageName);  
    //https://developer.android.com/reference/android/provider/Settings#ACTION_REQUEST_SCHEDULE_EXACT_ALARM  
   Intent intent = new Intent(Android.Provider.Settings.ActionRequestScheduleExactAlarm, uri);  
   StartActivity(intent);
owenashurst commented 5 months ago

Having the same issue here #465.

The last release is quite old now, if master contains a fix for this, it'd be nice to have a new release soon. Google Play Developer Console is picking up on this issue for me which i'm concerned will halt my release to production.

LeoJHarris commented 5 months ago

@thudugala any update?

@cagriy

In my case, the issue is resolved after adding USE_EXACT_ALARM, and it works on its own as well without SCHEDULE_EXACT_ALARM.

Since that permission is a restricted permission, apps that request that restricted permission are subject to review and those that do not meet the acceptable use case criteria will be disallowed from publishing on Google Play. I think only alarm or calendar apps should have that permission.

LeoJHarris commented 5 months ago

@owenashurst The authors response or lack of is some what concerning, we have QA being put on hold until this can be resolved 😒

owenashurst commented 5 months ago

@LeoJHarris Interestingly on my shipped version of my app, I do get notifications scheduled for an exact datetime. I guess this is the USE_EXACT_ALARM permission you mentioned.

This is for my Pixel 7 Pro.

LeoJHarris commented 5 months ago

@owenashurst

Our manifest looks like this now, maybe similar to yours

xml

    <uses-permission android:name="android.permission.USE_EXACT_ALARM" />
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" android:maxSdkVersion="32" />

We don't encounter any crash anymore but the concern is when we publish onto the Playstore again whether they will scrutinize the app and this new permission, the app we develop schedules alarms for medications so seems like a good fit though since it also needs precise datetime

cagriy commented 4 months ago

As @LeoJHarris suggested, my app has been rejected by Google due to inappropriate use of USE_EXACT_ALARM :( Back to the drawing board.

cagriy commented 4 months ago

I may be wrong but in my case 11.0.1-preview01 seems to solve the problem. As it has been built from the latest master.

LeoJHarris commented 4 months ago

@cagriy I'm assuming your running a MAUI app? I don't think can 11.0.1-preview01 target Xamarin apps

VinShen commented 4 months ago

Hi,

Xamarin Forms App.

The Local Notification works properly on Android OS 10 to 14 with both USE_EXACT_ALARM and SCHEDULE_EXACT_ALARM. Without these permission Local Notification works for OS <=12 Local Notification does not work for OS >= 13 without USE_EXACT_ALARM Permission. Only SCHEDULE_EXACT_ALARM does not work.

The App has been rejected by Google due to inappropriate use of USE_EXACT_ALARM. Any suggestions please.

Thanks

cagriy commented 4 months ago

@VinShen , the code in master works fine without USE_EXACT_ALARM, is this something you can add to your project ? There is also nugget version 11.0.1-preview01, but it sounds like it is not possible to use it with Xamarin.

VinShen commented 4 months ago

Thanks @cagriy,

I am using Latest Nuget v10.1.8 with Xamarin Forms. Using only SCHEDULE_EXACT_ALARM permission in Manifest. I confirmed that LocalNotificationCenter.Current.Show(request) fails without USE_EXACT_ALARM permission for OS = 14

StackTrace

Samsung SM-G990E Verbose 8230 mono-stdout ### SetLocalNotification Catch Caller com.bright.droid needs to hold android.permission.SCHEDULE_EXACT_ALARM or android.permission.USE_EXACT_ALARM to set exact alarms. - at Java.Interop.JniEnvironment+InstanceMethods.CallVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue args) [0x0006e] in :0 at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeVirtualVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue parameters) [0x00036] in :0 at Android.App.AlarmManager.SetExactAndAllowWhileIdle (Android.App.AlarmType type, System.Int64 triggerAtMillis, Android.App.PendingIntent operation) [0x0005a] in <7340629091c14b6eb465e053dd50e2d0>:0 at Plugin.LocalNotification.Platforms.NotificationServiceImpl.ShowLater (Plugin.LocalNotification.NotificationRequest request) [0x000a4] in :0 at Plugin.LocalNotification.Platforms.NotificationServiceImpl.Show (Plugin.LocalNotification.NotificationRequest request) [0x00159] in :0 at Bright.App ViewModels.MapViewModel.c () [0x00189] in <50090c4ee1c113e1b9a0f9fd96c6baff>:0 --- End of managed Java.Lang.SecurityException stack trace ---

I also confirmed that LocalNotificationCenter.Current.Show(request) works properly with USE_EXACT_ALARM permission on same device. But Google rejects to publish.

Is code in master different from Nuget v10.1.8?

Thanks

VinShen commented 4 months ago

My Observation on above

For OS = 14, When I set SCHEDULE_EXACT_ALARM in Manifest. The permission is not granted to App.

Even when I try in MainActivity.cs { int REQUEST_SCHEDULE_EXACT_ALARM = 100; string[] reqestPermission = { "android.permission.SCHEDULE_EXACT_ALARM" }; ActivityCompat.RequestPermissions(this, reqestPermission, REQUEST_SCHEDULE_EXACT_ALARM); } Still android.permission.SCHEDULE_EXACT_ALARM is not granted to App.

When I manually Allow 'Alarms and Reaminder' from App Settings on device. The local notifications work.

How can I auto grant only android.permission.SCHEDULE_EXACT_ALARM to App for OS >= 13 ?

Am I missing something. Please guide.

Thanks

cagriy commented 4 months ago

@VinShen , you are right, OS >=13 does not allow Schedule Exact alarm by default. For me the code in the master solved this problem. Have you had a chance to try that ?

VinShen commented 4 months ago

@cagriy, The current master code is for .Net 8. My App is in Xamarin Forms. I did build and try https://github.com/thudugala/Plugin.LocalNotification/tree/v10.1.8/Source But the same thing observed for OS >=13. OS does not allow SCHEDULE_EXACT_ALARM and Google does not allow USE_EXACT_ALARM for non Calendar Apps. Thanks for support.

LeoJHarris commented 4 months ago

@thudugala could we get some input/direction if possible on this one regarding the state of the libray, thanks!

thudugala commented 4 months ago

@LeoJHarris @cagriy @owenashurst @StevilKnevil

The next version of the plugin only supports .Net Maui using .Net 8.

If there are no issues I can publish 11.0.1

The below change is not there in the current release.

image

LeoJHarris commented 4 months ago

@thudugala thanks for letting us know! πŸ‘ Sounds like we will need to accelerate faster to a MAUI migration.

thudugala commented 4 months ago

Xamarin support will be dropped May 1, 2024 by Microsoft

https://dotnet.microsoft.com/en-us/platform/support/policy/xamarin

LeoJHarris commented 4 months ago

@thudugala the problem is we have a first beta release of an app developed with Xamarin that must be done next month, whilst our migration is at about 80% completion, tight deadlines!! 😨

thudugala commented 4 months ago

@LeoJHarris hmm ok. I will release a Xamarin version tonight.

LeoJHarris commented 4 months ago

@thudugala wow that would be appreciated!!

thudugala commented 4 months ago

@LeoJHarris please try version 10.2.0-preview01

LeoJHarris commented 4 months ago

@thudugala I will check today, thank you!

LeoJHarris commented 4 months ago

@thudugala I am going to close this issue as our Xamarin App is working fine on 10.2.0-preview01 thank you very much for offering this final support for Xamarin Apps.

ckoziel commented 3 months ago

Leo, using the 10.2.0-preview01 do you include in the Android Manifest? Or is that not needed in the new version.

LeoJHarris commented 3 months ago

@ckoziel

Manifest changes are as below using 10.2.0-preview01

<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" android:maxSdkVersion="32" />
ckoziel commented 3 months ago

Thanks Leo. I was wondering in version 10.2.0-preview01 can you leave out completely: uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" android:maxSdkVersion="32" /

I know Elvin mentions in v11.1.0 Below permissions are optional now uses-permission android:name="android.permission.USE_EXACT_ALARM" / uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" /

LeoJHarris commented 3 months ago

@ckoziel I have not tried without uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" android:maxSdkVersion="32" @elvinthudugala might be able to answer this question though.

That being said we will probably drop our own reference to the above permission when we move to V11.1.0 if we don't need it.

ckoziel commented 3 months ago

I removed that reference using 10.2.0-preview01. I do not use either EXACT_ALARM entry in the Android Manifest. It seems to be working. I just want to make sure. I am using Xamarin.

Google is very strict on those entries when submitting your app.

thumbnail_image

LeoJHarris commented 3 months ago

If you have removed EXACT_ALARM permission because you dont need it and updated to V10.2.0-preview-01 then you should not have any more issues.

ckoziel commented 3 months ago

Leo,

Elvin mentioned that SCHEDULE_EXACT_ALARM does not need to be included in the manifest on V10.2.0-preview-01

thudugala commented 3 months ago

@cagriy

You don't need EXACT_ALARM in V10.2.0-preview-01.

ckoziel commented 3 months ago

@LeoJHarris Leo, using this permission, uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" android:maxSdkVersion="32"

Do you ask for permission from the user to use SCHEDULE_EXACT_ALRM if their device is above android 12 (API level 31)?

ckoziel commented 3 months ago

Here is what I found out after testing for scheduling exact alarms if anyone is interested. (Xamarin)

Android

v12, you do not need any manifest permissions as alarm manager is enabled by default.

v13, you need to include in the manifest (android:name="android.permission.SCHEDULE_EXACT_ALARM" android:maxSdkVersion="33")

v14 and above, you do not include anything in the manifest. The user needs to enable Alarms manually. So, you need to ask permission and redirect them to the Alarm Page.

Intent intent = new Intent(); intent.SetAction(Android.Provider.Settings.ActionRequestScheduleExactAlarm); intent.SetData(Android.Net.Uri.Parse("package:" + context.PackageName)); intent.AddFlags(ActivityFlags.NewTask);