thudugala / Plugin.LocalNotification

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

[Android] Your app schedules exact alarms without checking whether the SCHEDULE_EXACT_ALARM permission has been granted. #465

Open owenashurst opened 10 months ago

owenashurst commented 10 months ago

Describe the bug When publishing release builds to the Google Play Developer Console, I found that it is showing me an error for the SCHEDULE_EXACT_ALARM permission. The exact error is:

Your app schedules exact alarms without checking whether the SCHEDULE_EXACT_ALARM permission has been granted. This is causing your app to crash for users on Android 14 because the permission is no longer granted by default.

In most cases, alternative methods of scheduling work or inexact alarms are more appropriate. If your use of exact alarms is justified, update your app so that it checks this permission is granted before scheduling.

The AndroidManifest has the permissions enabled outlined in the Wiki for this plugin, including the SCHEDULE_EXACT_ALARM permission. When testing via debug, I can see the notification that was scheduled fine (Google Pixel 5 emulator & My own Google Pixel 7 Pro).

I'm aware you can use Android specific namespaces to request this permission manually, however the issue is I am planning to also make a build for iOS, and from my experience prior to knowing about this plugin, I tried to create notifications via Intent, however the build would fail since iOS does not know about Android specific code. Even by conditionally registering an Android class via Dependency Injection with #if Android.

To Reproduce Steps to reproduce the behavior:

  1. Install Plugin.LocalNotifications
  2. Set a notification to appear by scheduling a DateTime.
  3. Publish the release to Google Play Console (Internal testing etc)
  4. See error

Expected behavior I should expect the plugin to have the ability to request missing permissions that it uses internally, instead of just one ability to Request Notification permissions.

Platform (please complete the following information):

Smartphone (please complete the following information):

vallgrenerik commented 9 months ago

Im also facing this! Did you @owenashurst find any solution? Ping @thudugala

owenashurst commented 9 months ago

Im also facing this! Did you @owenashurst find any solution? Ping @thudugala

Nope! I read a comment on another issue that a potential fix is in master. There needs to be a new release ideally. I tried cloning the code and including it in the project but I had all sorts of issues. Plus that didn't seem right to me.

thudugala commented 8 months ago

@owenashurst new releases are planned only to be release using .Net 8 Maui

also does not require

<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
owenashurst commented 8 months ago

@owenashurst new releases are planned only to be release using .Net 8 Maui

also does not require

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

Thanks for the reply @thudugala.

I'm already targeting .NET 8 since it's a relatively new app. Could you provide an estimate on when you plan to release the new version, please?

thudugala commented 8 months ago

@owenashurst can release new version, if you do not any issues with latest pre release version

owenashurst commented 8 months ago

@owenashurst can release new version, if you do not any issues with latest pre release version

@thudugala Just installed the pre-release, and it seems to still work fine (for android at least). I think you're good. I'm ready to deploy a new version of my app, so I'm happy to update once you release so I can publish.

Quick question, are you saying I can remove the following permissions after your release?

<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
thudugala commented 8 months ago

@owenashurst yes.

But please remember notification will not pop up at the exact time.

Try with the pre release

owenashurst commented 8 months ago

@owenashurst yes.

But please remember notification will not pop up at the exact time.

Try with the pre release

@thudugala My app doesn't need to be exact. As long as it shows the notification +- a few seconds and not minutes.

I've just tried with the above permissions removed and it was still relatively exact. Although this was inside an Android Emulator.

Does that mean it's good?

thudugala commented 8 months ago

@owenashurst yes.

owenashurst commented 8 months ago

@thudugala Brilliant. Looking forward to the release. Thank you.

thudugala commented 8 months ago

Will release tonight at about 10 pm New Zealand time

thudugala commented 8 months ago

@owenashurst Please try version 11.1.0

vallgrenerik commented 8 months ago

Thanks for the update @thudugala

In the Wiki you have:

[assembly: UsesPermission(Manifest.Permission.WakeLock)]

//Required so that the plugin can reschedule notifications upon a reboot
[assembly: UsesPermission(Manifest.Permission.ReceiveBootCompleted)]
[assembly: UsesPermission(Manifest.Permission.Vibrate)]
[assembly: UsesPermission("android.permission.POST_NOTIFICATIONS")]

optional
[assembly: UsesPermission("android.permission.USE_EXACT_ALARM")]
[assembly: UsesPermission("android.permission.SCHEDULE_EXACT_ALARM")]

Could you elaborate, when should we use the optional permissions and when should we avoid them? :)

thudugala commented 8 months ago

@vallgrenerik if you want notifications to fire at the exact time you need the optional permission.

andrea-torre commented 7 months ago

Hi, I'm having this problem too, in Google Play Console I can see the same warning for Android 14 that the original poster described. My App is developed with .net 7.0. It's not clear to me if I have to update to version 11.1.0 and .net 8.0 in order to solve the problem or if it is possible to deal with the permissions also without porting to .net 8.0. Thank you

alexsmi-noveo commented 7 months ago

For .NET8.0 Google Play fires me warning: "Your app schedules exact alarms without checking whether the SCHEDULE_EXACT_ALARM permission has been granted. This is causing your app to crash for users on Android 14 because the permission is no longer granted by default".

I was managed to request SCHEDULE_EXACT_ALARM permission (Android, API 31+) using android native classes (MainActivity.cs):

AlarmManager alarmManager = AlarmManager.FromContext(Platform.AppContext);
var isPermissionSet = alarmManager.CanScheduleExactAlarms();

if (!isPermissionSet)
{
    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);
}
Kebechet commented 6 months ago

Except the permissions in AndroidManifest consider adding AndroidNotificationPermission

private static NotificationPermission _notificationPermissions = new()
{
    Android = new AndroidNotificationPermission()
    {
        RequestPermissionToScheduleExactAlarm = true,
    }
};

and then call:

var areNotificationsEnabled = await notificationService.AreNotificationsEnabled(_notificationPermissions);

await notificationService.RequestNotificationPermission(_notificationPermissions);
erossini commented 5 months ago

I'm working on a NET8 MAUI app, I can't publish the app on Google Play because I get the same error that @owenashurst had. If I remove the SCHEDULE_EXACT_ALARM, the user can't accept the notifications (see this post).

Do you have any suggestions/ideas how can I fix it?

Kebechet commented 5 months ago

I had to remove USE_EXACT_ALARM because from android 14 this permission in not granted by default and Google allows it only for calendar and alarm apps.

So I kept SCHEDULE_EXACT_ALARM and asked for permissions with: https://github.com/thudugala/Plugin.LocalNotification/issues/465#issuecomment-2106834738

After that Google allowed our release.

But I still see the warning that for some of our users it can crash the app. I have no idea why because before every notification call we have permission check

erossini commented 5 months ago

I had to remove USE_EXACT_ALARM because from android 14 this permission in not granted by default and Google allows it only for calendar and alarm apps.

So I kept SCHEDULE_EXACT_ALARM and asked for permissions with: #465 (comment)

After that Google allowed our release.

But I still see the warning that for some of our users it can crash the app. I have no idea why because before every notification call we have permission check

Just to clarify for me. You kept in the AndroidManifest.xml the line

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

and then add the code in the code above. How did you define notificationService?

Kebechet commented 5 months ago

Just to clarify for me. You kept in the AndroidManifest.xml the line

yes

How did you define notificationService?

Here are some parts of my notification service + extension method I use for permissions:

INotificationServiceExtensions

public static class INotificationServiceExtensions
{
    private static NotificationPermission _notificationPermissions = new()
    {
        Android = new AndroidNotificationPermission()
        {
            RequestPermissionToScheduleExactAlarm = true,
        },
        IOS = new iOSNotificationPermission()
        {
            NotificationAuthorization =
                iOSAuthorizationOptions.Badge |
                iOSAuthorizationOptions.Sound |
                iOSAuthorizationOptions.Alert |
                iOSAuthorizationOptions.TimeSensitive
        },
    };

    public static async Task<bool> TryAllowNotifications(this INotificationService notificationService)
    {
        var areNotificationsEnabled = await notificationService.AreNotificationsEnabled(_notificationPermissions);
        if(!areNotificationsEnabled)
        {
            //return of this method doesnt give TRUE on iOS
            await notificationService.RequestNotificationPermission(_notificationPermissions);

            areNotificationsEnabled = await notificationService.AreNotificationsEnabled(_notificationPermissions);
        }

        return areNotificationsEnabled;
    }
}

NativeNotificationService

public class NativeNotificationService : IDisposable
{
    private const int _testNotificationId = 10;

    public NativeNotificationService()
    {
        LocalNotificationCenter.Current.NotificationActionTapped += OnNotificationActionTapped;
    }
    public async Task TriggerInstantTestNotification()
    {
        var areNotificationsAllowed = await LocalNotificationCenter.Current.TryAllowNotifications();
        if(!areNotificationsAllowed)
        {
            return;
        }

        var notification = new NotificationRequest
        {
            NotificationId = _testNotificationId,
            Title = "Test notification",
            Description = "Test notification description",
            CategoryType = NotificationCategoryType.Reminder,
            ReturningData = "your data",
        };

        await notification.Show();
    }

    public void Dispose()
    {
        LocalNotificationCenter.Current.NotificationActionTapped -= OnNotificationActionTapped;
    }

    private void OnNotificationActionTapped(NotificationActionEventArgs e)
    {
        if(e.IsDismissed)
        {
            return;
        }

        //handle notification action
    }
}
erossini commented 5 months ago

@Kebechet Thank you so much! Very useful!

erossini commented 5 months ago

When the app starts, the authorization page is displayed but I can't enable the alarms.

image

Kebechet commented 5 months ago

In my app I can enable those alarms. I have all these permissions enabled:

    <!--Required so that the plugin can reschedule notifications upon a reboot-->
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

    <!--Unlike USE_EXACT_ALARM , the SCHEDULE_EXACT_ALARM permission must be granted by the user-->
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />

otherwise I dunno what could be wrong with your implementation

Kebechet commented 3 months ago

After upgrading to the latest version of the library the error disappeared