Android GCM - WakefulBroadcastReceiver.startWakefulService crash due to IllegalStateException 8.0 - android

We just migrated app's target api to Android API 27 (8.1) and it keeps on crashing when notification arrives specially when the app is in the background.
java.lang.RuntimeException: Unable to start receiver <package>.service.GCMBroadcastReceiver: java.lang.IllegalStateException: Not allowed to start service Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x1000010 pkg=<package> cmp=<package>/.service.GCMIntentService (has extras) }: app is in background uid UidRecord{b248a9d u0a85 RCVR bg:+1m4s53ms idle change:uncached procs:1 seq(0,0,0)}
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3194)
at android.app.ActivityThread.-wrap17(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1672)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.IllegalStateException: Not allowed to start service Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x1000010 pkg=<package> cmp=<package>/.service.GCMIntentService (has extras) }: app is in background uid UidRecord{b248a9d u0a85 RCVR bg:+1m4s53ms idle change:uncached procs:1 seq(0,0,0)}
at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1521)
at android.app.ContextImpl.startService(ContextImpl.java:1477)
at android.content.ContextWrapper.startService(ContextWrapper.java:650)
at android.support.v4.content.WakefulBroadcastReceiver.startWakefulService(WakefulBroadcastReceiver.java:99)
at <package>.service.GCMBroadcastReceiver.onReceive(GCMBroadcastReceiver.java:32)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3187)
at android.app.ActivityThread.-wrap17(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1672)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

This is how I fix the issue:
Why this issue happens?
Due to the new Background Execution Limits of Android 8 and you should
not start services background.
How I fixed it
Migrate your GCMIntetService to JobIntentService instead of IntentService.
Please follow this steps:
1) Add the BIND_JOB_SERVICE permission to your service:
<service android:name=".service.GCMIntentService"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE"/>
2) In your GCMIntentService, instead extending the IntentService, use android.support.v4.app.JobIntentService and override onHandleWork
then remove the override in you onHandleIntent.
public class GCMIntentService extends JobIntentService {
// Service unique ID
static final int SERVICE_JOB_ID = 50;
// Enqueuing work in to this service.
public static void enqueueWork(Context context, Intent work) {
enqueueWork(context, GCMIntentService.class, SERVICE_JOB_ID, work);
}
#Override
protected void onHandleWork(#NonNull Intent intent) {
onHandleIntent(intent);
}
private void onHandleIntent(Intent intent) {
//Handling of notification goes here
}
}
Then finally, in your GCMBroadcastReceiver, enqueue your GCMIntentService.
public class GCMBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(),
GCMIntentService.class.getName());
// Start the service, keeping the device awake while it is launching.
// startWakefulService(context, (intent.setComponent(comp)));
//setResultCode(Activity.RESULT_OK);
GCMIntentService.enqueueWork(context, (intent.setComponent(comp)));
}
}
This implementation work for me after we update our target sdk to 27 and I hope it works for you.

Related

Fatal Exception: android.app.ForegroundServiceDidNotStartInTimeException

Fatal Exception: android.app.ForegroundServiceDidNotStartInTimeException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{294bdda u0 com.xyz.xyz/com.xyz.pushnotification.BookingProgressService}
at android.app.ActivityThread.throwRemoteServiceException(ActivityThread.java:1923)
at android.app.ActivityThread.access$2700(ActivityThread.java:247)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2148)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
I'm facing this crash inside my service and that i have wrote on below way
Start service:
if (Build.VERSION.SDK_INT >= 26)
mContext.startForegroundService(serviceIntent)
else
mContext.startService(serviceIntent)
Inside Time Tick update or create notification:
registerTimeTickReceiver() method called inside onStartCommand() of Service class
private fun registerTimeTickReceiver() {
if (timeTickReceiver != null)
unregisterTimeTickReceiver()
timeTickReceiver = object : BroadcastReceiver() {
override fun onReceive(
context: Context, intent: Intent
) { //trigger the callback on every minutes
Log.e("BookingProgressService", "Service registerTimeTickReceiver")
if (intent.action?.compareTo(Intent.ACTION_TIME_TICK) == 0)
fetchDataForNotification()
}
}
registerReceiver(timeTickReceiver, IntentFilter(Intent.ACTION_TIME_TICK))
}
Inside fetchDataForNotification() added:
startForeground(booking.id, notification)
Note: This crashes I can't able to reproduce from my device but it is reproduced on some of the devices
My requirement is update multiple booking progress notification on every minute If my app is running or not running(Background) Can anyone please help me? or If you know other best approach then very thankful to you guys

App seems to be in background when activity onStart is called

Since Android Oreo you cannot start a service when the app is not in foreground. In my app I start a service in the activity's onStart-method. This works perfectly fine most of the times. However, from time to time an IllegalStateException is thrown saying that the application is trying to start a service while in the background:
java.lang.IllegalStateException: Not allowed to start service Intent { act=ui cmp=com.someapp/.services.ConnectionService }: app is in background uid UidRecord{8d70361 u0a255 TPSL bg:+3m12s948ms idle change:cached procs:1 proclist:20368, seq(0,0,0)}
at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1666)
at android.app.ContextImpl.startService(ContextImpl.java:1611)
at android.content.ContextWrapper.startService(ContextWrapper.java:677)
at com.someapp.ui.SomeActivity.connectToBackend(SomeActivity.java:62)
at com.someapp.ui.SomeActivity.onStart(SomeActivity.java:55)
at com.someapp.ui.MainActivity.onStart(MainActivity.kt:228)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1391)
at android.app.Activity.performStart(Activity.java:7348)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3131)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:180)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1947)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7032)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)
I start the service as follows:
#Override
protected void onStart() {
if (BuildConfig.DEBUG_MODE) Log.d(TAG, "activity started");
super.onStart();
connectToBackend();
}
void connectToBackend() {
Intent intent = new Intent(this, ConnectionService.class);
intent.setAction("ui");
startService(intent);
getApplicationContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
I noticed that this only happens when I lock and then unlock the phone while in the app. I cannot reproduce it consistently.
Does somebody have the same issue?
The device I'm using is a Samsung Galaxy S10e.
For post Nougat devices, use startForegroundService, and for pre Oreo devices, use startService
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent);
} else {
startService(intent);
}

Android 8.0+ java.lang.IllegalStateException: Not allowed to start service Intent

Android Studio 3.2
public class GcmWakefulBroadcastReceiver extends WakefulBroadcastReceiver {
private static String TAG;
#Override
public void onReceive(Context context, Intent intent) {
ComponentName comp = new ComponentName(context.getPackageName(), GcmIntentService_.class.getName());
startWakefulService(context, (intent.setComponent(comp))); // crash here
setResultCode(Activity.RESULT_OK);
}
}
public class GcmIntentService extends IntentService {
private static String TAG = GcmIntentService.class.getName();
public GcmIntentService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
}
}
On Android 8.0- success work. App is on background.
But on Android 8.0+ the app is crash with error:
FATAL EXCEPTION: main
Process: com.myproject.app, PID: 6506
java.lang.RuntimeException: Unable to start receiver com.myproject.app.gcm.GcmWakefulBroadcastReceiver: java.lang.IllegalStateException: Not allowed to start service Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x1000010 pkg=com.myproject.app cmp=com.myproject.app/.gcm.GcmIntentService_ (has extras) }: app is in background uid UidRecord{27efe68 u0a164 RCVR idle change:idle|uncached procs:1 seq(0,0,0)}
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3194)
at android.app.ActivityThread.-wrap17(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1672)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.IllegalStateException: Not allowed to start service Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x1000010 pkg=com.myproject.app cmp=com.myproject.app/.gcm.GcmIntentService_ (has extras) }: app is in background uid UidRecord{27efe68 u0a164 RCVR idle change:idle|uncached procs:1 seq(0,0,0)}
at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1521)
at android.app.ContextImpl.startService(ContextImpl.java:1477)
at android.content.ContextWrapper.startService(ContextWrapper.java:650)
at android.content.ContextWrapper.startService(ContextWrapper.java:650)
at com.myproject.app.gcm.GcmWakefulBroadcastReceiver.onReceive(GcmWakefulBroadcastReceiver.java:44)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3187)
... 8 more
broadcast intent callback: result=CANCELLED
Crash in this line:
startWakefulService(context, (intent.setComponent(comp))); // crash here
My app must work on Android 4.4+
Use JobIntentService Instead of IntentService.
public class GcmIntentService extends JobIntentService {
private static String TAG = GcmIntentService.class.getName();
public static void startService(Context context) {
enqueueWork(context, GcmIntentService.class, 1001, new Intent());
}
#Override
protected void onHandleWork(Intent intent) {
}
}
And From your Receiver:
public class GcmWakefulBroadcastReceiver extends WakefulBroadcastReceiver {
private static String TAG;
#Override
public void onReceive(Context context, Intent intent) {
GcmIntentService.startService(context);
}
}
If you are using GcmWakefulBroadcastReceiver just for starting the service then, You do not need to use WakefulBroadcastReceiver.
When running on Android O, the JobScheduler will take care of wake
locks for you (holding a wake lock from the time you enqueue work
until the job has been dispatched and while it is running).
https://developer.android.com/reference/android/support/v4/app/JobIntentService

Context.startForegroundService did not then call Service.startForeground

It's mine BroadcastReciever class. The class working on Boot phone status.
Code ;
public class BroadCastRecieverBoot extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent ıntent) {
if(Intent.ACTION_BOOT_COMPLETED.equals(ıntent.getAction()))
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(new Intent(context, MyService.class));
context.startForegroundService(new Intent(context, GPSTracker.class));
} else {
context.startService(new Intent(context, MyService.class));
context.startService(new Intent(context, GPSTracker.class));
}
}
}
}
I get This Error ;
android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1792)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6523)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:857)
It doesn't work on Android Oreo now. I don't know what is the mistake of that.
According to official document of Android 8.0 Background Execution Limits
Android 8.0 introduces the new method
startForegroundService() to start a new service in the foreground.
After the system has created the service, the app has five seconds to
call the service's startForeground() method to show the new service's
user-visible notification. If the app does not call startForeground()
within the time limit, the system stops the service and declares the
app to be ANR.
So, make sure you have started ongoing notification by calling startForeground (int id, Notification notification) in the onCreate() method of your service.
Note: Apps targeting API Build.VERSION_CODES.P or later must request the permission Manifest.permission.FOREGROUND_SERVICE in order to use this API.

Intent error while using startWakefulService

I'm trying to use startWakefulService(context, intent)
But after encoutering some issues I debugged my app and found that the intent being passed on to the method is false, it uses
Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x10 pkg=com.myApp.beta cmp=com.myApp.beta/fonctionnalite.Actualites.GcmReceiver (has extras) }
Instead of
Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x10 pkg=fonctionnalite.Actualites cmp=fonctionnalite.Actualites.GcmReceiver (has extras) }
So basically I'm trying to call the class called GcmReceiver which is in the package fonctionnalite.Actualites. I tried using a different component and intent but it still didn't work, would anyone know how I can solve this problem ?
Thanks !
Here is the code for the class using startWakefulService
public class GcmReceiver extends WakefulBroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
ComponentName comp = new ComponentName(context.getPackageName(), GcmMessageHandler.class.getName());
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}

Categories

Resources