• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Pusing notificaitons after app is killed

AsafKov

Newbie
Hi guys. I've been trying to make notifications for my calendar-planner project and I'm stuck for the past couple of days on an issue with no progress.
Thus far I have a notification publisher that works fine as long as the app is isn't removed from the recent tasks. Otherwise, the notifications will not be shown.
I tried searching online for answers but got no concrete answer for how it is supposed to work. What I did find simply doesn't work. The code:
Declaring the service in the manifest-
Code:
        <service android:name=".Helpers.NotificationService"
            android:exported="false" />
NotificationService (The class that's supposed to handle the notifications)-
Code:
package com.example.android.calendar.Helpers;

import android.app.AlarmManager;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;

import com.example.android.calendar.Model.Event;
import com.example.android.calendar.R;
import java.util.Calendar;
import java.util.HashMap;
import java.util.UUID;

public class NotificationService extends IntentService {

    private static Context mContext;
    private static final String NOTIFICATION_CHANNEL_ID = "notificationChannelId";
    private static final String NOTIFICATION_CHANNEL_NAME = "eventsNotificationChannel";

    public static final String EX_ID = "extraId";
    public static final String ACTION_START_SERVICE = "startService";
    public static final String ACTION_NOTIFY_ON_TIME = "notifyOnTime";

    private static HashMap<UUID, Notification> notifications = new HashMap<>();
    public static int mCounter = 0;


    public NotificationService(){
        super("notificationService");
    }

    @Override
    public void onCreate(){
        super.onCreate();
    }

    @Override
    protected void onHandleIntent(Intent intent){
        if(intent.getAction().contentEquals(ACTION_START_SERVICE))
            return;
        UUID id = (UUID) intent.getSerializableExtra(EX_ID);
        Notification notification = notifications.get(id);
        NotificationManagerCompat mNM = NotificationManagerCompat.from(mContext);
        mNM.notify(mCounter++, notification);
        try{
            Thread.sleep(1000);
        } catch(InterruptedException e){
            e.printStackTrace();
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId){
        super.onStartCommand(intent, flags, startId);
        return IntentService.START_REDELIEVER_INTENT;
    }

    public void createNotificationChannel(Context context){
        mContext = context;
        NotificationManager mNM = (NotificationManager) mContext.getSystemService(NOTIFICATION_SERVICE);
        NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
                NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
        notificationChannel.enableVibration(true);
        notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 100});
        notificationChannel.enableLights(true);
        mNM.createNotificationChannel(notificationChannel);
    }

    public void createNotification(int minutesBefore, Event event){
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mContext, NOTIFICATION_CHANNEL_ID).
                setSmallIcon(R.drawable.ic_launcher_foreground).setContentTitle(event.getLabel()).
                setContentText(event.getComment()).setAutoCancel(true);

        // If an event is edited, remove existing notification
        if(notifications.get(event.getId()) != null)
            notifications.remove(event.getId());

        Calendar mCalendar = Calendar.getInstance();
        notifications.put(event.getId(), mBuilder.build());
        mCalendar.setTime(event.getTime());
        mCalendar.set(Calendar.SECOND, 0);

        Intent intent = new Intent(mContext, NotificationService.class);
        intent.putExtra(EX_ID, event.getId());
        intent.setAction(ACTION_NOTIFY_ON_TIME);
        PendingIntent notificationIntent = PendingIntent.getService(mContext, (int)System.currentTimeMillis(),
                intent, PendingIntent.FLAG_CANCEL_CURRENT);
        long triggerInMills = mCalendar.getTimeInMillis() - Calendar.getInstance().getTimeInMillis();
        AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        alarmManager.setExact(AlarmManager.RTC, System.currentTimeMillis() + triggerInMills, notificationIntent);
    }

    public void cancelNotification(Event event, PendingIntent notificationIntent){
        AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        alarmManager.cancel(notificationIntent);
        notifications.remove(event.getId());
    }
}

I want to stress - the notifications properly work when the app is in the background\foreground.
I don't have prior knowledge with processes. From what I gathered the problem is that this app component is destroyed when the app itself is destroyed.
One work around I found was making it a foreground service, however this doesn't suit the nature of the app. The other is making onStartCommand() return START_REDELIEVER_INTENT, I thought it made sense according to the docs, but it does nothing. Some people suggested START_STICKY is the key but it didn't work either.

I hope I descirbed the issue well enough and gave the relevant code. Any insight into the matter would be appreciated.
Also, any good sources that explain this subject. Pehaps I overlooked something obvious or simply didn't manage to peice things together.
 
Back
Top Bottom