googlesamples / google-signin-unity

Google Sign-In API plugin for Unity game engine. Works with Android and iOS.
Other
408 stars 223 forks source link

Application.Quit() on Android breaks Google sign-in in Unity 2018.3 #86

Open giliwerner opened 5 years ago

giliwerner commented 5 years ago

Up until recently, we were using Unity version 2018.2.1 and it worked well with this plugin (version 1.0.4). We were forced to update our Unity version, and are now using 2018.3.9, and the Google sign in plugin is now completely broken if we call Application.Quit().

As long as we kill our app by closing it from the task manager (or just swiping it shut from the list of open apps), the google sign-in will continue to work on next attempts. However, if we try to gracefully exit the app by calling Application.Quit() when the back button is pressed, the next attempt to sign-in with google breaks (we tried using both SignIn() and SignInSilently() and both fail with the same error message)

This is the code we use to sign the user in: GoogleSignIn.Configuration = new GoogleSignInConfiguration() { UseGameSignIn = false, RequestIdToken = true, RequestEmail = true, WebClientId = "our_app_id", }; GoogleSignIn.DefaultInstance.EnableDebugLogging(AppDefs.IsDebugEnvironment); GoogleSignIn.DefaultInstance.SignIn().ContinueWith(task => OnGoogleSignInCallback(task));

and this is the error message we see in the adb logs after calling Application.Quit(), opening the app again and trying to sign in: 04-10 18:15:55.876 11214 11591 I Unity : [INFO] [LoginComponent]: Log in with google 04-10 18:15:55.891 11214 11591 D SignInFragment: TokenFragment.configure called 04-10 18:15:55.891 11214 11591 D SignInFragment: AuthHelperFragment.authenticate called! 04-10 18:15:55.891 11214 11591 D SignInFragment: Using DEFAULT_SIGN_IN 04-10 18:15:55.941 11214 11591 D SignInFragment: Requesting email 04-10 18:15:55.941 11214 11591 D SignInFragment: Requesting IDToken client: our_app_id 04-10 18:15:55.951 11214 11591 E SignInFragment: Exception caught! Attempt to invoke virtual method 'android.os.Looper android.content.Context.getMainLooper()' on a null object reference 04-10 18:15:55.966 11214 11591 D TokenPendingResult: Calling onResult for callback. result: Status: Status{statusCode=INTERNAL_ERROR, resolution=null} 04-10 18:15:55.966 11214 11591 D SignInFragment: Calling nativeOnResult: handle: 2420836400, status: 8 acct: null 04-10 18:15:56.001 11674 11674 W System : ClassLoader referenced unknown path: /system/priv-app/SecVideoPlayer/lib/arm 04-10 18:15:56.086 11214 11591 E Unity : [ERROR] [LoginComponent]: Failed to log in to google [Completed: True] [Faulted: True] [Cancelled: False] [Status: InternalError] [Message: Exception of type 'Google.GoogleSignIn+SignInException' was thrown.]

Any idea how to fix this issue? We have no choice but to use the latest unity version, but this leaves us without an option to use Google Sign-in... Thanks

giliwerner commented 5 years ago

After examining the plugin code, I found the problem in GoogleSignInFragment.java. There's a static field holding the fragment: private static GoogleSignInFragment theFragment; This is being populated in onResume, but never cleared. Apart from being a memory leak, this actually causes the crash, since we are later on trying to use a dead fragment. For this reason, getActivity() returns null, and you can see the error message: SignInFragment: Exception caught! Attempt to invoke virtual method 'android.os.Looper android.content.Context.getMainLooper()' on a null object reference

All you need to do is set this to null on onDestroy and the problem is fixed. Since compiling this plugin myself kept brining up errors, I ended up fixing this with reflection in my Activity class: `@Override public void onDestroy() { super.onDestroy();

try {
    Log.d(TAG, "Set fragment to null");
    Field field = GoogleSignInFragment.class.getDeclaredField("theFragment");
    field.setAccessible(true);
    field.set(null, null);
} catch (Exception ex) {
    Log.w(TAG, "Failed to set Fragment to null: " + ex);
}

}`

Can this plugin be fixed to address this crash and memory leak? Thanks

arek199602 commented 5 years ago

Hello. I don't know java. Could you exactly explain what should I do?

anisabboud commented 5 years ago

Encountered the same issue (with Unity 2019.1). Here's the Logcat output showing the Exception:

google-sign-in-after-application-quit-error

This happens after using Application.Quit(), then opening the app again and clicking Sign in with Google.

Handling the exception then calling GoogleSignIn.DefaultInstance.SignIn() again to retry the sign in process never comes back... Stuck waiting after:

hangs-forever-after-restart

thientvimo commented 4 years ago

Up until recently, we were using Unity version 2018.2.1 and it worked well with this plugin (version 1.0.4). We were forced to update our Unity version, and are now using 2018.3.9, and the Google sign in plugin is now completely broken if we call Application.Quit().

As long as we kill our app by closing it from the task manager (or just swiping it shut from the list of open apps), the google sign-in will continue to work on next attempts. However, if we try to gracefully exit the app by calling Application.Quit() when the back button is pressed, the next attempt to sign-in with google breaks (we tried using both SignIn() and SignInSilently() and both fail with the same error message)

This is the code we use to sign the user in: GoogleSignIn.Configuration = new GoogleSignInConfiguration() { UseGameSignIn = false, RequestIdToken = true, RequestEmail = true, WebClientId = "our_app_id", }; GoogleSignIn.DefaultInstance.EnableDebugLogging(AppDefs.IsDebugEnvironment); GoogleSignIn.DefaultInstance.SignIn().ContinueWith(task => OnGoogleSignInCallback(task));

and this is the error message we see in the adb logs after calling Application.Quit(), opening the app again and trying to sign in: 04-10 18:15:55.876 11214 11591 I Unity : [INFO] [LoginComponent]: Log in with google 04-10 18:15:55.891 11214 11591 D SignInFragment: TokenFragment.configure called 04-10 18:15:55.891 11214 11591 D SignInFragment: AuthHelperFragment.authenticate called! 04-10 18:15:55.891 11214 11591 D SignInFragment: Using DEFAULT_SIGN_IN 04-10 18:15:55.941 11214 11591 D SignInFragment: Requesting email 04-10 18:15:55.941 11214 11591 D SignInFragment: Requesting IDToken client: our_app_id 04-10 18:15:55.951 11214 11591 E SignInFragment: Exception caught! Attempt to invoke virtual method 'android.os.Looper android.content.Context.getMainLooper()' on a null object reference 04-10 18:15:55.966 11214 11591 D TokenPendingResult: Calling onResult for callback. result: Status: Status{statusCode=INTERNAL_ERROR, resolution=null} 04-10 18:15:55.966 11214 11591 D SignInFragment: Calling nativeOnResult: handle: 2420836400, status: 8 acct: null 04-10 18:15:56.001 11674 11674 W System : ClassLoader referenced unknown path: /system/priv-app/SecVideoPlayer/lib/arm 04-10 18:15:56.086 11214 11591 E Unity : [ERROR] [LoginComponent]: Failed to log in to google [Completed: True] [Faulted: True] [Cancelled: False] [Status: InternalError] [Message: Exception of type 'Google.GoogleSignIn+SignInException' was thrown.]

Any idea how to fix this issue? We have no choice but to use the latest unity version, but this leaves us without an option to use Google Sign-in... Thanks

thanks alots, that solved my problem, but memory leak bug still orrcurs..

arunpande21 commented 4 years ago

@thientvimo What solved your problem ? How did you solve it? Please Help

Lowpolywood commented 4 years ago

I did next steps and now it works:

  1. In Unity build your project with checked field: "Export project".

  2. Import project to Android Studio.

  3. In UnityPlayerActivity add dependencies: import java.lang.reflect.asterisk; import com.google.googlesignin.asterisk;

  4. In onDestroy method add: try { //Log.d("SignInFix", "Set fragment to null"); Field field = GoogleSignInFragment.class.getDeclaredField("theFragment"); field.setAccessible(true); field.set(null, null); } catch (Exception ex) { //Log.w("SignInFix", "Failed to set Fragment to null: " + ex); }

  5. Build project.

thientvimo commented 4 years ago

I did next steps and now it works:

  1. In Unity build your project with checked field: "Export project".
  2. Import project to Android Studio.
  3. In UnityPlayerActivity add dependencies: import java.lang.reflect.asterisk; import com.google.googlesignin.asterisk;
  4. In onDestroy method add: try { //Log.d("SignInFix", "Set fragment to null"); Field field = GoogleSignInFragment.class.getDeclaredField("theFragment"); field.setAccessible(true); field.set(null, null); } catch (Exception ex) { //Log.w("SignInFix", "Failed to set Fragment to null: " + ex); }
  5. Build project.

ya, I did like that rebuild java project, reimport to unity, force resolve java resolve, then build ok

arunpande21 commented 4 years ago

@thientvimo

rebuild java project, reimport to unity, force resolve java resolve, then build ok

How to reimport it from android studio to unity?? please help. Thankyou

arunpande21 commented 4 years ago

I did what you guyz said and now my app crashes after calling onsilentlogin