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 75dcc58af33..5d2419a2c83 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.35
+
+* Removes the dependency on the Guava library.
+
## 6.1.34
* Removes unnecessary native code.
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 11fb6c7a710..6ce621afccb 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
@@ -57,7 +57,6 @@ android {
dependencies {
implementation 'com.google.android.gms:play-services-auth:21.0.0'
- implementation 'com.google.guava:guava:33.3.1-android'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.mockito:mockito-inline:5.0.0'
}
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
deleted file mode 100644
index 4fc0afadd4d..00000000000
--- a/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/BackgroundTaskRunner.java
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-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;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Future;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-/**
- * A class for running tasks in a background thread.
- *
- *
TODO(jackson): If this class is useful for other plugins, consider including it in a shared
- * library or in the Flutter engine
- */
-public final class BackgroundTaskRunner {
-
- /**
- * Interface that callers of this API can implement to be notified when a {@link
- * #runInBackground(Callable,Callback) background task} has completed.
- */
- public interface Callback {
- /**
- * Invoked on the UI thread when the specified future has completed (calling {@code get()} on
- * the future is guaranteed not to block). If the future completed with an exception, then
- * {@code get()} will throw an {@code ExecutionException}.
- */
- void run(@NonNull Future future);
- }
-
- private final ThreadPoolExecutor executor;
-
- /**
- * Creates a new background processor with the given number of threads.
- *
- * @param threads The fixed number of threads in ther pool.
- */
- public BackgroundTaskRunner(int threads) {
- BlockingQueue workQueue = new LinkedBlockingQueue<>();
- // Only keeps idle threads open for 1 second if we've got more threads than cores.
- executor = new ThreadPoolExecutor(threads, threads, 1, TimeUnit.SECONDS, workQueue);
- }
-
- /**
- * Executes the specified task in a background thread and notifies the specified callback once the
- * task has completed (either successfully or with an exception).
- *
- *
The callback will be notified on the UI thread.
- */
- public void runInBackground(@NonNull Callable task, final @NonNull Callback callback) {
- final ListenableFuture future = runInBackground(task);
- future.addListener(() -> callback.run(future), Executors.uiThreadExecutor());
- }
-
- /**
- * Executes the specified task in a background thread and returns a future with which the caller
- * can be notified of task completion.
- *
- *
Note: the future will be notified on the background thread. To be notified on the UI thread,
- * use {@link #runInBackground(Callable,Callback)}.
- */
- 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);
- }
- }
- });
-
- 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
deleted file mode 100644
index 89f5c22acf2..00000000000
--- a/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/Executors.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package io.flutter.plugins.googlesignin;
-
-import android.os.Handler;
-import android.os.Looper;
-import androidx.annotation.NonNull;
-import java.util.concurrent.Executor;
-
-/**
- * Factory and utility methods for {@code Executor}.
- *
- *
TODO(jackson): If this class is useful for other plugins, consider including it in a shared
- * library or in the Flutter engine
- */
-public final class Executors {
-
- static final class UiThreadExecutor implements Executor {
- private static final Handler UI_THREAD = new Handler(Looper.getMainLooper());
-
- @Override
- public void execute(Runnable command) {
- UI_THREAD.post(command);
- }
- }
-
- /** Returns an {@code Executor} that will post commands to the UI thread. */
- public static @NonNull Executor uiThreadExecutor() {
- return new UiThreadExecutor();
- }
-
- // Should never be instantiated.
- private Executors() {}
-}
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 92f3f9927df..127c7c281f8 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
@@ -9,6 +9,8 @@
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
+import android.os.Handler;
+import android.os.Looper;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -25,8 +27,6 @@
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.tasks.RuntimeExecutionException;
import com.google.android.gms.tasks.Task;
-import com.google.common.base.Joiner;
-import com.google.common.base.Strings;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
@@ -37,8 +37,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
/** Google sign-in plugin for Flutter. */
public class GoogleSignInPlugin implements FlutterPlugin, ActivityAware {
@@ -135,8 +133,6 @@ public static class Delegate implements PluginRegistry.ActivityResultListener, G
private final @NonNull Context context;
// Only set activity for v2 embedder. Always access activity from getActivity() method.
private @Nullable Activity activity;
- // TODO(stuartmorgan): See whether this can be replaced with background channels.
- private final BackgroundTaskRunner backgroundTaskRunner = new BackgroundTaskRunner(1);
private final GoogleSignInWrapper googleSignInWrapper;
private GoogleSignInClient signInClient;
@@ -224,7 +220,7 @@ public void init(@NonNull Messages.InitParams params) {
// https://developers.google.com/android/guides/client-auth
// https://developers.google.com/identity/sign-in/android/start#configure-a-google-api-project
String serverClientId = params.getServerClientId();
- if (!Strings.isNullOrEmpty(params.getClientId()) && Strings.isNullOrEmpty(serverClientId)) {
+ if (!isNullOrEmpty(params.getClientId()) && isNullOrEmpty(serverClientId)) {
Log.w(
"google_sign_in",
"clientId is not supported on Android and is interpreted as serverClientId. "
@@ -232,7 +228,7 @@ public void init(@NonNull Messages.InitParams params) {
serverClientId = params.getClientId();
}
- if (Strings.isNullOrEmpty(serverClientId)) {
+ if (isNullOrEmpty(serverClientId)) {
// Only requests a clientId if google-services.json was present and parsed
// by the google-services Gradle script.
// TODO(jackson): Perhaps we should provide a mechanism to override this
@@ -246,7 +242,7 @@ public void init(@NonNull Messages.InitParams params) {
serverClientId = context.getString(webClientIdIdentifier);
}
}
- if (!Strings.isNullOrEmpty(serverClientId)) {
+ if (!isNullOrEmpty(serverClientId)) {
optionsBuilder.requestIdToken(serverClientId);
optionsBuilder.requestServerAuthCode(
serverClientId, params.getForceCodeForRefreshToken());
@@ -255,7 +251,7 @@ public void init(@NonNull Messages.InitParams params) {
for (String scope : requestedScopes) {
optionsBuilder.requestScopes(new Scope(scope));
}
- if (!Strings.isNullOrEmpty(params.getHostedDomain())) {
+ if (!isNullOrEmpty(params.getHostedDomain())) {
optionsBuilder.setHostedDomain(params.getHostedDomain());
}
@@ -450,6 +446,10 @@ private void finishWithError(String errorCode, String errorMessage) {
pendingOperation = null;
}
+ private static boolean isNullOrEmpty(@Nullable String s) {
+ return s == null || s.isEmpty();
+ }
+
private static class PendingOperation {
final @NonNull String method;
final @Nullable Messages.Result userDataResult;
@@ -478,37 +478,26 @@ private static class PendingOperation {
}
}
- /** Clears the token kept in the client side cache. */
+ /**
+ * Clears the token kept in the client side cache.
+ *
+ *
Runs on a background task queue.
+ */
@Override
- public void clearAuthCache(@NonNull String token, @NonNull Messages.VoidResult result) {
- Callable clearTokenTask =
- () -> {
- GoogleAuthUtil.clearToken(context, token);
- return null;
- };
-
- backgroundTaskRunner.runInBackground(
- clearTokenTask,
- clearTokenFuture -> {
- try {
- clearTokenFuture.get();
- result.success();
- } catch (ExecutionException e) {
- @Nullable Throwable cause = e.getCause();
- result.error(
- new FlutterError(
- ERROR_REASON_EXCEPTION, cause == null ? null : cause.getMessage(), null));
- } catch (InterruptedException e) {
- result.error(new FlutterError(ERROR_REASON_EXCEPTION, e.getMessage(), null));
- Thread.currentThread().interrupt();
- }
- });
+ public void clearAuthCache(@NonNull String token) {
+ try {
+ GoogleAuthUtil.clearToken(context, token);
+ } catch (Exception e) {
+ throw new FlutterError(ERROR_REASON_EXCEPTION, e.getMessage(), null);
+ }
}
/**
* Gets an OAuth access token with the scopes that were specified during initialization for the
* user with the specified email address.
*
+ *
Runs on a background task queue.
+ *
*
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.
*/
@@ -517,53 +506,39 @@ public void getAccessToken(
@NonNull String email,
@NonNull Boolean shouldRecoverAuth,
@NonNull Messages.Result result) {
- Callable getTokenTask =
- () -> {
- 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 {
- result.success(tokenFuture.get());
- } catch (ExecutionException e) {
- if (e.getCause() instanceof UserRecoverableAuthException) {
- if (shouldRecoverAuth && pendingOperation == null) {
- Activity activity = getActivity();
- if (activity == null) {
- result.error(
- new FlutterError(
- ERROR_USER_RECOVERABLE_AUTH,
- "Cannot recover auth because app is not in foreground. "
- + e.getLocalizedMessage(),
- null));
- } else {
- checkAndSetPendingAccessTokenOperation("getTokens", result, email);
- Intent recoveryIntent =
- ((UserRecoverableAuthException) e.getCause()).getIntent();
- activity.startActivityForResult(recoveryIntent, REQUEST_CODE_RECOVER_AUTH);
- }
- } else {
+ try {
+ Account account = new Account(email, "com.google");
+ String scopesStr = "oauth2:" + String.join(" ", requestedScopes);
+ String token = GoogleAuthUtil.getToken(context, account, scopesStr);
+ result.success(token);
+ } catch (UserRecoverableAuthException e) {
+ // This method runs in a background task queue; hop to the main thread for interactions with
+ // plugin state and activities.
+ final Handler handler = new Handler(Looper.getMainLooper());
+ handler.post(
+ () -> {
+ if (shouldRecoverAuth && pendingOperation == null) {
+ Activity activity = getActivity();
+ if (activity == null) {
result.error(
- new FlutterError(ERROR_USER_RECOVERABLE_AUTH, e.getLocalizedMessage(), null));
+ new FlutterError(
+ ERROR_USER_RECOVERABLE_AUTH,
+ "Cannot recover auth because app is not in foreground. "
+ + e.getLocalizedMessage(),
+ null));
+ } else {
+ checkAndSetPendingAccessTokenOperation("getTokens", result, email);
+ Intent recoveryIntent = e.getIntent();
+ activity.startActivityForResult(recoveryIntent, REQUEST_CODE_RECOVER_AUTH);
}
} else {
- @Nullable Throwable cause = e.getCause();
result.error(
- new FlutterError(
- ERROR_REASON_EXCEPTION, cause == null ? null : cause.getMessage(), null));
+ new FlutterError(ERROR_USER_RECOVERABLE_AUTH, e.getLocalizedMessage(), null));
}
- } catch (InterruptedException e) {
- result.error(new FlutterError(ERROR_REASON_EXCEPTION, e.getMessage(), null));
- Thread.currentThread().interrupt();
- }
- });
+ });
+ } catch (Exception e) {
+ result.error(new FlutterError(ERROR_REASON_EXCEPTION, e.getMessage(), null));
+ }
}
@Override
diff --git a/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/Messages.java b/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/Messages.java
index 2bf6b6c1e06..e93f2bc6689 100644
--- a/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/Messages.java
+++ b/packages/google_sign_in/google_sign_in_android/android/src/main/java/io/flutter/plugins/googlesignin/Messages.java
@@ -1,7 +1,7 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Autogenerated from Pigeon (v22.4.2), do not edit directly.
+// Autogenerated from Pigeon (v24.2.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
package io.flutter.plugins.googlesignin;
@@ -547,7 +547,7 @@ void getAccessToken(
@NonNull
Boolean isSignedIn();
/** Clears the authentication caching for the given token, requiring a new sign in. */
- void clearAuthCache(@NonNull String token, @NonNull VoidResult result);
+ void clearAuthCache(@NonNull String token);
/** Requests access to the given scopes. */
void requestScopes(@NonNull List scopes, @NonNull Result result);
@@ -567,6 +567,7 @@ static void setUp(
@NonNull String messageChannelSuffix,
@Nullable GoogleSignInApi api) {
messageChannelSuffix = messageChannelSuffix.isEmpty() ? "" : "." + messageChannelSuffix;
+ BinaryMessenger.TaskQueue taskQueue = binaryMessenger.makeBackgroundTaskQueue();
{
BasicMessageChannel