From 9e142d225897c34c502e997dd288e0a107bc24db Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 19 Apr 2023 08:12:30 -0400 Subject: [PATCH 1/6] Remove baseline file --- .../android/build.gradle | 1 - .../android/lint-baseline.xml | 730 ------------------ 2 files changed, 731 deletions(-) delete mode 100644 packages/google_sign_in/google_sign_in_android/android/lint-baseline.xml diff --git a/packages/google_sign_in/google_sign_in_android/android/build.gradle b/packages/google_sign_in/google_sign_in_android/android/build.gradle index d6872d51b6d4..ae2abf5b1631 100644 --- a/packages/google_sign_in/google_sign_in_android/android/build.gradle +++ b/packages/google_sign_in/google_sign_in_android/android/build.gradle @@ -37,7 +37,6 @@ android { checkAllWarnings true warningsAsErrors true disable 'AndroidGradlePluginVersion', 'InvalidPackage', 'GradleDependency' - baseline file("lint-baseline.xml") } diff --git a/packages/google_sign_in/google_sign_in_android/android/lint-baseline.xml b/packages/google_sign_in/google_sign_in_android/android/lint-baseline.xml deleted file mode 100644 index c59558ae18a2..000000000000 --- a/packages/google_sign_in/google_sign_in_android/android/lint-baseline.xml +++ /dev/null @@ -1,730 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 9489c092d3eda80d6879e07c4fd5225ba4cf536a Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 19 Apr 2023 08:13:36 -0400 Subject: [PATCH 2/6] Auto-convert lambdas --- .../googlesignin/BackgroundTaskRunner.java | 26 +-- .../googlesignin/GoogleSignInPlugin.java | 179 ++++++++---------- 2 files changed, 87 insertions(+), 118 deletions(-) diff --git a/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/BackgroundTaskRunner.java b/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/BackgroundTaskRunner.java index b13ec7e3412a..2aec17b23026 100644 --- a/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/BackgroundTaskRunner.java +++ b/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/BackgroundTaskRunner.java @@ -56,12 +56,7 @@ public BackgroundTaskRunner(int threads) { public void runInBackground(Callable task, final Callback callback) { final ListenableFuture future = runInBackground(task); future.addListener( - new Runnable() { - @Override - public void run() { - callback.run(future); - } - }, + () -> callback.run(future), Executors.uiThreadExecutor()); } @@ -76,18 +71,15 @@ public ListenableFuture runInBackground(final Callable task) { final SettableFuture future = SettableFuture.create(); executor.execute( - new Runnable() { - @Override - public void run() { - if (!future.isCancelled()) { - try { - future.set(task.call()); - } catch (Throwable t) { - future.setException(t); + () -> { + if (!future.isCancelled()) { + try { + future.set(task.call()); + } catch (Throwable t) { + future.setException(t); + } } - } - } - }); + }); return future; } diff --git a/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java b/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java index 8963a5169e89..93f3675d0296 100644 --- a/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java +++ b/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java @@ -10,6 +10,7 @@ import android.content.Intent; import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.google.android.gms.auth.GoogleAuthUtil; import com.google.android.gms.auth.UserRecoverableAuthException; @@ -21,7 +22,6 @@ import com.google.android.gms.common.api.ApiException; import com.google.android.gms.common.api.CommonStatusCodes; import com.google.android.gms.common.api.Scope; -import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.RuntimeExecutionException; import com.google.android.gms.tasks.Task; import com.google.common.base.Joiner; @@ -41,7 +41,6 @@ import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; /** Google sign-in plugin for Flutter. */ public class GoogleSignInPlugin implements MethodCallHandler, FlutterPlugin, ActivityAware { @@ -62,7 +61,7 @@ public class GoogleSignInPlugin implements MethodCallHandler, FlutterPlugin, Act private ActivityPluginBinding activityPluginBinding; @SuppressWarnings("deprecation") - public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registrar registrar) { + public static void registerWith(@NonNull io.flutter.plugin.common.PluginRegistry.Registrar registrar) { GoogleSignInPlugin instance = new GoogleSignInPlugin(); instance.initInstance(registrar.messenger(), registrar.context(), new GoogleSignInWrapper()); instance.setUpRegistrar(registrar); @@ -112,7 +111,7 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { } @Override - public void onAttachedToActivity(ActivityPluginBinding activityPluginBinding) { + public void onAttachedToActivity(@NonNull ActivityPluginBinding activityPluginBinding) { attachToActivity(activityPluginBinding); } @@ -122,7 +121,7 @@ public void onDetachedFromActivityForConfigChanges() { } @Override - public void onReattachedToActivityForConfigChanges(ActivityPluginBinding activityPluginBinding) { + public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding activityPluginBinding) { attachToActivity(activityPluginBinding); } @@ -132,7 +131,7 @@ public void onDetachedFromActivity() { } @Override - public void onMethodCall(MethodCall call, Result result) { + public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { switch (call.method) { case METHOD_INIT: String signInOption = call.argument("signInOption"); @@ -199,7 +198,7 @@ public void onMethodCall(MethodCall call, Result result) { */ public interface IDelegate { /** Initializes this delegate so that it is ready to perform other operations. */ - public void init( + void init( Result result, String signInOption, List requestedScopes, @@ -212,13 +211,13 @@ public void init( * Returns the account information for the user who is signed in to this app. If no user is * signed in, tries to sign the user in without displaying any user interface. */ - public void signInSilently(Result result); + void signInSilently(Result result); /** * Signs the user in via the sign-in user interface, including the OAuth consent flow if scopes * were requested. */ - public void signIn(Result result); + void signIn(Result result); /** * Gets an OAuth access token with the scopes that were specified during initialization for the @@ -227,28 +226,28 @@ public void init( *

If shouldRecoverAuth is set to true and user needs to recover authentication for method to * complete, the method will attempt to recover authentication and rerun method. */ - public void getTokens(final Result result, final String email, final boolean shouldRecoverAuth); + void getTokens(final Result result, final String email, final boolean shouldRecoverAuth); /** * Clears the token from any client cache forcing the next {@link #getTokens} call to fetch a * new one. */ - public void clearAuthCache(final Result result, final String token); + void clearAuthCache(final Result result, final String token); /** * Signs the user out. Their credentials may remain valid, meaning they'll be able to silently * sign back in. */ - public void signOut(Result result); + void signOut(Result result); /** Signs the user out, and revokes their credentials. */ - public void disconnect(Result result); + void disconnect(Result result); /** Checks if there is a signed in user. */ - public void isSignedIn(Result result); + void isSignedIn(Result result); /** Prompts the user to grant an additional Oauth scopes. */ - public void requestScopes(final Result result, final List scopes); + void requestScopes(final Result result, final List scopes); } /** @@ -409,12 +408,7 @@ public void signInSilently(Result result) { onSignInResult(task); } else { task.addOnCompleteListener( - new OnCompleteListener() { - @Override - public void onComplete(Task task) { - onSignInResult(task); - } - }); + this::onSignInResult); } } @@ -444,16 +438,13 @@ public void signOut(Result result) { signInClient .signOut() .addOnCompleteListener( - new OnCompleteListener() { - @Override - public void onComplete(Task task) { - if (task.isSuccessful()) { - finishWithSuccess(null); - } else { - finishWithError(ERROR_REASON_STATUS, "Failed to signout."); - } - } - }); + task -> { + if (task.isSuccessful()) { + finishWithSuccess(null); + } else { + finishWithError(ERROR_REASON_STATUS, "Failed to signout."); + } + }); } /** Signs the user out, and revokes their credentials. */ @@ -464,16 +455,13 @@ public void disconnect(Result result) { signInClient .revokeAccess() .addOnCompleteListener( - new OnCompleteListener() { - @Override - public void onComplete(Task task) { - if (task.isSuccessful()) { - finishWithSuccess(null); - } else { - finishWithError(ERROR_REASON_STATUS, "Failed to disconnect."); - } - } - }); + task -> { + if (task.isSuccessful()) { + finishWithSuccess(null); + } else { + finishWithError(ERROR_REASON_STATUS, "Failed to disconnect."); + } + }); } /** Checks if there is a signed in user. */ @@ -549,7 +537,6 @@ private String errorCodeForStatus(int statusCode) { case GoogleSignInStatusCodes.SIGN_IN_FAILED: case CommonStatusCodes.INVALID_ACCOUNT: case CommonStatusCodes.INTERNAL_ERROR: - return ERROR_REASON_SIGN_IN_FAILED; default: return ERROR_REASON_SIGN_IN_FAILED; } @@ -581,29 +568,24 @@ private static class PendingOperation { @Override public void clearAuthCache(final Result result, final String token) { Callable clearTokenTask = - new Callable() { - @Override - public Void call() throws Exception { - GoogleAuthUtil.clearToken(context, token); - return null; - } - }; + () -> { + GoogleAuthUtil.clearToken(context, token); + return null; + }; backgroundTaskRunner.runInBackground( clearTokenTask, - new BackgroundTaskRunner.Callback() { - @Override - public void run(Future clearTokenFuture) { - try { - result.success(clearTokenFuture.get()); - } catch (ExecutionException e) { - result.error(ERROR_REASON_EXCEPTION, e.getCause().getMessage(), null); - } catch (InterruptedException e) { - result.error(ERROR_REASON_EXCEPTION, e.getMessage(), null); - Thread.currentThread().interrupt(); - } - } - }); + clearTokenFuture -> { + try { + result.success(clearTokenFuture.get()); + } catch (ExecutionException e) { + @Nullable Throwable cause = e.getCause(); + result.error(ERROR_REASON_EXCEPTION, cause == null ? null : cause.getMessage(), null); + } catch (InterruptedException e) { + result.error(ERROR_REASON_EXCEPTION, e.getMessage(), null); + Thread.currentThread().interrupt(); + } + }); } /** @@ -622,56 +604,51 @@ public void getTokens( } Callable getTokenTask = - new Callable() { - @Override - public String call() throws Exception { - Account account = new Account(email, "com.google"); - String scopesStr = "oauth2:" + Joiner.on(' ').join(requestedScopes); - return GoogleAuthUtil.getToken(context, account, scopesStr); - } - }; + () -> { + Account account = new Account(email, "com.google"); + String scopesStr = "oauth2:" + Joiner.on(' ').join(requestedScopes); + return GoogleAuthUtil.getToken(context, account, scopesStr); + }; // Background task runner has a single thread effectively serializing // the getToken calls. 1p apps can then enjoy the token cache if multiple // getToken calls are coming in. backgroundTaskRunner.runInBackground( getTokenTask, - new BackgroundTaskRunner.Callback() { - @Override - public void run(Future tokenFuture) { - try { - String token = tokenFuture.get(); - HashMap tokenResult = new HashMap<>(); - tokenResult.put("accessToken", token); - result.success(tokenResult); - } catch (ExecutionException e) { - if (e.getCause() instanceof UserRecoverableAuthException) { - if (shouldRecoverAuth && pendingOperation == null) { - Activity activity = getActivity(); - if (activity == null) { - result.error( - ERROR_USER_RECOVERABLE_AUTH, - "Cannot recover auth because app is not in foreground. " - + e.getLocalizedMessage(), - null); + tokenFuture -> { + try { + String token = tokenFuture.get(); + HashMap tokenResult = new HashMap<>(); + tokenResult.put("accessToken", token); + result.success(tokenResult); + } catch (ExecutionException e) { + if (e.getCause() instanceof UserRecoverableAuthException) { + if (shouldRecoverAuth && pendingOperation == null) { + Activity activity = getActivity(); + if (activity == null) { + result.error( + ERROR_USER_RECOVERABLE_AUTH, + "Cannot recover auth because app is not in foreground. " + + e.getLocalizedMessage(), + null); + } else { + checkAndSetPendingOperation(METHOD_GET_TOKENS, result, email); + Intent recoveryIntent = + ((UserRecoverableAuthException) e.getCause()).getIntent(); + activity.startActivityForResult(recoveryIntent, REQUEST_CODE_RECOVER_AUTH); + } } else { - checkAndSetPendingOperation(METHOD_GET_TOKENS, result, email); - Intent recoveryIntent = - ((UserRecoverableAuthException) e.getCause()).getIntent(); - activity.startActivityForResult(recoveryIntent, REQUEST_CODE_RECOVER_AUTH); + result.error(ERROR_USER_RECOVERABLE_AUTH, e.getLocalizedMessage(), null); } } else { - result.error(ERROR_USER_RECOVERABLE_AUTH, e.getLocalizedMessage(), null); + @Nullable Throwable cause = e.getCause(); + result.error(ERROR_REASON_EXCEPTION, cause == null ? null : cause.getMessage(), null); } - } else { - result.error(ERROR_REASON_EXCEPTION, e.getCause().getMessage(), null); + } catch (InterruptedException e) { + result.error(ERROR_REASON_EXCEPTION, e.getMessage(), null); + Thread.currentThread().interrupt(); } - } catch (InterruptedException e) { - result.error(ERROR_REASON_EXCEPTION, e.getMessage(), null); - Thread.currentThread().interrupt(); - } - } - }); + }); } @Override From 80f15c90751de2b14182f0731c1dad351839f277 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 19 Apr 2023 12:24:38 -0400 Subject: [PATCH 3/6] Fix warnings --- .../googlesignin/BackgroundTaskRunner.java | 29 +-- .../plugins/googlesignin/Executors.java | 5 +- .../googlesignin/GoogleSignInPlugin.java | 242 +++++++++--------- .../lib/google_sign_in_android.dart | 2 +- 4 files changed, 142 insertions(+), 136 deletions(-) diff --git a/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/BackgroundTaskRunner.java b/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/BackgroundTaskRunner.java index 2aec17b23026..4fc0afadd4d9 100644 --- a/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/BackgroundTaskRunner.java +++ b/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/BackgroundTaskRunner.java @@ -4,6 +4,7 @@ package io.flutter.plugins.googlesignin; +import androidx.annotation.NonNull; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; import java.util.concurrent.BlockingQueue; @@ -31,7 +32,7 @@ public interface Callback { * the future is guaranteed not to block). If the future completed with an exception, then * {@code get()} will throw an {@code ExecutionException}. */ - void run(Future future); + void run(@NonNull Future future); } private final ThreadPoolExecutor executor; @@ -53,11 +54,9 @@ public BackgroundTaskRunner(int threads) { * *

The callback will be notified on the UI thread. */ - public void runInBackground(Callable task, final Callback callback) { + public void runInBackground(@NonNull Callable task, final @NonNull Callback callback) { final ListenableFuture future = runInBackground(task); - future.addListener( - () -> callback.run(future), - Executors.uiThreadExecutor()); + future.addListener(() -> callback.run(future), Executors.uiThreadExecutor()); } /** @@ -67,19 +66,19 @@ public void runInBackground(Callable task, final Callback callback) { *

Note: the future will be notified on the background thread. To be notified on the UI thread, * use {@link #runInBackground(Callable,Callback)}. */ - public ListenableFuture runInBackground(final Callable task) { + public @NonNull ListenableFuture runInBackground(final @NonNull Callable task) { final SettableFuture future = SettableFuture.create(); executor.execute( - () -> { - if (!future.isCancelled()) { - try { - future.set(task.call()); - } catch (Throwable t) { - future.setException(t); - } - } - }); + () -> { + if (!future.isCancelled()) { + try { + future.set(task.call()); + } catch (Throwable t) { + future.setException(t); + } + } + }); return future; } diff --git a/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/Executors.java b/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/Executors.java index 824c6da8ec9f..89f5c22acf2a 100644 --- a/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/Executors.java +++ b/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/Executors.java @@ -6,6 +6,7 @@ import android.os.Handler; import android.os.Looper; +import androidx.annotation.NonNull; import java.util.concurrent.Executor; /** @@ -16,7 +17,7 @@ */ public final class Executors { - private static final class UiThreadExecutor implements Executor { + static final class UiThreadExecutor implements Executor { private static final Handler UI_THREAD = new Handler(Looper.getMainLooper()); @Override @@ -26,7 +27,7 @@ public void execute(Runnable command) { } /** Returns an {@code Executor} that will post commands to the UI thread. */ - public static Executor uiThreadExecutor() { + public static @NonNull Executor uiThreadExecutor() { return new UiThreadExecutor(); } diff --git a/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java b/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java index 93f3675d0296..d27cd5e11663 100644 --- a/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java +++ b/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/GoogleSignInPlugin.java @@ -5,6 +5,7 @@ package io.flutter.plugins.googlesignin; import android.accounts.Account; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.Intent; @@ -39,6 +40,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; @@ -61,7 +63,8 @@ public class GoogleSignInPlugin implements MethodCallHandler, FlutterPlugin, Act private ActivityPluginBinding activityPluginBinding; @SuppressWarnings("deprecation") - public static void registerWith(@NonNull io.flutter.plugin.common.PluginRegistry.Registrar registrar) { + public static void registerWith( + @NonNull io.flutter.plugin.common.PluginRegistry.Registrar registrar) { GoogleSignInPlugin instance = new GoogleSignInPlugin(); instance.initInstance(registrar.messenger(), registrar.context(), new GoogleSignInWrapper()); instance.setUpRegistrar(registrar); @@ -69,7 +72,9 @@ public static void registerWith(@NonNull io.flutter.plugin.common.PluginRegistry @VisibleForTesting public void initInstance( - BinaryMessenger messenger, Context context, GoogleSignInWrapper googleSignInWrapper) { + @NonNull BinaryMessenger messenger, + @NonNull Context context, + @NonNull GoogleSignInWrapper googleSignInWrapper) { channel = new MethodChannel(messenger, CHANNEL_NAME); delegate = new Delegate(context, googleSignInWrapper); channel.setMethodCallHandler(this); @@ -77,7 +82,7 @@ public void initInstance( @VisibleForTesting @SuppressWarnings("deprecation") - public void setUpRegistrar(PluginRegistry.Registrar registrar) { + public void setUpRegistrar(@NonNull PluginRegistry.Registrar registrar) { delegate.setUpRegistrar(registrar); } @@ -121,7 +126,8 @@ public void onDetachedFromActivityForConfigChanges() { } @Override - public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding activityPluginBinding) { + public void onReattachedToActivityForConfigChanges( + @NonNull ActivityPluginBinding activityPluginBinding) { attachToActivity(activityPluginBinding); } @@ -134,12 +140,13 @@ public void onDetachedFromActivity() { public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { switch (call.method) { case METHOD_INIT: - String signInOption = call.argument("signInOption"); - List requestedScopes = call.argument("scopes"); + String signInOption = Objects.requireNonNull(call.argument("signInOption")); + List requestedScopes = Objects.requireNonNull(call.argument("scopes")); String hostedDomain = call.argument("hostedDomain"); String clientId = call.argument("clientId"); String serverClientId = call.argument("serverClientId"); - boolean forceCodeForRefreshToken = call.argument("forceCodeForRefreshToken"); + boolean forceCodeForRefreshToken = + Objects.requireNonNull(call.argument("forceCodeForRefreshToken")); delegate.init( result, signInOption, @@ -159,8 +166,8 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { break; case METHOD_GET_TOKENS: - String email = call.argument("email"); - boolean shouldRecoverAuth = call.argument("shouldRecoverAuth"); + String email = Objects.requireNonNull(call.argument("email")); + boolean shouldRecoverAuth = Objects.requireNonNull(call.argument("shouldRecoverAuth")); delegate.getTokens(result, email, shouldRecoverAuth); break; @@ -169,7 +176,7 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { break; case METHOD_CLEAR_AUTH_CACHE: - String token = call.argument("token"); + String token = Objects.requireNonNull(call.argument("token")); delegate.clearAuthCache(result, token); break; @@ -182,7 +189,7 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { break; case METHOD_REQUEST_SCOPES: - List scopes = call.argument("scopes"); + List scopes = Objects.requireNonNull(call.argument("scopes")); delegate.requestScopes(result, scopes); break; @@ -199,25 +206,25 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { public interface IDelegate { /** Initializes this delegate so that it is ready to perform other operations. */ void init( - Result result, - String signInOption, - List requestedScopes, - String hostedDomain, - String clientId, - String serverClientId, + @NonNull Result result, + @NonNull String signInOption, + @NonNull List requestedScopes, + @Nullable String hostedDomain, + @Nullable String clientId, + @Nullable String serverClientId, boolean forceCodeForRefreshToken); /** * Returns the account information for the user who is signed in to this app. If no user is * signed in, tries to sign the user in without displaying any user interface. */ - void signInSilently(Result result); + void signInSilently(@NonNull Result result); /** * Signs the user in via the sign-in user interface, including the OAuth consent flow if scopes * were requested. */ - void signIn(Result result); + void signIn(@NonNull Result result); /** * Gets an OAuth access token with the scopes that were specified during initialization for the @@ -226,28 +233,29 @@ void init( *

If shouldRecoverAuth is set to true and user needs to recover authentication for method to * complete, the method will attempt to recover authentication and rerun method. */ - void getTokens(final Result result, final String email, final boolean shouldRecoverAuth); + void getTokens( + final @NonNull Result result, final @NonNull String email, final boolean shouldRecoverAuth); /** * Clears the token from any client cache forcing the next {@link #getTokens} call to fetch a * new one. */ - void clearAuthCache(final Result result, final String token); + void clearAuthCache(final @NonNull Result result, final @NonNull String token); /** * Signs the user out. Their credentials may remain valid, meaning they'll be able to silently * sign back in. */ - void signOut(Result result); + void signOut(@NonNull Result result); /** Signs the user out, and revokes their credentials. */ - void disconnect(Result result); + void disconnect(@NonNull Result result); /** Checks if there is a signed in user. */ - void isSignedIn(Result result); + void isSignedIn(@NonNull Result result); /** Prompts the user to grant an additional Oauth scopes. */ - void requestScopes(final Result result, final List scopes); + void requestScopes(final @NonNull Result result, final @NonNull List scopes); } /** @@ -277,12 +285,12 @@ public static class Delegate implements IDelegate, PluginRegistry.ActivityResult private static final String DEFAULT_SIGN_IN = "SignInOption.standard"; private static final String DEFAULT_GAMES_SIGN_IN = "SignInOption.games"; - private final Context context; + private final @NonNull Context context; // Only set registrar for v1 embedder. @SuppressWarnings("deprecation") private PluginRegistry.Registrar registrar; // Only set activity for v2 embedder. Always access activity from getActivity() method. - private Activity activity; + private @Nullable Activity activity; private final BackgroundTaskRunner backgroundTaskRunner = new BackgroundTaskRunner(1); private final GoogleSignInWrapper googleSignInWrapper; @@ -290,23 +298,23 @@ public static class Delegate implements IDelegate, PluginRegistry.ActivityResult private List requestedScopes; private PendingOperation pendingOperation; - public Delegate(Context context, GoogleSignInWrapper googleSignInWrapper) { + public Delegate(@NonNull Context context, @NonNull GoogleSignInWrapper googleSignInWrapper) { this.context = context; this.googleSignInWrapper = googleSignInWrapper; } @SuppressWarnings("deprecation") - public void setUpRegistrar(PluginRegistry.Registrar registrar) { + public void setUpRegistrar(@NonNull PluginRegistry.Registrar registrar) { this.registrar = registrar; registrar.addActivityResultListener(this); } - public void setActivity(Activity activity) { + public void setActivity(@Nullable Activity activity) { this.activity = activity; } // Only access activity with this method. - public Activity getActivity() { + public @Nullable Activity getActivity() { return registrar != null ? registrar.activity() : activity; } @@ -328,12 +336,12 @@ private void checkAndSetPendingOperation(String method, Result result, Object da */ @Override public void init( - Result result, - String signInOption, - List requestedScopes, - String hostedDomain, - String clientId, - String serverClientId, + @NonNull Result result, + @NonNull String signInOption, + @NonNull List requestedScopes, + @Nullable String hostedDomain, + @Nullable String clientId, + @Nullable String serverClientId, boolean forceCodeForRefreshToken) { try { GoogleSignInOptions.Builder optionsBuilder; @@ -368,6 +376,7 @@ public void init( // by the google-services Gradle script. // TODO(jackson): Perhaps we should provide a mechanism to override this // behavior. + @SuppressLint("DiscouragedApi") int webClientIdIdentifier = context .getResources() @@ -400,15 +409,14 @@ public void init( * signed in, tries to sign the user in without displaying any user interface. */ @Override - public void signInSilently(Result result) { + public void signInSilently(@NonNull Result result) { checkAndSetPendingOperation(METHOD_SIGN_IN_SILENTLY, result); Task task = signInClient.silentSignIn(); if (task.isComplete()) { // There's immediate result available. onSignInResult(task); } else { - task.addOnCompleteListener( - this::onSignInResult); + task.addOnCompleteListener(this::onSignInResult); } } @@ -417,7 +425,7 @@ public void signInSilently(Result result) { * were requested. */ @Override - public void signIn(Result result) { + public void signIn(@NonNull Result result) { if (getActivity() == null) { throw new IllegalStateException("signIn needs a foreground activity"); } @@ -432,47 +440,47 @@ public void signIn(Result result) { * sign back in. */ @Override - public void signOut(Result result) { + public void signOut(@NonNull Result result) { checkAndSetPendingOperation(METHOD_SIGN_OUT, result); signInClient .signOut() .addOnCompleteListener( - task -> { - if (task.isSuccessful()) { - finishWithSuccess(null); - } else { - finishWithError(ERROR_REASON_STATUS, "Failed to signout."); - } - }); + task -> { + if (task.isSuccessful()) { + finishWithSuccess(null); + } else { + finishWithError(ERROR_REASON_STATUS, "Failed to signout."); + } + }); } /** Signs the user out, and revokes their credentials. */ @Override - public void disconnect(Result result) { + public void disconnect(@NonNull Result result) { checkAndSetPendingOperation(METHOD_DISCONNECT, result); signInClient .revokeAccess() .addOnCompleteListener( - task -> { - if (task.isSuccessful()) { - finishWithSuccess(null); - } else { - finishWithError(ERROR_REASON_STATUS, "Failed to disconnect."); - } - }); + task -> { + if (task.isSuccessful()) { + finishWithSuccess(null); + } else { + finishWithError(ERROR_REASON_STATUS, "Failed to disconnect."); + } + }); } /** Checks if there is a signed in user. */ @Override - public void isSignedIn(final Result result) { + public void isSignedIn(final @NonNull Result result) { boolean value = GoogleSignIn.getLastSignedInAccount(context) != null; result.success(value); } @Override - public void requestScopes(Result result, List scopes) { + public void requestScopes(@NonNull Result result, @NonNull List scopes) { checkAndSetPendingOperation(METHOD_REQUEST_SCOPES, result); GoogleSignInAccount account = googleSignInWrapper.getLastSignedInAccount(context); @@ -566,26 +574,26 @@ private static class PendingOperation { /** Clears the token kept in the client side cache. */ @Override - public void clearAuthCache(final Result result, final String token) { + public void clearAuthCache(final @NonNull Result result, final @NonNull String token) { Callable clearTokenTask = - () -> { - GoogleAuthUtil.clearToken(context, token); - return null; - }; + () -> { + GoogleAuthUtil.clearToken(context, token); + return null; + }; backgroundTaskRunner.runInBackground( clearTokenTask, - clearTokenFuture -> { - try { - result.success(clearTokenFuture.get()); - } catch (ExecutionException e) { - @Nullable Throwable cause = e.getCause(); - result.error(ERROR_REASON_EXCEPTION, cause == null ? null : cause.getMessage(), null); - } catch (InterruptedException e) { - result.error(ERROR_REASON_EXCEPTION, e.getMessage(), null); - Thread.currentThread().interrupt(); - } - }); + clearTokenFuture -> { + try { + result.success(clearTokenFuture.get()); + } catch (ExecutionException e) { + @Nullable Throwable cause = e.getCause(); + result.error(ERROR_REASON_EXCEPTION, cause == null ? null : cause.getMessage(), null); + } catch (InterruptedException e) { + result.error(ERROR_REASON_EXCEPTION, e.getMessage(), null); + Thread.currentThread().interrupt(); + } + }); } /** @@ -597,62 +605,60 @@ public void clearAuthCache(final Result result, final String token) { */ @Override public void getTokens( - final Result result, final String email, final boolean shouldRecoverAuth) { - if (email == null) { - result.error(ERROR_REASON_EXCEPTION, "Email is null", null); - return; - } - + @NonNull final Result result, + @NonNull final String email, + final boolean shouldRecoverAuth) { Callable getTokenTask = - () -> { - Account account = new Account(email, "com.google"); - String scopesStr = "oauth2:" + Joiner.on(' ').join(requestedScopes); - return GoogleAuthUtil.getToken(context, account, scopesStr); - }; + () -> { + Account account = new Account(email, "com.google"); + String scopesStr = "oauth2:" + Joiner.on(' ').join(requestedScopes); + return GoogleAuthUtil.getToken(context, account, scopesStr); + }; // Background task runner has a single thread effectively serializing // the getToken calls. 1p apps can then enjoy the token cache if multiple // getToken calls are coming in. backgroundTaskRunner.runInBackground( getTokenTask, - tokenFuture -> { - try { - String token = tokenFuture.get(); - HashMap tokenResult = new HashMap<>(); - tokenResult.put("accessToken", token); - result.success(tokenResult); - } catch (ExecutionException e) { - if (e.getCause() instanceof UserRecoverableAuthException) { - if (shouldRecoverAuth && pendingOperation == null) { - Activity activity = getActivity(); - if (activity == null) { - result.error( - ERROR_USER_RECOVERABLE_AUTH, - "Cannot recover auth because app is not in foreground. " - + e.getLocalizedMessage(), - null); - } else { - checkAndSetPendingOperation(METHOD_GET_TOKENS, result, email); - Intent recoveryIntent = - ((UserRecoverableAuthException) e.getCause()).getIntent(); - activity.startActivityForResult(recoveryIntent, REQUEST_CODE_RECOVER_AUTH); - } - } else { - result.error(ERROR_USER_RECOVERABLE_AUTH, e.getLocalizedMessage(), null); - } + tokenFuture -> { + try { + String token = tokenFuture.get(); + HashMap tokenResult = new HashMap<>(); + tokenResult.put("accessToken", token); + result.success(tokenResult); + } catch (ExecutionException e) { + if (e.getCause() instanceof UserRecoverableAuthException) { + if (shouldRecoverAuth && pendingOperation == null) { + Activity activity = getActivity(); + if (activity == null) { + result.error( + ERROR_USER_RECOVERABLE_AUTH, + "Cannot recover auth because app is not in foreground. " + + e.getLocalizedMessage(), + null); } else { - @Nullable Throwable cause = e.getCause(); - result.error(ERROR_REASON_EXCEPTION, cause == null ? null : cause.getMessage(), null); + checkAndSetPendingOperation(METHOD_GET_TOKENS, result, email); + Intent recoveryIntent = + ((UserRecoverableAuthException) e.getCause()).getIntent(); + activity.startActivityForResult(recoveryIntent, REQUEST_CODE_RECOVER_AUTH); } - } catch (InterruptedException e) { - result.error(ERROR_REASON_EXCEPTION, e.getMessage(), null); - Thread.currentThread().interrupt(); + } else { + result.error(ERROR_USER_RECOVERABLE_AUTH, e.getLocalizedMessage(), null); } - }); + } else { + @Nullable Throwable cause = e.getCause(); + result.error( + ERROR_REASON_EXCEPTION, cause == null ? null : cause.getMessage(), null); + } + } catch (InterruptedException e) { + result.error(ERROR_REASON_EXCEPTION, e.getMessage(), null); + Thread.currentThread().interrupt(); + } + }); } @Override - public boolean onActivityResult(int requestCode, int resultCode, Intent data) { + public boolean onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { if (pendingOperation == null) { return false; } diff --git a/packages/google_sign_in/google_sign_in_android/lib/google_sign_in_android.dart b/packages/google_sign_in/google_sign_in_android/lib/google_sign_in_android.dart index 5a2ccab3250b..ce651d7e8dc4 100644 --- a/packages/google_sign_in/google_sign_in_android/lib/google_sign_in_android.dart +++ b/packages/google_sign_in/google_sign_in_android/lib/google_sign_in_android.dart @@ -70,7 +70,7 @@ class GoogleSignInAndroid extends GoogleSignInPlatform { return channel .invokeMapMethod('getTokens', { 'email': email, - 'shouldRecoverAuth': shouldRecoverAuth, + 'shouldRecoverAuth': shouldRecoverAuth ?? true, }).then((Map? result) => getTokenDataFromMap(result!)); } From c2b08d6b6ee5e467cdb35bb8174d5c5f757eb167 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 19 Apr 2023 12:31:33 -0400 Subject: [PATCH 4/6] Add a test for the channenl bug fix --- .../test/google_sign_in_android_test.dart | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/google_sign_in/google_sign_in_android/test/google_sign_in_android_test.dart b/packages/google_sign_in/google_sign_in_android/test/google_sign_in_android_test.dart index b70d2e7bffa6..671d7683b2f6 100644 --- a/packages/google_sign_in/google_sign_in_android/test/google_sign_in_android_test.dart +++ b/packages/google_sign_in/google_sign_in_android/test/google_sign_in_android_test.dart @@ -103,6 +103,17 @@ void main() { })); }); + test('getTokens will not pass null for shouldRecoverAuth', () async { + await googleSignIn.getTokens( + email: 'example@example.com', shouldRecoverAuth: null); + expect( + log[0], + isMethodCall('getTokens', arguments: { + 'email': 'example@example.com', + 'shouldRecoverAuth': true, + })); + }); + test('Other functions pass through arguments to the channel', () async { final Map tests = { () { From a60133f672e1488c8819f7718609392b73282634 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 19 Apr 2023 17:09:24 -0400 Subject: [PATCH 5/6] Version bump --- packages/google_sign_in/google_sign_in_android/CHANGELOG.md | 4 ++++ packages/google_sign_in/google_sign_in_android/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/google_sign_in/google_sign_in_android/CHANGELOG.md b/packages/google_sign_in/google_sign_in_android/CHANGELOG.md index a419d902e70f..4f4f6dd7561b 100644 --- a/packages/google_sign_in/google_sign_in_android/CHANGELOG.md +++ b/packages/google_sign_in/google_sign_in_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.1.11 + +* Fixes Java warnings. + ## 6.1.10 * Sets an explicit Java compatibility version. diff --git a/packages/google_sign_in/google_sign_in_android/pubspec.yaml b/packages/google_sign_in/google_sign_in_android/pubspec.yaml index b6e892f50c64..921e7f1d9d33 100644 --- a/packages/google_sign_in/google_sign_in_android/pubspec.yaml +++ b/packages/google_sign_in/google_sign_in_android/pubspec.yaml @@ -2,7 +2,7 @@ name: google_sign_in_android description: Android implementation of the google_sign_in plugin. repository: https://github.com/flutter/packages/tree/main/packages/google_sign_in/google_sign_in_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_sign_in%22 -version: 6.1.10 +version: 6.1.11 environment: sdk: ">=2.17.0 <4.0.0" From 37425eff287acbcef173e5871f766c90e90d1e09 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 19 Apr 2023 17:14:15 -0400 Subject: [PATCH 6/6] Fix unit test that was passing invalid arguments --- .../io/flutter/plugins/googlesignin/GoogleSignInTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/google_sign_in/google_sign_in_android/android/src/test/java/io/flutter/plugins/googlesignin/GoogleSignInTest.java b/packages/google_sign_in/google_sign_in_android/android/src/test/java/io/flutter/plugins/googlesignin/GoogleSignInTest.java index cbd2e40c433f..627ac40a4823 100644 --- a/packages/google_sign_in/google_sign_in_android/android/src/test/java/io/flutter/plugins/googlesignin/GoogleSignInTest.java +++ b/packages/google_sign_in/google_sign_in_android/android/src/test/java/io/flutter/plugins/googlesignin/GoogleSignInTest.java @@ -75,7 +75,9 @@ public void tearDown() throws Exception { @Test public void requestScopes_ResultErrorIfAccountIsNull() { - MethodCall methodCall = new MethodCall("requestScopes", null); + HashMap> arguments = new HashMap<>(); + arguments.put("scopes", Collections.singletonList("requestedScope")); + MethodCall methodCall = new MethodCall("requestScopes", arguments); when(mockGoogleSignIn.getLastSignedInAccount(mockContext)).thenReturn(null); plugin.onMethodCall(methodCall, result); verify(result).error("sign_in_required", "No account to grant scopes.", null);