java - 使用 WorkManager 触发推送通知有一些延迟
问题描述
我正在做一个示例项目来练习背景工作。首先,我使用了 FirebaseJobDispatcher,一切都很好。然后我知道了 WorkManager,它是目前进行后台工作的最佳方式。
我的应用程序的想法是用户输入他希望在之后触发通知的分钟数,使用 FirebaseJobDispatcher 时立即触发通知,但是当我切换到 WorkManager 时,通知延迟了近 20 秒 +用户已经进入的时间.. 换句话说,如果用户将触发器设置为 1 分钟然后关闭应用程序,则在 Activity 销毁后 20 秒重新开始倒计时.. 意味着将在 1 后触发通知: 20分钟。
这是 MainActivity 中的代码(使用 WorkManager):
Data data = new Data.Builder()
.putInt("number", minutes*60)
.build();
OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(MyWorker.class)
.setInputData(data)
.addTag("timer")
.build();
WorkManager.getInstance(MainActivity.this).enqueue(oneTimeWorkRequest);
MainActivity(使用 FirebaseJobDispatcher)
JobSchedulerUtils.scheduleNotification(MainActivity.this, minutes);
下面是扩展Worker的java类:
public class MyWorker extends Worker {
public MyWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@NonNull
@Override
/*
this is a simulation for background work, a countdown starts at a given number and this number decrements every second.
the process runs off of the main thread.
*/
public Result doWork() {
// this is like an intent bundle, if you want to pass data from the activity to the Worker
// in this app, the passed int is the number where we start countdown
Data inputData = getInputData();
int number = inputData.getInt("number", -1);
for(int i = number; i >= 0; i--){
Log.d("logmsg", i+"");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
return Result.failure();
}
}
TriggerTasks.executeTask(getApplicationContext(), TriggerTasks.TRIGGER_NOTIFICATION);
return Result.success();
}
}
以下是使用 FirebaseJobDispatcher 时使用的类:
A- SchedulerFirebaseJobDispatcher.java
public class SchedulerFirebaseJobService extends JobService {
private AsyncTask mTask;
@Override
public boolean onStartJob(final JobParameters job) {
mTask = new AsyncTask() {
@Override
protected Object doInBackground(Object[] objects) {
// work to be done in background
Context context = SchedulerFirebaseJobService.this;
TriggerTasks.executeTask(context, TriggerTasks.TRIGGER_NOTIFICATION);
return null;
}
@Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
jobFinished(job, false);
}
};
mTask.execute();
return true;
}
@Override
public boolean onStopJob(JobParameters job) {
if (mTask != null) mTask.cancel(true);
return false;
}
}
B- JobSchedulerUtils.java
public class JobSchedulerUtils {
private static final String TRIGGER_NOTIFICATION_JOB_TAG = "trigger-notification";
synchronized public static void scheduleNotification(@NonNull final Context context, int time){
Driver driver = new GooglePlayDriver(context);
// TODO: use WorkManager instead of FirebaseJobDispatcher
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(driver);
// job is triggered in the service so we set service to SchedulerFirebaseJobService, but here we define the parameters of this job
// to be done in the background..
// in other words, services's doInBackground is triggered using the following parameters and after the event in setTrigger occurs
Job job = dispatcher.newJobBuilder().setService(SchedulerFirebaseJobService.class)
.setTag(TRIGGER_NOTIFICATION_JOB_TAG)
.setLifetime(Lifetime.FOREVER)
.setRecurring(false)
.setTrigger(Trigger.executionWindow(time*60, time*60))
.setReplaceCurrent(true)
.build();
dispatcher.schedule(job);
}
}
以下是这两种情况下使用的其余类:
A- TriggerTasks.java
public class TriggerTasks {
public static final String DISMISS_NOTIFICATION = "dismiss-notification";
public static final String TRIGGER_NOTIFICATION = "trigger-notification";
public static void executeTask(Context context, String action){
if(DISMISS_NOTIFICATION.equals(action)){
NotificationUtils.clearAllNotifications(context);
}
if(TRIGGER_NOTIFICATION.equals(action)){
NotificationUtils.createNotification(context);
}
}
}
B- NotificationUtils.java
public class NotificationUtils {
private static final String NOTIFICATION_CHANNEL_ID = "notif-channel";
private static final String NOTIFICATION_CHANNEL_NAME = "Primary";
private static final int PENDING_INTENT_ID = 1991;
private static final int NOTIFICATION_ID = 500;
private static final int ACTION_IGNORE_PENDING_INTENT_ID = 24;
public static void clearAllNotifications(Context context){
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancelAll();
}
public static void createNotification(Context context){
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel notificationChannel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_NAME,
NotificationManager.IMPORTANCE_HIGH
);
notificationManager.createNotificationChannel(notificationChannel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(context,NOTIFICATION_CHANNEL_ID);
builder.setAutoCancel(true)
.setContentText(context.getString(R.string.notification_text))
.setContentTitle(context.getString(R.string.notification_title))
// this attribute controls what happens when a notification is clicked
.setContentIntent(contentIntent(context))
.setSmallIcon(R.drawable.ic_launcher_background)
.addAction(dismissNotification(context));
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
}
notificationManager.notify(NOTIFICATION_ID, builder.build());
}
/*
guarantees that a click on the notification will start MainActivity
*/
private static PendingIntent contentIntent(Context context){
Intent toMainActivity = new Intent(context, MainActivity.class);
return PendingIntent.getActivity(
context,
PENDING_INTENT_ID,
toMainActivity,
PendingIntent.FLAG_UPDATE_CURRENT);
}
private static NotificationCompat.Action dismissNotification (Context context){
Intent intent = new Intent(context, TriggerIntentService.class);
intent.setAction(TriggerTasks.DISMISS_NOTIFICATION);
PendingIntent pendingIntent = PendingIntent.getService(
context,
ACTION_IGNORE_PENDING_INTENT_ID,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action dismissNotificationAction = new NotificationCompat.Action(
R.drawable.ic_launcher_foreground,
context.getString(R.string.notification_action_dismiss),
pendingIntent);
return dismissNotificationAction;
}
}
C-TriggerIntentService.java
public class TriggerIntentService extends IntentService {
public TriggerIntentService() {
super("TriggerIntentService");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
String action = intent.getAction();
TriggerTasks.executeTask(this, action);
}
}
解决方案
推荐阅读
- elasticsearch - 在 ElasticSearch 6.8.1 中过滤嵌套对象
- internet-explorer - 从 Internet Explorer 访问网络摄像头有问题
- autodesk-forge - AUTODESK FORGE BIM360 WEBHOOK ISSUES ROADMAP
- powershell - Overwrite and Append Csv output in PowerShell
- reference - 将客户 Jouney 参考传递到 Dynamics 365 Workflow
- android - How to create only one method OnClickListening and apply it for all my checkboxes in a fragment?
- docker - rsyslog未连接到docker中的elasticsearch
- javascript - 根据所选电台隐藏 div WooCommerce 购物车页面
- vue.js - Vuetify Tree-view --- 获取父节点和子节点
- selenium - 如何在 20 个请求硒刮后等待 30 秒