25

From last week , Our app occur a lot of exception about this .we use GMS 11.0.2

Fatal Exception: java.lang.IllegalStateException: Results have already been set
   at com.google.android.gms.common.internal.zzbo.zza(Unknown Source)
   at com.google.android.gms.internal.zzbbl.setResult(Unknown Source)
   at com.google.android.gms.internal.zzbbf.zzz(Unknown Source)
   at com.google.android.gms.internal.zzbbf.zzf(Unknown Source)
   at com.google.android.gms.internal.zzbbf.zzb(Unknown Source)
   at com.google.android.gms.internal.zzbav.zza(Unknown Source:3)
   at com.google.android.gms.internal.zzbdk.zzb(Unknown Source)
   at com.google.android.gms.internal.zzbdk.zzrR(Unknown Source)
   at com.google.android.gms.internal.zzbdk.onConnected(Unknown Source)
   at com.google.android.gms.common.internal.zzaa.onConnected(Unknown Source)
   at com.google.android.gms.common.internal.zzn.zzsR(Unknown Source:2)
   at com.google.android.gms.common.internal.zze.zzy(Unknown Source)
   at com.google.android.gms.common.internal.zzh.handleMessage(Unknown Source:4)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:148)
   at android.os.HandlerThread.run(HandlerThread.java:61)

the log report by fabric.

we use firebase and gms version is 11.0.2

how do we check these problems?

and the same problem in gms version 11.8.0

java.lang.IllegalStateException: Results have already been set

   at com.google.android.gms.common.internal.zzbs.zza(Unknown Source)
   at com.google.android.gms.common.api.internal.zzs.setResult(Unknown Source)
   at com.google.android.gms.common.api.internal.zzm.zzy(Unknown Source)
   at com.google.android.gms.common.api.internal.zzm.zzf(Unknown Source)
   at com.google.android.gms.common.api.internal.zzm.zzb(Unknown Source)
   at com.google.android.gms.common.api.internal.zzc.zza(Unknown Source:3)
   at com.google.android.gms.common.api.internal.zzbr.zzb(Unknown Source)
   at com.google.android.gms.common.api.internal.zzbr.zzakz(Unknown Source)
   at com.google.android.gms.common.api.internal.zzbr.onConnected(Unknown Source)
Jamin
  • 300
  • 4
  • 10
  • Try to add this line in your code: `compile 'com.google.android.gms:play-services:11.0.4'` as what have been instructed in the documentation on how to [Add Google Play Services to Your Project](https://developers.google.com/android/guides/setup#add_google_play_services_to_your_project). Also you can check [this post](https://productforums.google.com/forum/#!msg/tag-manager/NOlng117_2g/w46OkQS5Gm8J) for further reference. – MαπμQμαπkγVπ.0 Dec 10 '17 at 10:47
  • Have you solved the issue ? – mob_web_dev Dec 12 '17 at 11:21
  • Do you have any update in the issue?, I have also experienced the same issue on my app (play services 11.6.2). – Pat Dec 19 '17 at 13:11
  • 1
    There's a bug report here: https://issuetracker.google.com/issues/70416429 – gosr Dec 21 '17 at 09:51
  • Any Updates? Looks like a bug in google play services. Did you managed to reproduce it? I can only see it in Crashlytics – bentzy Jan 28 '18 at 08:24

3 Answers3

5

This hack is based on Jamin's and divonas' answer. It works with Crashlytics and without Crashlytics. Call this method in Application onCreate() method. If you are using Crashlytics, call this method after Crashlytics initialized. BTW, ui thread id may not always be 1.

/**
 * Hack for gms bug https://issuetracker.google.com/issues/70416429
 * https://stackoverflow.com/questions/47726111/gms-illegalstateexception-results-have-already-been-set
 */
private void handleGMS70416429() {
    final Thread.UncaughtExceptionHandler defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
    final long uiThreadId = Thread.currentThread().getId();
    Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {

        @Override
        public void uncaughtException(Thread t, Throwable e) {
            if (e != null && t.getId() != uiThreadId && e.getStackTrace() != null && e.getStackTrace().length > 0
                    && e.getStackTrace()[0].toString().contains("com.google.android.gms")
                    && e.getMessage() != null && e.getMessage().contains("Results have already been set")) {
                return; // non-UI thread
            }
            if (defaultExceptionHandler != null)
                defaultExceptionHandler.uncaughtException(t, e);
        }

    });
}
Hexise
  • 1,520
  • 15
  • 20
  • You don't seem to be using `mDefaultExceptionHandler` and `mUIThreadId` elsewhere: why do you need them as private member variable? – ozbek May 07 '19 at 02:24
  • @ozbek it is ok to use final local variables, I will update the answer, thanks. – Hexise May 07 '19 at 15:24
  • I'm facing this issue in SafetyNet API. When I try to debug, my code isn't executing your suggestion. Any possible reasons, why? – Yasir Tahir May 07 '20 at 14:31
3

Since the bug hasn't been fixed yet, call handleGMSException() in BaseApplication's onCreate() method or implement your own ExceptionHandler. This hack is based on Jamin's answer, updated on Hexise's comment.

private void handleGMSException() {
    Thread.UncaughtExceptionHandler rootHandler = Thread.getDefaultUncaughtExceptionHandler();
    Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
        if (!isGMSException(thread, throwable)) {
            rootHandler.uncaughtException(thread, throwable);
        }
    });
}

private boolean isGMSException(Thread thread, Throwable throwable) {
    //Check if Main Thread.
    if (throwable == null || thread.getId() == 1) return false;

    if (throwable.getStackTrace() != null && throwable.getStackTrace().length > 0
            && throwable.getStackTrace()[0].toString().contains("com.google.android.gms")
            && throwable.getMessage().contains("Results have already been set")) {
        return true;
    }

    return false;
}
divonas
  • 992
  • 1
  • 10
  • 11
  • 1
    Will it enter infinite loop? Since DefaultUncaughtExceptionHandler has already been changed to customized one, Thread.getDefaultUncaughtExceptionHandler().uncaughtException() will call its own method. – Hexise Mar 08 '18 at 04:14
  • I'm facing this issue in SafetyNet API. When I try to debug, my code isn't executing your suggestion. Any possible reasons, why? – Yasir Tahir May 07 '20 at 14:38
0

I haven't solved this bug, but I try to catch it by UncaughtExceptionHandler.I'm using fabric, so I register MyUncaughtExceptionHandler after fabric so that I can determine whether handle this problem first. if I find is this exception. I will catch it.

//try to catch some uncaught exception
 public static boolean crashInterceptor(Thread thread, Throwable throwable) {

if (throwable == null || thread.getId() == 1) {
  //Don't intercept the Exception of Main Thread.
  return false;
}

String classpath = null;
if (throwable.getStackTrace() != null && throwable.getStackTrace().length > 0) {
  classpath = throwable.getStackTrace()[0].toString();
}

//intercept GMS Exception
if (classpath != null
    && throwable.getMessage().contains("Results have already been set")
    && classpath.contains("com.google.android.gms")) {
  //CrashHelper.logNonFatalException();
  return true;
}

return false;
}
}
Jamin
  • 300
  • 4
  • 10