I have an application in production that is receiving a significant number of force/closes when calling an authenticated Cloud Endpoint. The most telling message is " java.lang.IllegalArgumentException: Service not registered: com.google.android.gms.internal.es@4481e6a8". The logic works correctly 95% of the time. The stack trace of the failure is as follows:
java.lang.RuntimeException: An error occured while executing doInBackground() at android.os.AsyncTask$3.done(AsyncTask.java:200) at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273) at java.util.concurrent.FutureTask.setException(FutureTask.java:124) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307) at java.util.concurrent.FutureTask.run(FutureTask.java:137) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561) at java.lang.Thread.run(Thread.java:1096)Caused by: java.lang.IllegalArgumentException: Service not registered: com.google.android.gms.internal.es@4481e6a8 at android.app.ActivityThread$PackageInfo.forgetServiceDispatcher(ActivityThread.java:1074) at android.app.ContextImpl.unbindService(ContextImpl.java:886) at android.content.ContextWrapper.unbindService(ContextWrapper.java:352) at com.google.android.gms.auth.GoogleAuthUtil.java.lang.String getToken(android.content.Context,java.lang.String,java.lang.String)(Unknown Source) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) at com.google.android.gms.auth.GoogleAuthUtil.java.lang.String getToken(android.content.Context,java.lang.String,java.lang.String)(Unknown Source) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential.java.lang.String getToken()(SourceFile:192) at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential$RequestHandler.void intercept(com.google.api.client.http.HttpRequest)(SourceFile:217) at com.google.api.client.http.HttpRequest.com.google.api.client.http.HttpResponse execute()(SourceFile:836) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.com.google.api.client.http.HttpResponse executeUnparsed(boolean)(SourceFile:412) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.com.google.api.client.http.HttpResponse executeUnparsed()(SourceFile:345) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.java.lang.Object execute()(SourceFile:463) at com.jdub.empiretracker.EmpireTrackerActivity$QueryMarketStats.com.google.api.services.marketendpoint.model.Market doInBackground(com.google.api.services.marketendpoint.model.Market[])(SourceFile:355) at com.jdub.empiretracker.EmpireTrackerActivity$QueryMarketStats.java.lang.Object doInBackground(java.lang.Object[])(SourceFile:1) at android.os.AsyncTask$2.call(AsyncTask.java:185) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) ... 4 more
My implementation is very consistent with the Google samples. For example, my Android activity is using an AsyncTask to make the call, as follows:
private class QueryMarketStats extends AsyncTask<com.google.api.services.marketendpoint.model.Market, com.google.api.services.marketendpoint.model.Market, com.google.api.services.marketendpoint.model.Market> {
/* (non-Javadoc)
* @see android.os.AsyncTask#doInBackground(Params[])
*/
@Override
protected com.google.api.services.marketendpoint.model.Market doInBackground(com.google.api.services.marketendpoint.model.Market...markets) {
com.google.api.services.marketendpoint.model.Market result = null;
try {
result = service.market().latest(state.getServerID()).execute();
}
catch (SSLException e) {
PrimeDataStore();
Log.d("app", e.getMessage(), e);
}
catch (GoogleAuthIOException e) {
Log.d("app", e.getMessage(), e);
}
catch (IOException e) {
Log.d("app", e.getMessage(), e);
}
return result;
}
/* (non-Javadoc)
* @see android.os.AsyncTask#onPostExecute(java.lang.Object)
*/
@Override
protected void onPostExecute(com.google.api.services.marketendpoint.model.Market result) {
// Process result...
}
}
The line giving the error is: result = service.market().latest(state.getServerID()).execute();
I have verified the parameter for getServerID() is returning a value that is acceptable. My theory at this point is that Google Play Services is not able to provide an account that is still authenticated. Although I have been unable to reproduce, I believe the issue may occur when the application goes to sleep. I therefore confirmed my onResume() logic, as follows:
@Override
protected void onResume() {
super.onResume();
checkPlayServices();
isInFront = true;
}
What else could cause this intermittent failure? Is this a known issue?