小部件如何在 Android 中更新(使用 AlarmManager)

Posted

技术标签:

【中文标题】小部件如何在 Android 中更新(使用 AlarmManager)【英文标题】:How is widget being updated in Android(using AlarmManager) 【发布时间】:2021-11-04 11:23:34 【问题描述】:

我的应用程序使用了一个小部件,我想在一天中的特定时间获取更新。代码如下:

package com.apps.app;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.RemoteViews;

import com.snappydb.DB;
import com.snappydb.DBFactory;
import com.snappydb.SnappydbException;

import java.util.ArrayList;
import java.util.Calendar;

public class Widget extends AppWidgetProvider 

public static String ACTION_AUTO_UPDATE_WIDGET = "ACTION_AUTO_UPDATE_WIDGET";

@Override
public void onReceive(Context context, Intent intent) 
    super.onReceive(context, intent);

    if (ACTION_AUTO_UPDATE_WIDGET.equals(intent.getAction())) 
        Log.d("widget","received");
        onUpdate(context, AppWidgetManager.getInstance(context),
                AppWidgetManager.getInstance(context).getAppWidgetIds(new ComponentName(context, Widget.class)));
    


@Override
public void onDisabled(Context context) 
    super.onDisabled(context);
    Intent intent = new Intent(context, Widget.class);
    intent.setAction(ACTION_AUTO_UPDATE_WIDGET);
    AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    alarmMgr.cancel(PendingIntent.getBroadcast(context, 0, intent, 0));


@Override
public void onEnabled(Context context) 
    super.onEnabled(context);

    try 
        DB db = DBFactory.open(context, "notes");
        ArrayList <Note> noteArrayList = db.getObject("notes", ArrayList.class);
        for(Note note: noteArrayList) 
            setUpdateIntent(context, note.getHours(), note.getMinutes());
        
     catch (SnappydbException e) 
        e.printStackTrace();
    
    


private void setUpdateIntent(Context context, int h, int m) 
    Intent intent1 = new Intent(context, Widget.class);
    intent1.setAction(ACTION_AUTO_UPDATE_WIDGET);
    PendingIntent alarmIntent = PendingIntent.getBroadcast(context, h*m, intent1, 0);

    Calendar c = Calendar.getInstance();
    c.set(Calendar.HOUR_OF_DAY, h);
    c.set(Calendar.MINUTE, m);

    AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    alarmMgr.setRepeating(AlarmManager.RTC, c.getTimeInMillis(), AlarmManager.INTERVAL_DAY, alarmIntent);


@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) 
    super.onUpdate(context, appWidgetManager, appWidgetIds);
    for (int id : appWidgetIds) 
        updateWidget(context, appWidgetManager, id);
    


private void updateWidget(Context context, AppWidgetManager manager, int widgetId) 
    RemoteViews widgetView = new RemoteViews(context.getPackageName(), R.layout.widget);
    widgetView.setTextViewText(R.id.dateTextView, TimeManager.getDay());
    widgetView.setTextViewText(R.id.curTimeTextView, TimeManager.getTime());
    widgetView.setTextViewText(R.id.weatherTextView,
            context.getSharedPreferences("weather", Context.MODE_PRIVATE).getString("weather", "default"));

    Intent configIntent = new Intent(context, MainActivity.class);
    configIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
    configIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
    PendingIntent pIntent = PendingIntent.getActivity(context, widgetId, configIntent, 0);
    widgetView.setOnClickPendingIntent(R.id.layoutId, pIntent);

    manager.updateAppWidget(widgetId, widgetView);



根据 DB 的数据,它应该在 17:37、17:40 和 17:42 准确更新。 这是我的更新日志:

2021-09-07 17:38:31.518 6787-6787/com.apps.app D/widget: received
2021-09-07 17:38:31.547 6787-6787/com.apps.app D/widget: received
2021-09-07 17:42:52.078 6787-6787/com.apps.app D/widget: received
2021-09-07 17:42:52.092 6787-6787/com.apps.app D/widget: received

我真的不明白算法小部件的更新是基于什么的。谁能给我解释一下?

【问题讨论】:

你能分享整个类吗,它是从什么扩展而来的,等等? @DanielBeleza 刚刚编辑了问题 不是小部件更新引起的。事实上,警报是不准确的。 【参考方案1】:

如果您的应用程序希望允许交付时间漂移以保证警报之间始终至少经过一定的时间间隔,那么采取的方法是使用一次性警报,在处理时自己安排下一个每次报警。

从 API 19 开始,所有重复警报都是不准确的。如果您的应用程序需要精确的交付时间,那么它必须使用一次性精确警报,并如上所述重新安排每次。 targetSdkVersion 早于 API 19 的旧版应用程序将继续将其所有警报(包括重复警报)视为准确。

【讨论】:

以上是关于小部件如何在 Android 中更新(使用 AlarmManager)的主要内容,如果未能解决你的问题,请参考以下文章

屏幕打开/关闭时如何更新 Android 小部件?

如何每分钟更新一个 Android 应用小部件

如何更新导航抽屉中的有状态小部件,同时在 Android 中保持与片段相同的类?

Android小部件,如何在Android API <11中使用notifyAppWidgetViewDataChanged

强制 Android 小部件更新

如何在 android:updatePeriodMillis="0" 时从 Flutter 更新 Android 小部件?