-1

I am working an android project. I want to send a notification to users when users are in app or killed the app. So, I use service and broadcastreceiver classes.

When I try to send a notification, it succeeds in both (App is running or killed). But when I reopen the app after getting it killed, the app crashes (Android 8.1 and later versions). I get this error:

"Context.startForegroundService() did not then call Service.startForeground()"

I added permission for FOREGROUND_SERVICE in AndroidManifest. As a result of my research, I tried many ways but I could not reach a solution. I follow this solutions but doesn't work. I'd appreciate it if you could show me what I can do. You can find my classes below.

My Base Class:

Intent GoService;
private PushService mPushService;
Context context;
public Context getCtx() {
    return  context ;
}
…
context = this;
mPushService = new PushService(getCtx());
GoService = new Intent(getCtx(),mPushService.getClass());
if (!isServiceRunning (mPushService.getClass())) {
    startService(GoService);
}
…
private boolean isServiceRunning(Class<?> serviceClass) {
    ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.getName().equals(service.service.getClassName())) {
            Log.i ("isServiceRunning?", true+"");
            return true;
        }
    }
    Log.i ("isServiceRunning?", false+"");
    return false;
}

@Override
protected void onDestroy() {
    stopService(GoService);
    Log.i("MAINACT", "onDestroy!");
    super.onDestroy();
}

My Service Class:

public class PushService extends Service {

public NotificationCompat.Builder builder;
private RequestQueue mQueue;

final Handler handler = new Handler();

public PushService (Context applicationContext) {
    super();
    Log.i("Service", "Here!");
}
public PushService () {
}
@Override
public void onCreate() {
    super.onCreate();
    handler.postDelayed(new Runnable() {
        public void run() {
            JSONParse();
            handler.postDelayed(this, 5000);
        }
    }, 0);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
   return START_STICKY;
}}}

My Receiver Class:

public class PushServiceReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        context.startForegroundService(new Intent(context, PushService.class));
    } else {
        context.startService(new Intent(context, PushService.class));
    }
}
AlpYuktug
  • 178
  • 1
  • 2
  • 13
  • where is your `Service`s `startForeground` call? – Pawel Dec 18 '19 at 12:36
  • @Pawel, Receiver class had for start methods. – AlpYuktug Dec 18 '19 at 12:37
  • This a different method, you have to call [`startForeground(int, Notification)`](https://developer.android.com/reference/android/app/Service#startForeground(int,%20android.app.Notification)) from within the service itself to satisfy foreground contact. – Pawel Dec 18 '19 at 12:40
  • But, I want to use without Notification. How I implement this method with? – AlpYuktug Dec 18 '19 at 12:42
  • 3
    You don't, your use case is the reason why this restriction was put in the first place - to prevent services from starting without user knowledge. – Pawel Dec 18 '19 at 12:45
  • For sure you have an exception before reaching startForeground – Duna Sep 02 '20 at 07:53

1 Answers1

1

Finally, I solve this problem. Thanks for show me what I can do. First, I add startForeground and custom startForeground on my service class. And I hide this notification. Now, app successfuly running everytime.

My service class:

   @Override
    public void onCreate() {
        super.onCreate();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
            startCustomForeground();
        else
            startForeground(1, new Notification());
    }

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

        stopForeground (true); //For hide notification
   ...

private void startCustomForeground(){
        String NOTIFICATION_CHANNEL_ID = "Try";
        String channelName = "BackgroundService";
        NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE);
        chan.setLightColor(Color.BLUE);
        chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        assert manager != null;
        manager.createNotificationChannel(chan);

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
        Notification notification = notificationBuilder.setOngoing(true)
                .setPriority(NotificationManager.IMPORTANCE_MIN)
                .setCategory(Notification.CATEGORY_SERVICE)
                .build();
        startForeground(2, notification);
    }
AlpYuktug
  • 178
  • 1
  • 2
  • 13
  • 2
    Note that after stopping foreground the system will be free to destroy your service. Additionally some AOSP android implementations display a warning notification when there's a background service running. – Pawel Dec 18 '19 at 20:16
  • @Pawel Thank you for your interest. I'm going to consider what you say. – AlpYuktug Dec 19 '19 at 08:45
  • @Pawel is there a way to prevent AOSP displaying the warning message? – Duna Sep 02 '20 at 07:54