Thursday, 16 May 2019

Android 8/9 Notification scheduling

I have tried to schedule notifications for a specific date and time, but on majority of devices it seems that the notifications are not showing up. Before android 9/8 I have used AlarmManager which was pretty easy to use and it worked but the last 2 versions of android have changed this...(thanks google for making everything easier...)
So, here is my code that I use to schedule the notification. I'm using OneTimeWorkRequest

tag = new AlertsManager(this).getCarId(nrInmatriculare);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

    Data inputData = new Data.Builder().putString("type", alarmType).putString("nrInmatriculare", nrInmatriculare).build();

    OneTimeWorkRequest notificationWork = new OneTimeWorkRequest.Builder(NotifyWorker.class)
            .setInitialDelay(calculateDelay(when), TimeUnit.MILLISECONDS)
            .setInputData(inputData)
            .addTag(String.valueOf(tag))
            .build();
    WorkManager.getInstance().enqueue(notificationWork);
}
else {
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, when, (24 * 60 * 60 * 1000), pendingIntent);
}

Then the class that I'm using to show the notification is this:

public class NotifyWorker extends Worker {

    public NotifyWorker(@NonNull Context context, @NonNull WorkerParameters params) {
        super(context, params);
    }

    @NonNull
    @Override
    public Worker.Result doWork() {
        // Method to trigger an instant notification


        new NotificationIntentService().showNotification(getInputData().getString("type"),getInputData().getString("nrInmatriculare"), getApplicationContext());

        return Worker.Result.SUCCESS;
        // (Returning RETRY tells WorkManager to try this task again
        // later; FAILURE says not to try again.)
    }
}

and this one :

public class NotificationIntentService extends IntentService {
    final Uri notificationSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    int alarmId = 0;


    public NotificationIntentService() {
        super("NotificationIntentService");
    }


    @Override
    protected void onHandleIntent(Intent intent) {
            showNotification(intent);
    }

    //show notification with workmanager
    public void showNotification(String type, String nrInmatriculare, Context context){
        try
        {
            if (!TextUtils.isEmpty(type) && !TextUtils.isEmpty(nrInmatriculare)) {

                AlertsManager alertsManager = new AlertsManager(context);
                Notifications notification = alertsManager.getAlertForCar(nrInmatriculare);
                String text ="";
                Calendar endDate = null;
                String date = notification.EndDate.get(Calendar.YEAR) + "-" + (notification.EndDate.get(Calendar.MONTH)/10==0 ? "0"+(notification.EndDate.get(Calendar.MONTH)+1) : (notification.EndDate.get(Calendar.MONTH))+1) + "-" + (notification.EndDate.get(Calendar.DAY_OF_MONTH)/10==0 ? "0"+notification.EndDate.get(Calendar.DAY_OF_MONTH) : notification.EndDate.get(Calendar.DAY_OF_MONTH));
                text = context.getString(R.string.notificationText).toString().replace("#type#", type.toUpperCase()).replace("#nrInmatriculare#", nrInmatriculare).replace("#date#", date ).replace("#days#", String.valueOf(new Utils().getDateDifferenceInDays(Calendar.getInstance(), notification.EndDate)));
                alarmId = alertsManager.getCarId(nrInmatriculare);
                endDate = (Calendar)notification.EndDate.clone();

                if (Calendar.getInstance().getTimeInMillis() > endDate.getTimeInMillis()){ //current time is after the end date (somehow the alarm is fired)
                }
                else {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                        //define the importance level of the notification
                        int importance = NotificationManager.IMPORTANCE_HIGH;
                        //build the actual notification channel, giving it a unique ID and name
                        NotificationChannel channel = new NotificationChannel("AppName", "AppName", importance);
                        //we can optionally add a description for the channel
                        String description = "A channel which shows notifications about events at Masina";
                        channel.setDescription(description);
                        //we can optionally set notification LED colour
                        channel.setLightColor(Color.MAGENTA);

                        // Register the channel with the system
                        NotificationManager notificationManager = (NotificationManager)context.
                                getSystemService(Context.NOTIFICATION_SERVICE);
                        if (notificationManager != null) {
                            notificationManager.createNotificationChannel(channel);
                        }

                        //---------

                        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "AppName");
                        builder.setContentTitle(context.getString(R.string.app_name));
                        builder.setContentText(text);
                        builder.setSmallIcon(R.mipmap.ic_launcher);
                        builder.setAutoCancel(true);
                        builder.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS);
                        builder.setLights(Color.CYAN, 1000, 2000);
                        builder.setPriority(NotificationCompat.PRIORITY_HIGH);
                        builder.setSound(notificationSound);
                        builder.setStyle(new NotificationCompat.BigTextStyle().bigText(text));
                        Intent notifyIntent = null;
                        if (type.equals("CarteDeIdentitate") || type.equals("PermisDeConducere"))
                            notifyIntent = new Intent(context, PersonalDataActivity.class);
                        else
                            notifyIntent = new Intent(context, DetailActivity.class);
                        notifyIntent.putExtra("car", new SharedPreference(context).getCarDetailString(nrInmatriculare));
                        // Create the TaskStackBuilder and add the intent, which inflates the back stack
                        TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
                        stackBuilder.addNextIntentWithParentStack(notifyIntent);
                        //PendingIntent pendingIntent = PendingIntent.getActivity(context, alarmId, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
                        PendingIntent pendingIntent = stackBuilder.getPendingIntent(alarmId, PendingIntent.FLAG_UPDATE_CURRENT);
                        //to be able to launch your activity from the notification
                        builder.setContentIntent(pendingIntent);

                        //trigger the notification
                        NotificationManagerCompat notificationAlert = NotificationManagerCompat.from(context);
                        notificationManager.notify(alarmId, builder.build());
                    }
                }
            }
            else
            {
                Log.d("here","No extra");
            }

        }
        catch(Exception ex)
        {
            Log.d("here","Error");
        }
    }

}

what am I doing wrong? there is a best and more efficient way of doing this?

EDIT: I would like to see an example about how to schedule a notification to a specific date + time, that really works.



from Android 8/9 Notification scheduling

No comments:

Post a Comment