在 Android Oreo 中,设备重新启动后 PeriodicWorkRequest 不起作用

16

我需要根据以下逻辑向用户推送应用程序通知。

  • 每24小时显示一次A类型的通知。
  • 每7天显示一次B类型的通知。
  • 每15天显示一次C类型的通知。

我已经使用PeriodicWorkRequest工作管理器,如下所示,它在设备未重启时运行良好。 设备重新启动后,我的工作未被触发。

build.gradle ---

implementation 'android.arch.work:work-runtime:1.0.0-alpha04'

Java代码

PeriodicWorkRequest showNotification =
                new PeriodicWorkRequest.Builder(ShowNotificationWorkManager.class, interval,
                        TimeUnit.HOURS)
                        .addTag(notificationType)
                        .setInputData(myData)
                        .build();

getWorkManger().enqueue(showNotification);

3
你有没有得到答案?如果是,请发布它。我也遇到了同样的问题。 - Suresh
@Suresh,你找到解决方案了吗?请发布答案,因为我也遇到了同样的问题。 - Pravinsingh Waghela
请确保您的应用程序未被电池优化,这似乎是所有应用程序默认开启的。 - lasec0203
7个回答

9

我已经尝试过这段代码,在旧的API和新的API上都可以使用: 这段代码在设备重新启动时每15分钟执行一次服务(工作管理器)。 适用于AndroidManifest.xml文件:

<receiver android:name=".WorkManagerStartReceiver" >
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
    </intent-filter>
</receiver>

关于WorkManagerStartReceiver类:

public class WorkManagerStartReceiver extends BroadcastReceiver {
    WorkManager mWorkManager;

    @Override
    public void onReceive(Context context, Intent intent) {

        PeriodicWorkRequest.Builder myWorkBuilder =
                new PeriodicWorkRequest.Builder(TestWorker.class,
                        PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS,
                        TimeUnit.MILLISECONDS);

        PeriodicWorkRequest myWork = myWorkBuilder.build();
        mWorkManager = WorkManager.getInstance(context);
        mWorkManager.enqueue(myWork);

    }
}

TestWorker.class是扩展Worker的类:

public class TestWorker extends Worker {

    public TestWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    @NonNull
    @Override
    public Result doWork() {

        //your work that you want to execute here
        return null;
    }
}

如果您希望在应用程序打开时服务开始运行,可以在MainActivity中使用以下代码片段:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    PeriodicWorkRequest.Builder myWorkBuilder =
            new PeriodicWorkRequest.Builder(TestWorker.class,
                                            PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS,
                                            TimeUnit.MILLISECONDS);
    PeriodicWorkRequest myWork = myWorkBuilder.build();
    WorkManager.getInstance(MainActivity.this)
            .enqueueUniquePeriodicWork("testworker", ExistingPeriodicWorkPolicy.KEEP, myWork);
}

4
WorkManager 已经在 Manifest 合并中请求了 BOOT_COMPLETED。您无需自己声明此意图。 - IgorGanapolsky

1

您调用了 getWorkManger().enqueue(showNotification)。相反,您应该将 周期性 工作加入队列,因为您的操作是一个 周期性操作

workManager = WorkManager.getInstance(this)
workManager.enqueueUniquePeriodicWork(
   WORKER_NAME, ExistingPeriodicWorkPolicy.KEEP, workRequest
 )

0

我已经尝试过这个方法,对HTC手机也有效。

<receiver android:name=".WorkManagerStartReceiver" android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
                <action android:name="android.intent.action.QUICKBOOT_POWERON"/>
            </intent-filter>
</receiver>

0
注意:在一些新版本的安卓系统中,启动完成意图受到保护,这意味着只有安卓系统才能调用或监听它。我目前遇到了这个问题,因为我想在启动完成后重启我的服务。它会抛出一个SecurityException异常。

-1
请在您的Android清单文件中添加以下权限
   <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

为什么需要这个权限? - IgorGanapolsky

-1
如果设备重启后PeriodicWorkRequest无法正常工作,您可以通过以下步骤解决此问题。 在onReceive(-)方法中定义BroadcastReceiver并安排您的WorKManager即可。
public class WorkManagerStartReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

    Constraints constraints = new Constraints.Builder()
            .setRequiresCharging(false)
            .build();

    PeriodicWorkRequest saveRequest =
            new PeriodicWorkRequest.Builder(ToastWorker.class, 15, TimeUnit.MINUTES)
                    .setConstraints(constraints)
                    .build();

    WorkManager.getInstance(context)
            .enqueue(saveRequest);
 } }

现在在 manifest.xml 文件中定义你的 BroadcastReceiver

<application
   ----
       >
    <activity android:name=".MainActivity"/>

    <receiver android:name=".WorkManagerStartReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
        </intent-filter>
    </receiver>

</application>

嘿,别忘了在你的清单文件中添加引导权限 android.permission.RECEIVE_BOOT_COMPLETED


1
“设备重启后,WorkManager 真的无法工作。” 谁这么说?它绝对可以正常工作。 - IgorGanapolsky
@IgorGanapolsky 可能在你的情况下有效。你不觉得问题的投票数似乎是一个反复出现的问题吗?无论如何,我会检查一下。另外,安卓开发人员可能已经在新版本的WorkManager中修复了这个问题。 - Ankit Dubey

-2
定期工作请求可以在应用程序首次在设备上启动时安排一次。我们可以使用共享首选项来识别应用程序是否是第一次启动。此外,为了在启动后重复执行工作,我们可以在广播接收器中启动工作,该接收器将在重新启动设备后触发。

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