在android oreo中设备重启后PeriodicWorkRequest不起作用

Posted

技术标签:

【中文标题】在android oreo中设备重启后PeriodicWorkRequest不起作用【英文标题】:PeriodicWorkRequest not working after device reboot in android oreo 【发布时间】:2018-12-28 14:00:03 【问题描述】:

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

A 类通知将在每 24 小时后显示一次。 B 类通知将在每 7 天后显示一次。 C 类通知将在每 15 天后显示一次。

我使用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);

【问题讨论】:

你得到答案了吗。如果有,请发布。我也面临同样的问题 @Suresh 您找到解决方案了吗?请发布答案,因为我也面临同样的问题 确保您的应用没有进行电池优化,所有应用似乎都默认开启了电池优化github.com/googlecodelabs/android-workmanager/issues/… 【参考方案1】:

我已经尝试过这段代码并与我一起处理旧 API 和新 API: 此代码在设备重新启动时每 15 分钟执行一次服务(workmanager)。 对于 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;
    

如果您希望服务在应用打开时开始工作,这个 sn-p(在 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);

【讨论】:

WorkManager 已经在 Manifest 合并中请求 BOOT_COMPLETED。您不必自己声明此意图。【参考方案2】:

你打电话给getWorkManger().enqueue(showNotification)。相反,您应该将周期性工作加入队列,因为您的工作是周期性操作

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

【讨论】:

【参考方案3】:

我已经尝试过了,也适用于 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>

【讨论】:

【参考方案4】:

请在您的 android manifest 中添加以下权限

   <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

【讨论】:

为什么需要这个权限?【参考方案5】:

如果 PeriodicWorkRequest 在设备重启后无法正常工作,您可以通过执行以下步骤来解决此问题。

只需定义一个 BroadcastReceiver 并在 onReceive(-) 方法中安排您的 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

【讨论】:

~"WorkManager 在设备重启后无法真正工作。" 谁说的?它绝对有效。 @IgorGanapolsky 在你的情况下,它可能有效。你不认为没有投票可以质疑。似乎这是反复出现的问题。无论如何,我会检查的。也有可能,Android 人在较新版本的 WorkManager 中修复了这个问题【参考方案6】:

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

【讨论】:

以上是关于在android oreo中设备重启后PeriodicWorkRequest不起作用的主要内容,如果未能解决你的问题,请参考以下文章

我的 MainActivity 在使用 android 旧版本(例如 oreo)时滞后,但在最新版本中运行良好,如何解决?

Android - 前台在 Oreo 中不起作用。操作系统在一段时间后终止服务

如何在 Android 中设置持久/定期计划?

iOS8中设备旋转后的ViewController偏移量

Android Oreo 字体系列 NPE 崩溃

如何在 Android Oreo 中管理来自未知来源的安装?