Reputation: 41
We recently implemented foreground service and on Android 9 (Samsung devices only) some users experience some recurring crashes and we don't know what's causing this. Has anyone encountered the same issue? Is there a fix for this issue?
Fatal Exception: android.app.RemoteServiceException Context.startForegroundService() did not then call Service.startForeground()
android.app.ActivityThread$H.handleMessage (ActivityThread.java:1874)
android.os.Handler.dispatchMessage (Handler.java:106)
android.os.Looper.loop (Looper.java:214)
android.app.ActivityThread.main (ActivityThread.java:7073)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:494)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:964)
AndroidManigest.xml
<service
android:name="com.sotg.base.util.GeoNotification"
android:exported="true"
android:foregroundServiceType="location" />
GeoNotificationManager.kt
override fun startService() {
val geoService = Intent(context, GeoNotification::class.java)
geoService.action = GeoNotification.START_SERVICE_ACTION
// for android Oreo and higher start as foreground
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(geoService)
} else {
context.startService(geoService)
}
}
override fun stopService() {
// Shouldn't initialize the service to stop it when the service is not running.
if (!GeoNotification.isServiceRunning()) return;
val geoService = Intent(context, GeoNotification::class.java)
geoService.action = GeoNotification.STOP_TRACKING_ACTION
runCatching { context.startService(geoService) }
.onFailure(analytics::logException)
}
GoeNotification.java
private static boolean isServiceRunning;
public static boolean isServiceRunning() {
return isServiceRunning;
}
@Override
public void onCreate() {
super.onCreate();
isServiceRunning = false;
}
@Override
public void onDestroy() {
stopTracking();
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (START_SERVICE_ACTION.equals(intent.getAction())) {
startTracking();
} else if (STOP_TRACKING_ACTION.equals(intent.getAction())) {
stopTracking();
} else {
Log.w(TAG, "Unknown action for location service");
}
// Service restarts if it gets terminated
// the original Intent is re-delivered to the onStartCommand
// method when using START_REDELIVER_INTENT.
return START_REDELIVER_INTENT;
}
private void startTracking() {
if (isServiceRunning) return;
// create notification and config as foreground only for android Oreo and higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(Constants.NOTIFY_SURVEY_GCM, createForegroundNotification(this));
}
isServiceRunning = true;
...
}
private void stopTracking() {
if (!isServiceRunning) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
stopForeground(true);
}
stopSelf();
return;
}
// stop location updates on partner SDKs
....
stopSelf();
isServiceRunning = false;
}
public static Notification createForegroundNotification(Context context) {
NotificationChannelUtil.INSTANCE.getPreparedManager(context);
String channel = NotificationChannelUtil.INSTANCE.getSYSTEM_CHANNEL_ID();
// The PendingIntent to launch activity.
PendingIntent activityPendingIntent = PendingIntent.getActivity(context, 0,
new Intent(context, MainTabActivity.class), 0);
NotificationCompat.Action settingsAction = NotificationUtil.createSettingAction(context);
String title = context.getResources().getString(R.string.foreground_service_notification_title);
String desc = context.getResources().getString(R.string.foreground_service_notification_description);
String expandedText = context.getResources().getString(R.string.foreground_service_notification_description_expanded);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channel)
.setContentIntent(activityPendingIntent)
.setSmallIcon(R.drawable.noti)
.setContentTitle(title)
.setContentText(desc)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(expandedText))
.addAction(settingsAction)
.setColorized(false)
.setOngoing(true);
return builder.build();
}
Upvotes: 4
Views: 4983
Reputation: 332
This happens even if a notification is launched with startForeground(). This problem is caused by bugs in the software on some devices. So it can not be solved in the app code. The only realistic solution is to go to crashes and ANR on the play developer console and find the problem devices. Then go to device manager on the same developer console and exclude those devices. I have seen that Huawei HUAWEI Y5 causes a lot of these crashes.
Upvotes: 0
Reputation: 132
I had the same problem with Samsung and Huawei devices with Android Oreo or above. I would get the same errors.
If I remember correctly, since Android Oreo and above it is required to make use of startForeground()
when using startService()
or startForegroundService()
.
I solved it by adding the following code to the onCreate function of the service class. I created a notification and launched it with startForeground()
.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationChannel mNotificationChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_NONE);
mNotificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
mNotificationManager.createNotificationChannel(mNotificationChannel);
Notification note = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Reboot Sequence")
.setContentText("Rescheduling Alarms")
.setSmallIcon(R.drawable.ic_alarm_24dp)
.build();
startForeground(1, note);
}
I hope this will help you.
Upvotes: 2