Meglali20
Meglali20

Reputation: 11

Android foreground service multiple notifications for same service

I have a RecyclerView which has on each holder a start button to start a countdown timer, I start the countdown timer in a foreground service so that the user can leave the app or do whatever he wants and be aware of the timer, each time I start a timer the onStartCommand is called I know the service can run only in one instance and the problem is that the text on the notification is messed up and updates randomly all the launched countdowns! When I call the service I put an extra for each call to set different notification channel id but it's the same thing I get only one notification. I need a separate notification for each countdown timer so the user can see/control each one individually.

@Override
public void onCreate() {
    super.onCreate();
    timerServiceInstance = this;
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            //  startForeground(requestCode, getMyActivityNotification("",completedParts,totalSize));
            startForeground(NOTIFICATION_ID, getNotification());
        }
    }, 1);
}



@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    NOTIFICATION_ID = intent.getIntExtra("foreGroundID", 1);
    CHANNEL_ID = "channel_" + NOTIFICATION_ID;
    long millisInput = intent.getLongExtra("time", 0);

    notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        CharSequence name = getString(R.string.app_name);

        NotificationChannel mChannel =
                new NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_DEFAULT);

        mChannel.setSound(null, null);
        mChannel.enableVibration(false);


        notificationManager.createNotificationChannel(mChannel);
    }
    setTime(millisInput);
    startTimer();


    return START_NOT_STICKY;
}


private void createNotificationChannel() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel serviceChannel = new NotificationChannel(
                CHANNEL_ID,
                "Foreground Service Channel",
                NotificationManager.IMPORTANCE_DEFAULT
        );
        serviceChannel.setSound(null, null);
        serviceChannel.enableVibration(false);
        NotificationManager manager = getSystemService(NotificationManager.class);
        manager.createNotificationChannel(serviceChannel);
    }
}

private void setTime(long milliseconds) {
    startTimeInMillis = milliseconds;
    resetTimer();
}

private void startTimer() {
    endTime = System.currentTimeMillis() + timeLeftInMillis;
    countDownTimer = new CountDownTimer(timeLeftInMillis, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            timeLeftInMillis = millisUntilFinished;
            updateCountDownText();
        }

        @Override
        public void onFinish() {
            timerRunning = false;
            updateWatchInterface();
        }
    }.start();
    timerRunning = true;
    updateWatchInterface();
}

private void pauseTimer() {
    countDownTimer.cancel();
    timerRunning = false;
    Paper.book().write("timerTimeLeft", timeLeftInMillis);
    pauseResumeButtonText = "Resume";
    updateWatchInterface();
}

private void resetTimer() {
    timeLeftInMillis = startTimeInMillis;
    updateCountDownText();
    updateWatchInterface();
}

private void updateCountDownText() {
    int hours = (int) (timeLeftInMillis / 1000) / 3600;
    int minutes = (int) ((timeLeftInMillis / 1000) % 3600) / 60;
    int seconds = (int) (timeLeftInMillis / 1000) % 60;

    timeLeftFormatted = String.format(Locale.getDefault(),
            "%02d:%02d:%02d", hours, minutes, seconds);

    // startForeground(NOTIFICATION_ID, getNotification());
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    if (mNotificationManager != null) {
        //Update the notification bar progress
        mNotificationManager.notify(NOTIFICATION_ID, getNotification());
    }
}

private void updateWatchInterface() {
    if (timerRunning) {
        pauseResumeButtonText = "Pause";
    } else {
        pauseResumeButtonText = "Resume";
        if (timeLeftInMillis == 0) {
            pauseResumeButtonText = "Done";
        }
        // startForeground(NOTIFICATION_ID, getNotification());
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        if (mNotificationManager != null) {
            //Update the notification bar progress
            mNotificationManager.notify(NOTIFICATION_ID, getNotification());
        }
    }
}

static public class MyReceiver extends BroadcastReceiver {


    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getStringExtra("action");

        System.out.println("ACTION CLICKED IS " + action);
        switch (action) {
            case PAUSE_RESUME_TIMER:
                if (timerServiceInstance.timerRunning) {
                    timerServiceInstance.pauseTimer();
                } else {
                    long millisInput = Paper.book().read("timerTimeLeft");
                    timerServiceInstance.setTime(millisInput);
                    timerServiceInstance.startTimer();
                }
                break;
            case STOP_TIMER:
                Paper.book().write("timerTimeLeft", 0);
                timerServiceInstance.stopSelf();
                break;
        }

    }

}

Upvotes: 1

Views: 3354

Answers (2)

Basu
Basu

Reputation: 763

This is how you can do it:

Intent intent = new Intent(getApplicationContext(), xyz.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);
        String channelId = Constant.CHANNEL_NAME_ALL;
        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder =
                new NotificationCompat.Builder(this, channelId)
                        .setSmallIcon(R.mipmap.ic_launcher)
                        .setContentTitle(title)
                        .setContentText(message)
                        .setAutoCancel(true)
                        .setSound(defaultSoundUri)
                        .setStyle(new NotificationCompat.BigTextStyle()
                                .bigText(expandedTitle))
                        .setPriority(NotificationCompat.PRIORITY_HIGH)
                        .setContentIntent(pendingIntent);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        try{
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                NotificationChannel channel = new NotificationChannel(channelId,
                        Constant.CHANNEL_DISTRICT_DATA,
                        NotificationManager.IMPORTANCE_HIGH);
                notificationManager.createNotificationChannel(channel);
            }
            Random rand = new Random();
            notificationManager.notify(rand.nextInt(10000) /* ID of notification */, notificationBuilder.build());
        } catch (Exception e){
            e.printStackTrace();
        }

The key here is using this code:

 Random rand = new Random();
            notificationManager.notify(rand.nextInt(10000) /* ID of notification */, notificationBuilder.build());

Sending notification using different ID result in the different notification and not same notification being updated.

[EDIT]

@Override
public void onCreate() {
    super.onCreate();
    timerServiceInstance = this;
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            //  startForeground(requestCode, getMyActivityNotification("",completedParts,totalSize));
            startForeground(NOTIFICATION_ID, getNotification());
        }
    }, 1);
}



@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    NOTIFICATION_ID = intent.getIntExtra("foreGroundID", 1);
    CHANNEL_ID = "channel_" + NOTIFICATION_ID;
    long millisInput = intent.getLongExtra("time", 0);

    notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        CharSequence name = getString(R.string.app_name);

        NotificationChannel mChannel =
                new NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_DEFAULT);

        mChannel.setSound(null, null);
        mChannel.enableVibration(false);


        notificationManager.createNotificationChannel(mChannel);
    }
    setTime(millisInput);
    startTimer(NOTIFICATION_ID);


    return START_NOT_STICKY;
}


private void createNotificationChannel() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel serviceChannel = new NotificationChannel(
                CHANNEL_ID,
                "Foreground Service Channel",
                NotificationManager.IMPORTANCE_DEFAULT
        );
        serviceChannel.setSound(null, null);
        serviceChannel.enableVibration(false);
        NotificationManager manager = getSystemService(NotificationManager.class);
        manager.createNotificationChannel(serviceChannel);
    }
}

private void setTime(long milliseconds) {
    startTimeInMillis = milliseconds;
    resetTimer();
}

private void startTimer(int N_ID) {
    endTime = System.currentTimeMillis() + timeLeftInMillis;
    countDownTimer = new CountDownTimer(timeLeftInMillis, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            timeLeftInMillis = millisUntilFinished;
            updateCountDownText(N_ID);
        }

        @Override
        public void onFinish() {
            timerRunning = false;
            updateWatchInterface(N_ID);
        }
    }.start();
    timerRunning = true;
    updateWatchInterface(N_ID);
}

private void pauseTimer(int N_ID) {
    countDownTimer.cancel();
    timerRunning = false;
    Paper.book().write("timerTimeLeft", timeLeftInMillis);
    pauseResumeButtonText = "Resume";
    updateWatchInterface(N_ID);
}

private void resetTimer(int N_ID) {
    timeLeftInMillis = startTimeInMillis;
    updateCountDownText(N_ID);
    updateWatchInterface(N_ID);
}

private void updateCountDownText(int N_ID) {
    int hours = (int) (timeLeftInMillis / 1000) / 3600;
    int minutes = (int) ((timeLeftInMillis / 1000) % 3600) / 60;
    int seconds = (int) (timeLeftInMillis / 1000) % 60;

    timeLeftFormatted = String.format(Locale.getDefault(),
            "%02d:%02d:%02d", hours, minutes, seconds);

    // startForeground(NOTIFICATION_ID, getNotification());
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    if (mNotificationManager != null) {
        //Update the notification bar progress
        mNotificationManager.notify(N_ID, getNotification());
    }
}

private void updateWatchInterface(int N_ID) {
    if (timerRunning) {
        pauseResumeButtonText = "Pause";
    } else {
        pauseResumeButtonText = "Resume";
        if (timeLeftInMillis == 0) {
            pauseResumeButtonText = "Done";
        }
        // startForeground(NOTIFICATION_ID, getNotification());
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        if (mNotificationManager != null) {
            //Update the notification bar progress
            mNotificationManager.notify(N_ID, getNotification());
        }
    }
}

static public class MyReceiver extends BroadcastReceiver {


    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getStringExtra("action");

        System.out.println("ACTION CLICKED IS " + action);
        switch (action) {
            case PAUSE_RESUME_TIMER:
                if (timerServiceInstance.timerRunning) {
                    timerServiceInstance.pauseTimer();
                } else {
                    long millisInput = Paper.book().read("timerTimeLeft");
                    timerServiceInstance.setTime(millisInput);
                    timerServiceInstance.startTimer();
                }
                break;
            case STOP_TIMER:
                Paper.book().write("timerTimeLeft", 0);
                timerServiceInstance.stopSelf();
                break;
        }

    }

}

Upvotes: 1

Murtadha S.
Murtadha S.

Reputation: 461

To display multiple notifications you should use multiple notifications IDs. not channel IDs.

i.e. The one you define here:

notificationManager.notify(NOTIFICATION_ID, notification)

Upvotes: -1

Related Questions