Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/226.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何在OREO中更新小部件(AlarmManager在几小时/几天后停止)_Android_Widget_Android Widget_Alarmmanager_Android 8.0 Oreo - Fatal编程技术网

Android 如何在OREO中更新小部件(AlarmManager在几小时/几天后停止)

Android 如何在OREO中更新小部件(AlarmManager在几小时/几天后停止),android,widget,android-widget,alarmmanager,android-8.0-oreo,Android,Widget,Android Widget,Alarmmanager,Android 8.0 Oreo,我有一个信息小部件,每60秒更新一次。在OREO之前,我是使用服务完成的,但是现在,你不能这样做,因为当应用程序在后台时,你不能使用服务,所以我在这里发布了一些帖子,并使用alarm and AlarmManager来更新小部件 问题是它工作了几个小时,但在一两天内,不再调用报警的onReceive方法。由于警报停止而用户未删除小部件,因此wiget停止更新,因此发生了一些情况 看来AlarmManager不是最好的方法,或者我做错了什么 这是我的小部件报警接收器: public class W

我有一个信息小部件,每60秒更新一次。在OREO之前,我是使用服务完成的,但是现在,你不能这样做,因为当应用程序在后台时,你不能使用服务,所以我在这里发布了一些帖子,并使用alarm and AlarmManager来更新小部件

问题是它工作了几个小时,但在一两天内,不再调用报警的onReceive方法。由于警报停止而用户未删除小部件,因此wiget停止更新,因此发生了一些情况

看来AlarmManager不是最好的方法,或者我做错了什么

这是我的小部件报警接收器:

public class WidgetAlarmReceiver extends BroadcastReceiver {
    private final static String TAG = "WidgetAlarmReceiver";

    @Override
    public void onReceive(final Context context, Intent intent) {
        Log.d(TAG,"onReceive");

        ComponentName componentName = new ComponentName(context, AppWidget.class);
        RemoteViews remoteViews = WidgetHelper.getInstance().generateRemoteViews(context);

        AppWidgetManager.getInstance(context).updateAppWidget(componentName, remoteViews);
    }
}
这是启动警报的小部件的源代码:

public class AppWidget extends AppWidgetProvider {
    private AlarmManager alarmMgr;
    private PendingIntent alarmIntent;

static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
    RemoteViews remoteViews = WidgetHelper.getInstance().generateRemoteViews(context);
    appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    for (int appWidgetId : appWidgetIds) {
        updateAppWidget(context, appWidgetManager, appWidgetId);
    }
}

private void startWidgetAlarm(Context context){
    alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context, WidgetAlarmReceiver.class);
    intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
    alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
    alarmMgr.setInexactRepeating(AlarmManager.RTC, System.currentTimeMillis(), 60000, alarmIntent);
}

private void stopWidgetAlarm(Context context){
    alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context, WidgetAlarmReceiver.class);
    PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
    alarmMgr.cancel(sender);
}

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

@Override
public void onDisabled(Context context) {
    super.onDisabled(context);
    stopWidgetAlarm(context);
}
}
我的舱单部分:

<receiver android:name=".AppWidget">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>

    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/new_app_widget_info" />
</receiver>

<receiver android:name=".WidgetAlarmReceiver"  android:exported="false"/>

根据我的经验,最好使用一次性报警,并在触发后重新注册,因为对于重复报警,Android可能会认为您滥用了AlarmManager。。这就是我使用的方法:

void registerOneTimeAlarm(PendingIntent alarmIntent, long delayMillis, boolean triggerNow) {
    int SDK_INT = Build.VERSION.SDK_INT;
    long timeInMillis = (System.currentTimeMillis() + (triggerNow ? 0 : delayMillis));

    if (SDK_INT < Build.VERSION_CODES.KITKAT) {
        alarmManager.set(AlarmManager.RTC_WAKEUP, timeInMillis, alarmIntent);
    } else if (Build.VERSION_CODES.KITKAT <= SDK_INT && SDK_INT < Build.VERSION_CODES.M) {
        alarmManager.setExact(AlarmManager.RTC_WAKEUP, timeInMillis, alarmIntent);
    } else if (SDK_INT >= Build.VERSION_CODES.M) {
        alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timeInMillis, alarmIntent);
    }
}
void registerOneTimeAlarm(PendingEvent alarmIntent、long delayMillis、boolean triggerNow){
int SDK_int=Build.VERSION.SDK_int;
long-timeInMillis=(System.currentTimeMillis()+(triggerNow?0:delayMillis));
如果(SDK_INT

也许它也适用于您。

AlarmManager的一个缺点是,您必须在设备重新启动后重新注册,这可能就是您所经历的。您可以尝试使用JobScheduler==>@HedShafran无法使用它,因为我需要在与JobScheduler不兼容的较低设备中执行此操作。此外,设备没有重新启动,因此这不是警报停止的原因。您正在测试什么设备?@earthw0rmjim Nexus 5X更新为8。1@NullPointerException你找到解决办法了吗?我有同样的pb。安卓系统是一个令人头痛的问题。Dev并不真正关心向后兼容性。当设备处于休眠状态时更新小部件是没有意义的。因此,使用“setExact()”,您可以根据需要更改代码。。但方法才是最重要的……难道没有更好的方法来实现这一点吗?如果您想使用AlarmManager,这并不令人沮丧。。它用于报警,而不是每60秒执行一次任务。。我提供的方法应该是一个足够好的解决方案,这就是我在我的应用程序中所做的,以实现代码不多的跨版本重复任务。对于alarmmanager和API 14,我还有哪些不同的方法?