如何解决定期通知不发送问题

时间:2019-07-19 08:08:40

标签: java android notifications android-workmanager periodic-task

我有一个带有按钮的小应用程序,用于激活定期通知(工作经理定期工作请求),每15分钟发送一次测试通知

当我按下按钮时,通知会立即发送,但仅发送一次。即使我等待20,30分钟或将时间设置为+1小时,也没什么

MainActivity:

private void initNotification() {

    sendNotifButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            enableNotification();
        }
    })

   private void enableNotification(){
    NotificationWorker.scheduleReminder();
}

通知工作者:

private SharedPreferences preferences;
private String notifMessage = "Notification numéro : ";
private int notifNumber = 1;
public static final int notif_id = 1;

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

@NonNull
@Override
public Result doWork() {
    preferences = getApplicationContext().getSharedPreferences("key", Context.MODE_PRIVATE);
    preferences.edit().putString("message", notifMessage).apply();
    preferences.edit().putInt("numero", notifNumber + 1).apply();

    sendNotification();

    return Result.success();
}

private void sendNotification() {
    String message = preferences.getString("message", null) + "" + preferences.getInt("numero", 50);
    NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext())
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle("title")
            .setContentText(message);

    Intent intent = new Intent(getApplicationContext(), MainActivity.class);

    PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);
    builder.setContentIntent(pendingIntent);

    NotificationManager manager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
    manager.notify(notif_id, builder.build());
}

public static void cancelReminder() {
    WorkManager instance = WorkManager.getInstance();
    instance.cancelAllWorkByTag("worker_tag");
}

public static void scheduleReminder() {
    PeriodicWorkRequest.Builder notificationWork = new PeriodicWorkRequest.Builder(NotificationWorker.class,
            15, TimeUnit.MINUTES)
            //Set network connected required to periodicWorkRequest
            .setConstraints(new Constraints.Builder()
                    .setRequiredNetworkType(NetworkType.CONNECTED).build());
    PeriodicWorkRequest request = notificationWork.build();

    WorkManager.getInstance().enqueueUniquePeriodicWork("worker_tag", ExistingPeriodicWorkPolicy.REPLACE , request);
}

}

此功能必须在更大的项目中实现,但我无法每15分钟发送一次通知

2 个答案:

答案 0 :(得分:0)

由于您有严格的时间间隔,因此在这种情况下,建议您使用AlarmManager而不是WorkManager。假设即使应用处于后台状态,您也希望显示这些通知,请尝试使用AlarmManager#setExactAndAllowWhileIdle方法。

答案 1 :(得分:0)

我对enqueUniquePeriodicWork(...)的作品也不太了解,但是一个简单的enque(...)在为我工作。
我还具有唯一性的附加要求,并且一次只能运行worker类的一个实例,因此我编写了这个小型单例类。以下代码:

  • 可以为某些工作人员MyWorker.class创建一个定期工作请求,该工作预定每15分钟不受限制地运行
  • 有一个方便的isMyWorkerRunning()方法,该方法可以返回您的工作者是否正在运行的天气。请注意,它将对enqueued,running or blocked state
  • 返回true
  • 在内部,它以自己的共享首选项将处于运行状态的工作人员的id保持不变,以处理插入和检查。并在删除时使用请求的唯一tag
public class WorkersHandler {
    private static WorkersHandler INSTANCE = null;
    private static final String TAG = "WorkersHandler";
    private static final String PREF_KEY_MY_WORKER = "my_Worker";

    private static final String TAG_WORKER_REQ = "Worker_req";

    private WorkManager workManagerObj;
    private SharedPreferences pref;
    private WorkersHandler(Context ctx) {
        Context appCtx = ctx.getApplicationContext();
        this.workManagerObj = WorkManager.getInstance(appCtx);

        String prefName = "WORKER_HANDLER";
        this.pref = ctx.getSharedPreferences(prefName, Context.MODE_PRIVATE);
    }
    public WorkersHandler getInstance(Context ctx) {
        if (INSTANCE == null) {
            INSTANCE = new WorkersHandler(ctx);
        }
        return INSTANCE;
    }

    public boolean isMyWorkerRunning() {
        boolean isRunning = false;

        UUID someWorkerID = getUUID(PREF_KEY_MY_WORKER);
        WorkInfo workInfo = getWorkInfoForWorker(someWorkerID);

        if (workInfo != null) {
            WorkInfo.State state = workInfo.getState();
            if (state == WorkInfo.State.RUNNING || state == WorkInfo.State.ENQUEUED || state == WorkInfo.State.BLOCKED) {
                isRunning = true;
            }
        }
        else {
            //do nothing, the  work request associated with the give uuid doesn't exist in androidOS
            // schedular. simply return false
        }

        return isRunning;
    }
    @Nullable private WorkInfo getWorkInfoForWorker(UUID uuid) {
        WorkInfo workInfo = null;
        try {
            workInfo = workManagerObj.getWorkInfoById(uuid).get();
        } catch (ExecutionException | InterruptedException e) {
            e.printStackTrace();
        }
        return workInfo;
    }
    private UUID getUUID(String key) {
        //will return uuid of either a previous Worker running, or a garbage uuid(if
        // preferences doesn't have a value
        String garbageID = UUID.randomUUID().toString();

        UUID generatedID = UUID.fromString(pref.getString(key, garbageID));

        return generatedID;
    }

    public void startMyWorkerSingleton() {
        if (isMyWorkerRunning()) {
            Log.e(TAG, "startSingleTonLogWorker: Worker already running, therefore return");
            //return;
        } else {
            PeriodicWorkRequest LogWorkerRequest = buildMyWorkerRequest();
            putUUID(PREF_KEY_MY_WORKER, LogWorkerRequest.getId());
            workManagerObj.enqueue(LogWorkerRequest);
        }
    }
    private PeriodicWorkRequest buildMyWorkerRequest() {
        Constraints.Builder constraintsBuilder = new Constraints.Builder()
                .setRequiresCharging(false)
                .setRequiredNetworkType(NetworkType.NOT_REQUIRED)
                .setRequiresBatteryNotLow(false)
                .setRequiresStorageNotLow(false);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            constraintsBuilder.setRequiresDeviceIdle(false);
        }

        return new PeriodicWorkRequest
                .Builder(LogsWorker.class, 15, TimeUnit.MINUTES)//<-- My workerclass. replace with yours
                .setConstraints(constraintsBuilder.build())
                .addTag(TAG_WORKER_REQ)
                .build();
    }
    private void putUUID(String key, UUID uuidString) {
        //will put uuid in prefs
        Log.e(TAG, "putUUID: called for key" + key + "with uuid string" + uuidString);
        pref.edit().putString(key, uuidString.toString()).apply();
    }

    public void  stopMyWorker(){
        Log.e(TAG, "stopPeriodicNotifierService: called" );
        workManagerObj.cancelAllWorkByTag(TAG_WORKER_REQ);
        putUUID(PREF_KEY_MY_WORKER, UUID.randomUUID());
    }



    }