经过一天疲惫的努力,我试图实现一个在后台运行的流程(甚至在关闭应用程序之后(并检查新的通知,我已经成功地结束了。我以为我即将成功结束
我有以下实现
引导接收器:-检查设备是否已打开以及用户是否已登录
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction()) && !getEmail(context).isEmpty()) {
startService(context);
}
}
}
utils:-启动/停止重复性活动(或在用户更改活动执行频率时重新启动(
public class utils {
private static final String TAG = "NotificationsChecker";
@SuppressLint("StaticFieldLeak")
public static NotificationsHelper notificationsHelper;
public static MutableLiveData<Boolean> newNotification = new MutableLiveData<>();
public static void startService(Context context) {
createNotificationsHelper(context);
if (newNotification == null || newNotification.getValue() == null) {
SQLiteData sqLiteData = new SQLiteData(context);
newNotification.setValue(sqLiteData.isUnreadNotification());
}
Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build();
PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(NotificationsWorker.class, getNotificationsFrequency(context), TimeUnit.MINUTES)
.addTag(TAG)
.setConstraints(constraints)
.build();
WorkManager.getInstance(context).enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.REPLACE, workRequest);
}
private static void createNotificationsHelper(Context context) {
notificationsHelper = new NotificationsHelper(context, APIUtils.getAPIService(), newNotifications -> {
if (newNotification != null && newNotification.getValue() != null && !newNotification.getValue()) {
newNotification.setValue(newNotifications);
if (newNotification.getValue() && !newNotification.hasActiveObservers())
showNotification(context, 1, "default_system_notification", "New notification", "There is new notification in Wedos app");
}
});
}
public static void stopService(Context context) {
WorkManager.getInstance(context).cancelAllWorkByTag(TAG);
Log.d("Notification service", "notification value is: " + newNotification.getValue());
}
public static void restartService(Context context) {
stopService(context);
startService(context);
}
public static void destroyService(Context context) {
stopService(context);
if (notificationsHelper != null)
notificationsHelper.destroy();
}
}
Worker-检查新通知
public class NotificationsWorker extends Worker {
public NotificationsWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
Log.d("Notifications worker", "Worker initiated");
}
@NonNull
@Override
public Result doWork() {
//if (notificationsHelper != null)
notificationsHelper.prepareAPI();
return Result.success();
}
}
NotificationsHelper-将notificationsHelper.prepareAPI()
的结果返回给utils
...
//API call
...
listener.onCheck(newNotifications); //depends on API result
问题是Worker在我关闭应用程序时返回以下内容:Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.package.example.ui.notifications.NotificationsHelper.prepareAPI()' on a null object reference
总体思路如下:
重新启动设备后,会检查用户是否登录。如果是,则会调用startService((方法,检查新的通知。
如果用户退出应用程序,则调用serviceDestroy((方法,该方法将取消PeriodicWorker并销毁NotificationsHelper(与SQLite数据库的连接等(
成功登录应用程序后,将调用startService((方法,该方法将创建新的NotificationHelper并再次启动PeriodicWorker。
如果用户更改了轮询新通知的频率,则会调用restartService((方法,从而重新启动PeriodicWorker。
如果应用程序没有运行(我使用hasActiveObserver((进行检查(,我将显示一个通知。
如果应用程序正在运行,我将什么都不做,因为
newNotification.observe((LifecycleOwner) context, aBoolean -> {
if (aBoolean) newNotificationPin.setVisibility(View.VISIBLE);
else newNotificationPin.setVisibility(View.GONE);
});
从每个活动或片段调用可视地指示是否存在未读通知的通知。
当然,newNotification变量仍然必须保持其设置状态,以正确地指示新通知(即,当在后台检测到未读通知并且我打开应用程序时,我必须看到有关未读通知的可视化信息(
感谢的帮助
"问题是Worker在我关闭应用程序时向我返回以下内容">
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.package.example.ui.notifications.NotificationsHelper.prepareAPI()' on a null object reference
如果在Worker完成之前关闭应用程序,然后再次启动应用程序,则会使用以前相同的Worker.id创建该Worker的新实例。发生这种情况时,将再次调用doWork。所以,如果那个家伙(NotificationsHelper(还没有创建,当Worker再次启动时,我们就会得到那个NPE。
Logcat:
2020-12-22 12:03:47.867 28181-28208/com.example.android D/Notifications worker: Worker initiated
2020-12-22 12:03:47.876 28181-28212/com.example.android D/Notifications worker: doWork initiated
2020-12-22 12:03:47.881 28181-28212/com.example.android D/Notifications worker: notificationsHelper is null
2020-12-22 12:03:47.882 28181-28211/com.example.android E/WM-WorkerWrapper: Work [ id=26e5ac17-51f0-4f38-9c61-ba29e76525cc, tags={ com.example.android.BackgroundService.NotificationsWorker, NotificationsChecker } ] failed because it threw an exception/error
java.util.concurrent.ExecutionException: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.android.ui.notifications.NotificationsHelper.prepareAPI()' on a null object reference
at androidx.work.impl.utils.futures.AbstractFuture.getDoneValue(AbstractFuture.java:516)
at androidx.work.impl.utils.futures.AbstractFuture.get(AbstractFuture.java:475)
at androidx.work.impl.WorkerWrapper$2.run(WorkerWrapper.java:298)
at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.android.ui.notifications.NotificationsHelper.prepareAPI()' on a null object reference
at com.example.android.BackgroundService.NotificationsWorker.doWork(NotificationsWorker.java:25)
at androidx.work.Worker$1.run(Worker.java:85)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
2020-12-22 12:03:47.884 28181-28211/com.example.android I/WM-WorkerWrapper: Worker result FAILURE for Work [ id=26e5ac17-51f0-4f38-9c61-ba29e76525cc, tags={ com.example.android.BackgroundService.NotificationsWorker, NotificationsChecker } ]
编辑:
设备重新启动后,如果有新的通知,Worker将运行并显示通知。在第二次运行时,notificationsHelper已为null。不与应用程序进行任何交互。