Android 8/9 Notification scheduling

Try below code, i have used it in one of my application which works fine for me.

private void startWorkForWeekNotification() {
    OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(
        OpenAppNotifyWorker.class)
        .setInitialDelay(OpenAppNotifyWorker.NOTIFY_TO_OPEN_APP_IN_DAYS, TimeUnit.DAYS)
        .build();

    WorkManager.getInstance().beginUniqueWork(
        OpenAppNotifyWorker.WORKER_NAME,
        ExistingWorkPolicy.REPLACE,
        oneTimeWorkRequest).enqueue();
}

Worker Class

public class OpenAppNotifyWorker extends Worker {

public static final String WORKER_NAME = "OpenAppNotifyWorker";

public static final int NOTIFY_TO_OPEN_APP_IN_DAYS = 7;

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

@NonNull
@Override
public Result doWork() {
    NotificationUtils
        .showNotification(getApplicationContext(), NotificationUtils.UPDATE_CHANNEL_ID,
            NotificationUtils.UPDATE_NOTIFICATION_ID);
    return Result.success();
}

}

NotificationUtils Class

public class NotificationUtils {

public static final String UPDATE_CHANNEL_ID = "updates";

public static final int UPDATE_NOTIFICATION_ID = 1;

public static final int NOTIFICATION_REQUEST_CODE = 50;

public static void showNotification(Context context, String channelId, int notificationId) {
    createNotificationChannel(context, channelId);
    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
        context, channelId)
        .setSmallIcon(R.drawable.ic_splash_logo)
        .setContentTitle(context.getString(R.string.title_notification))
        .setContentText(context.getString(R.string.msg_body_notification))
        .setPriority(NotificationCompat.PRIORITY_DEFAULT);
    NotificationManagerCompat notificationManager = NotificationManagerCompat
        .from(context);
    notificationManager.notify(notificationId, mBuilder.build());
}

public static void createNotificationChannel(Context context, String channelId) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        //TODO change channel name and description
        CharSequence name = context.getString(R.string.notification_channel_updates);
        String description = context.getString(R.string.desc_notification_channel);
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel channel = new NotificationChannel(
            channelId, name, importance);
        channel.setDescription(description);
        NotificationManager notificationManager = context
            .getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
}

public static void createPushNotification(Context context, String message) {
    NotificationUtils
        .createNotificationChannel(context, NotificationUtils.UPDATE_CHANNEL_ID);
    Intent notificationIntent = new Intent(context, SplashActivity.class);
    notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    notificationIntent.setAction(Intent.ACTION_MAIN);
    notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
    notificationIntent.putExtra(FcmPushListenerService.EXTRAS_NOTIFICATION_DATA, message);
    PendingIntent contentIntent = PendingIntent
        .getActivity(context, NOTIFICATION_REQUEST_CODE, notificationIntent,
            PendingIntent.FLAG_UPDATE_CURRENT);

    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
        context, NotificationUtils.UPDATE_CHANNEL_ID)
        .setSmallIcon(R.drawable.ic_notification_app_logo)
        .setContentTitle(context.getString(R.string.app_name))
        .setContentText(message)
        .setAutoCancel(true)
        .setContentIntent(contentIntent)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT);
    NotificationManagerCompat notificationManager = NotificationManagerCompat
        .from(context);
    notificationManager.notify(NotificationUtils.UPDATE_NOTIFICATION_ID, mBuilder.build());
}

public static void cancelAllNotification(Context context) {
    NotificationManagerCompat notificationManager = NotificationManagerCompat
        .from(context);
    notificationManager.cancelAll();
}
}

if you want to start service you can do that by following :

public class OpenAppNotifyWorker extends Worker {

public static final String WORKER_NAME = "OpenAppNotifyWorker";

public static final int NOTIFY_TO_OPEN_APP_IN_DAYS = 7;

public Context context;

public OpenAppNotifyWorker(@NonNull Context context,
@NonNull WorkerParameters workerParams) {
    this.context = context
    super(context, workerParams);
}

@NonNull
@Override
public Result doWork() {

    context.startService(new NotificationIntentService())
    return Result.success();
}

}

Here is one working implementation that I've used in one of my project.

Add this to your build.gradle (app) (Since it's in Kotlin)

//android-jet pack
implementation 'android.arch.work:work-runtime-ktx:1.0.1'

or using Android X:

implementation "androidx.work:work-runtime-ktx:2.5.0"

https://developer.android.com/jetpack/androidx/releases/work

Create a method scheduleNotification. Pass your necessary data

fun scheduleNotification(timeDelay: Long, tag: String, body: String) {

    val data = Data.Builder().putString("body", body)

    val work = OneTimeWorkRequestBuilder<NotificationSchedule>()
                .setInitialDelay(timeDelay, TimeUnit.MILLISECONDS)
                .setConstraints(Constraints.Builder().setTriggerContentMaxDelay(Constant.ONE_SECOND, TimeUnit.MILLISECONDS).build()) // API Level 24
                .setInputData(data.build())
                .addTag(tag)
                .build()

    WorkManager.getInstance().enqueue(work)
}

NotificationSchedule Class

class NotificationSchedule (var context: Context, var params: WorkerParameters) : Worker(context, params) {

    override fun doWork(): Result {
        val data = params.inputData
        val title = "Title"
        val body = data.getString("body")

        TriggerNotification(context, title, body)

        return Result.success()
    }
}

TriggerNotification Class. Customize this class according to your need

class TriggerNotification(context: Context, title: String, body: String) {

init {
    sendNotification(context, title, body)
}

private fun createNotificationChannel(context: Context, name: String, description: String): String {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is new and not in the support library
    val chanelId = UUID.randomUUID().toString()
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val importance = NotificationManager.IMPORTANCE_HIGH
        val channel = NotificationChannel(chanelId, name, importance)
        channel.enableLights(true)
        channel.enableVibration(true)
        channel.description = description
        channel.lightColor = Color.BLUE
        channel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
       
        val notificationManager = context.getSystemService(NotificationManager::class.java)
        notificationManager?.createNotificationChannel(channel)
    }

    return chanelId
}

private fun sendNotification(context: Context, title: String, body: String) {

    val notificationManager = NotificationManagerCompat.from(context)
    val mBuilder = NotificationCompat.Builder(context, createNotificationChannel(context, title, body))
    val notificationId = (System.currentTimeMillis() and 0xfffffff).toInt()

    mBuilder.setDefaults(Notification.DEFAULT_ALL)
            .setTicker("Hearty365")
            .setContentTitle(title)
            .setContentText(body)
            .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setSmallIcon(R.drawable.icon)
            .setContentInfo("Content Info")
            .setAutoCancel(true)

    notificationManager.notify(notificationId, mBuilder.build())
}


}