My project requires an android foreground service to run continuously (even after the application is destroyed). To this effect I have the following code snippets:
build.gradle
implementation fileTree(dir: 'libs', include: ['*.jar'])
//noinspection GradleCompatible
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.android.support:design:28.0.0'
implementation 'com.google.android.gms:play-services-maps:16.1.0'
implementation 'com.google.android.gms:play-services-places:16.0.0'
implementation 'com.google.android.libraries.places:places:1.1.0'
implementation 'com.google.android.gms:play-services-location:16.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.google.android.gms:play-services-ads:17.2.0'
Manifest permissions
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
MainActivity.java
@Override
public void onCreate() {
Intent intent = new Intent(getApplicationContext(), MyService.class);
if (!isMyServiceRunning(MyService.class, MainActivity.this)) {
intent.setAction(MYConstants.ACTION_START_GPS_SERVICE);
intent.setAction(MyConstants.ACTION_START_GPS_SERVICE);
startService(intent);
Log.i(TAG, "MyService call made.");
}
}
MyService.java
public class MyService extends Service {
@Override
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
startServiceWithNotification();
} else{
startForeground(9999, new Notification());
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
@Override
public void onTaskRemoved(Intent rootIntent){
stopMyService();
Intent broadcastIntent = new Intent(this, MyBroadcastReceiver.class);
sendBroadcast(broadcastIntent);
}
@Override
public void onDestroy() {
stopMyService();
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
// Used only in case of bound services.
return null;
}
void stopMyService() {
stopForeground(true);
stopSelf();
}
@RequiresApi(Build.VERSION_CODES.O)
void startServiceWithNotification() {
String channelId = "com.mypackage.myapp";
String channelName = "Your Service";
NotificationChannel chan;
chan = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager mNotificationManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.createNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this,
channelId);
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("App is running in background")
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(10000, notification);
}
}
MyBroadcastReceiver.java
@Override
public void onReceive(Context context, Intent intent) {
Intent intent = new Intent(context, MyService.class);
intent.setAction(MYConstants.ACTION_START_GPS_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(intent);
Log.i(TAG, "MyService call made.");
} else {
context.startService(intent);
}
}
This Application is working as expected, the foreground service runs fine doing what it is intended to do even after the app is destroyed, but I consistently see a Warning as an IllegalArgumentException while running the application. The exception is attached below:
D/EGL_emulation: eglMakeCurrent: 0xdda12a20: ver 3 0 (tinfo 0xdda81230)
W/System: A resource failed to call close.
W/ConnectionTracker: Exception thrown while unbinding
java.lang.IllegalArgumentException: Service not registered: ll@85f600c
at android.app.LoadedApk.forgetServiceDispatcher(LoadedApk.java:1731)
at android.app.ContextImpl.unbindService(ContextImpl.java:1755)
at android.content.ContextWrapper.unbindService(ContextWrapper.java:735)
at ce.b(:com.google.android.gms.dynamite_measurementdynamite@[email protected] (100700-0):1)
at ce.a(:com.google.android.gms.dynamite_measurementdynamite@[email protected] (100700-0):5)
at lm.A(:com.google.android.gms.dynamite_measurementdynamite@[email protected] (100700-0):10)
at kx.a(:com.google.android.gms.dynamite_measurementdynamite@[email protected] (100700-0):3)
at dx.run(:com.google.android.gms.dynamite_measurementdynamite@[email protected] (100700-
0):2)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at iv.run(:com.google.android.gms.dynamite_measurementdynamite@[email protected] (100700-
0):15)
W/.myapp: Reducing the number of considered missed Gc histogram windows from 186 to 100
W/System: A resource failed to call close.
Can someone help me out in understanding why this exception is consistently being thrown and how can I resolve this??
As suggested by @CommonsWare in the comments above, the exceptions observed here are being logged by Play Services which is quite common and isn't a consequence of the application. Unless the exceptions are causing serious problems (such as the app crashing), such exceptions must not be considered as a pain point.