You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过推送通知更新Android Widget?Xamarin.Forms实现咨询

问题:收到Firebase推送时自动更新Android Widget(进程被杀时也生效)

我希望在收到推送通知时更新我的Android Widget(即使应用进程已被杀死),请问是否有可行的实现方式,还是只能通过点击Widget来更新?

目前我已在Xamarin.Forms项目中集成了Firebase推送通知,Android项目中的Application.cs代码如下:

using Android.App;
using Android.OS;
using Android.Runtime;
using Plugin.FirebasePushNotification;
using System;

namespace appslovo.Droid
{
    [Application]
    public class MainApplication : Application
    {
        public MainApplication(IntPtr handle, JniHandleOwnership transer) : base(handle, transer)
        {
        }

        public override void OnCreate()
        {
            base.OnCreate();

            //Set the default notification channel for your app when running Android Oreo
            if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
            {
                //Change for your default notification channel id here
              FirebasePushNotificationManager.DefaultNotificationChannelId = "FirebasePushNotificationChannel";

                //Change for your default notification channel name here
                FirebasePushNotificationManager.DefaultNotificationChannelName = "New posts";
                
               FirebasePushNotificationManager.DefaultNotificationChannelImportance = NotificationImportance.Max;
            }

            //If debug you should reset the token each time.
#if DEBUG
           // FirebasePushNotificationManager.Initialize(this, true);
#else
            FirebasePushNotificationManager.Initialize(this, false);
#endif

            //Handle notification when app is closed here
            CrossFirebasePushNotification.Current.OnNotificationReceived += (s, p) =>
           {

// *??????probably i need to write something there?????????*
           };
        }
    }
}

另外,我在Android文件夹中有Widget.cs文件(默认通过点击更新):

using System;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Android.App;
using Android.Appwidget;
using Android.Content;
using System.Configuration;
using System.IO;
using Xamarin.Essentials;
using Android.Runtime;
using Android.Content.PM;
using System.Collections.Specialized;
using Android.Widget;
using System.ComponentModel;
using System.Text.RegularExpressions;

namespace appslovo.Droid
{

    [BroadcastReceiver(Label = "Widget", Exported =true)]
    [IntentFilter(new string[] { "android.appwidget.action.APPWIDGET_UPDATE" })]
    [IntentFilter(new string[] { "android.intent.action.BOOT_COMPLETED" })]
    [IntentFilter(new[] { Intent.ActionTimeTick })]
    [IntentFilter(new[] { Intent.ActionApplicationRestrictionsChanged })]
    [IntentFilter(new string[] { "android.intent.action.TIME_CHANGED" })]
    
    [IntentFilter(new [] { Intent.ActionAppError })]
    [MetaData("android.appwidget.provider", Resource = "@xml/appwidgetprovider")]
    public class AppWidget : AppWidgetProvider
    {
        public async override void OnUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
        {
            
                var me = new ComponentName(context_wdgt, Java.Lang.Class.FromType(typeof(AppWidget)).Name);
                appWidgetManager_wdgt.UpdateAppWidget(me, BuildRemoteViews(context_wdgt, appWidgetIds_wdgt, ss, nn, tt));
            
            
        }
...
}

我认为应该在CrossFirebasePushNotification.Current.OnNotificationReceived += (s, p) => {}中调用Widget的更新方法,但不知道具体如何实现。


解决方案

完全可以实现推送触发Widget更新,无需依赖点击操作,具体步骤如下:

1. 给Widget添加自定义更新广播Action

在AppWidget类的IntentFilter中添加一个自定义Action,用于触发Widget更新:

[BroadcastReceiver(Label = "Widget", Exported =true)]
[IntentFilter(new string[] { "android.appwidget.action.APPWIDGET_UPDATE" })]
// 保留原有其他IntentFilter...
// 添加自定义更新Action
[IntentFilter(new string[] { "com.appslovo.droid.UPDATE_WIDGET" })]
[MetaData("android.appwidget.provider", Resource = "@xml/appwidgetprovider")]
public class AppWidget : AppWidgetProvider
{
    // 定义常量方便全局调用
    public const string UpdateWidgetAction = "com.appslovo.droid.UPDATE_WIDGET";
    // ...
}

2. 在Firebase推送回调中发送自定义广播

在MainApplication的OnNotificationReceived事件中,发送自定义广播触发Widget更新:

CrossFirebasePushNotification.Current.OnNotificationReceived += (s, p) =>
{
    // 创建触发Widget更新的Intent
    var updateIntent = new Intent(AppWidget.UpdateWidgetAction);
    updateIntent.SetPackage(PackageName); // 指定包名,确保广播仅发给自身App,避免被系统拦截
    // 发送广播
    SendBroadcast(updateIntent);
};

3. 在Widget中处理自定义广播

重写AppWidgetProvider的OnReceive方法,判断广播Action并执行更新逻辑:

public override void OnReceive(Context context, Intent intent)
{
    base.OnReceive(context, intent);
    
    // 判断是否为自定义更新广播
    if (intent.Action == UpdateWidgetAction)
    {
        var appWidgetManager = AppWidgetManager.GetInstance(context);
        // 获取当前所有该Widget的实例ID
        var componentName = new ComponentName(context, Java.Lang.Class.FromType(typeof(AppWidget)).Name);
        int[] appWidgetIds = appWidgetManager.GetAppWidgetIds(componentName);
        
        // 调用OnUpdate执行更新
        OnUpdate(context, appWidgetManager, appWidgetIds);
    }
}

4. 修正Widget中OnUpdate的变量问题

你原代码中的context_wdgt、appWidgetManager_wdgt属于未定义变量,直接使用方法参数中的实例即可:

public async override void OnUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
    // 替换为你实际的BuildRemoteViews逻辑,确保参数正确
    var remoteViews = BuildRemoteViews(context, appWidgetIds, ss, nn, tt);
    var componentName = new ComponentName(context, Java.Lang.Class.FromType(typeof(AppWidget)).Name);
    appWidgetManager.UpdateAppWidget(componentName, remoteViews);
}

关键注意事项

  • Android 8.0+后台限制:必须通过SetPackage(PackageName)指定广播接收方,否则系统会拦截后台广播。
  • 推送优先级:确保Firebase推送消息设置为高优先级(priority: high),这样即使App进程被杀,系统也会唤醒App处理推送,进而触发Widget更新。
  • 权限说明:无需额外申请权限,因为我们发送的是应用内定向广播。

内容的提问来源于stack exchange,提问作者демид владимиров

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 14:32:44