在Xamarin Forms中为Android使用Alarm Manager安排通知

9
  • 我创建了一个依赖项以显示通知

  • 在我的DeviceDetails_Droid.cs文件中,我设置了30秒的闹钟

  • 本地通知功能在应用程序处于活动状态时正常工作,但当我杀掉应用程序(关闭应用程序)时,闹钟接收器没有被调用。

public void ShowNotification(string message, string title)
{

Intent alarmIntent = new Intent(Forms.Context, typeof(AlarmReceiver));
alarmIntent.PutExtra ("message", message);
alarmIntent.PutExtra ("title", title);

    PendingIntent pendingIntent = PendingIntent.GetBroadcast(Forms.Context, 0, alarmIntent, PendingIntentFlags.UpdateCurrent);
    AlarmManager alarmManager = (AlarmManager) Forms.Context.GetSystemService(Context.AlarmService);

    //TODO: For demo set after 5 seconds.
    alarmManager.Set(AlarmType.RtcWakeup, DateTime.Now.Millisecond + 30000, pendingIntent);
}

在Android的MainActivity中
[BroadcastReceiver]
public class AlarmReceiver : BroadcastReceiver
{
    public override void OnReceive (Context context, Intent intent)
    {

        var message = intent.GetStringExtra ("message");
        var title = intent.GetStringExtra ("title");

        var notIntent = new Intent (context, typeof(MainActivity));
        var contentIntent = PendingIntent.GetActivity (context, 0, notIntent, PendingIntentFlags.CancelCurrent);
        var manager = NotificationManagerCompat.From (context);

        var style = new NotificationCompat.BigTextStyle();
        style.BigText(message);



        //Generate a notification with just short text and small icon
        var builder = new NotificationCompat.Builder (context)
            .SetContentIntent (contentIntent)
            .SetSmallIcon (Resource.Drawable.Icon)
            .SetContentTitle (title)
            .SetContentText (message)
            .SetStyle (style)
            .SetWhen (Java.Lang.JavaSystem.CurrentTimeMillis ())
            .SetAutoCancel (true);

        var notification = builder.Build();
        manager.Notify(0, notification);
    }
}

在清单文件中,
  • And in manifest file
<receiver 
 android:name=".AlarmReceiver" 
 android:enabled="true" 
 android:exported="true" 
 android:process=":remote" 
 android:label="AlarmReceiver">

  • 当应用程序处于运行状态时,上述代码可以完美运行。 但是,当应用程序关闭或被终止时,通知无法正常工作。

1
你需要实现后台服务,以便在应用程序被杀死或关闭后仍能正常工作。请参考此链接:https://dev59.com/L-o6XIcBkEYKwwoYKRLd#34207954。 - Janki Gadhiya
在清单文件中 <receiver android:name=".AlarmReceiver" android:enabled="true" android:exported="true" android:process=":remote" android:label="AlarmReceiver"> - user797725
2个回答

8

1) 如果有人杀死了您的应用程序,则已注册到您的应用程序的警报将被取消。

2) 为了注册您的警报或运行任何其他需要设置通知的代码,您可以在设备的启动时在后台启动服务...

  • 将"android.intent.action.BOOT_COMPLETED"添加到您的广播接收器中:

[BroadcastReceiver]
[IntentFilter(new string[]{"android.intent.action.BOOT_COMPLETED"}, Priority = (int)IntentFilterPriority.LowPriority)]
public class AlarmReceiver : BroadcastReceiver

在您的清单中添加启动完成权限:
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>    

在 Xamarin 的股票价格示例中,如果您设置了 "RECEIVE_BOOT_COMPLETED",则会自动重新启动您的服务,您将在手机重新启动时开始接收通知,而无需首先启动应用程序:

[BroadcastReceiver]
[IntentFilter(new string[]{StockService.StocksUpdatedAction,Boo "android.intent.action.BOOT_COMPLETED"}, Priority = (int)IntentFilterPriority.LowPriority)]
public class StockNotificationReceiver : BroadcastReceiver

3) 你可以使用 Service 而不是 SeviceIntent,并重写 StartCommandResult 返回 Sticky

使用基于 Sticky 的 Service,如果被终止,将会重新启动。

在 onStartCommand(Intent, int, int) 返回后,如果该服务的进程被杀死,则 Constant 将从该方法返回。此时服务仍处于已启动状态,但不保留传递的 intent。稍后系统将尝试重新创建服务。因为它处于已启动状态,所以系统会保证在创建新的服务实例后调用 onStartCommand(Intent, int, int);如果没有要传递给服务的等待中的启动命令,则会使用一个 null intent 对象调用它,因此您必须注意检查此项。

    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
        return StartCommandResult.Sticky;
    }

@SushiHangover,能否帮我们一个忙,编辑一下你回答中发布的问题,因为我想知道应该将依赖项放在哪个PCL类中。 - Lutaaya Huzaifah Idris
@LutaayaHuzaifahIdris,您是在谈论基于Xamarin.Forms的依赖服务吗?如果是,请发布一个新问题,因为该问题涉及到Xamarin.Android本地化,而所有这些代码都是在Xamarin.Android应用程序或库项目中编写的。 - SushiHangover
@SushiHangover,请帮我看一下这个问题:https://stackoverflow.com/questions/47052256/how-can-i-call-a-broadcastreceiver-inside-a-service-with-a-local-notification-x - Lutaaya Huzaifah Idris
@SushiHangover,我建议您编辑您的答案,并制作一个演示定时闹钟通知和粘性服务的教程,我将非常感激。 - Lutaaya Huzaifah Idris
@SushiHangover,我在MainActivity中调用**StartService()**时,应用程序会崩溃,你的答案有问题,请问为什么?我也不知道为什么。请查看以下链接:https://stackoverflow.com/questions/47092507/android-crashes-with-startservice-calling?noredirect=1# - user7615935
显示剩余3条评论

0

AlarmManager会在应用程序在前台或后台运行时工作。但是,当应用程序退出/强制停止/被杀死时,闹钟管理器也将被终止。只有在Android重新启动或应用程序再次由用户启动时,闹钟才会再次响起。请参考这些答案link1, link2


这还是现状吗?你分享的链接现在有点过时了。 - Stinky Towel
那么现有的闹钟应用程序是如何运作的呢?因为对于它们来说,无论被杀死多少次,它们仍然能够正常工作。 - user7615935

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接