From ebe5367e4d31150718db4de23c0448efaa501ef9 Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Mon, 9 Dec 2024 09:44:17 -0800 Subject: [PATCH 01/24] [google_sign_in] Clean up Java code (#8241) Removes the legacy public native interface to the sign-in plugin, which was inherently linked to raw method channels (which we no longer use) and the structure of the Google Sign-In native SDK (which is deprecated), so we don't want to continue supporting. I (unsurprisingly, as native->native plugin dependencies are very rare) can't find any evidence that any public plugin has ever directly used this Java code. The original use case this was added for was internal, and no longer exists (see b/158361263). The test file being deleted is specific to the legacy interface. There is already an almost-exact duplicate of that test file that tests the Pigeon interface. --- .../google_sign_in_android/CHANGELOG.md | 4 + .../googlesignin/GoogleSignInPlugin.java | 345 +--------------- .../GoogleSignInLegacyMethodChannelTest.java | 374 ------------------ .../googlesignin/GoogleSignInTest.java | 2 - .../google_sign_in_android/pubspec.yaml | 2 +- 5 files changed, 9 insertions(+), 718 deletions(-) delete mode 100644 packages/google_sign_in/google_sign_in_android/android/src/test/java/io/flutter/plugins/googlesignin/GoogleSignInLegacyMethodChannelTest.java 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 35af262af528..75dcc58af336 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.34 + +* Removes unnecessary native code. + ## 6.1.33 * Updates Pigeon for non-nullable collection type support. 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 301642bce1e8..92f3f9927df3 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 @@ -31,14 +31,11 @@ import io.flutter.embedding.engine.plugins.activity.ActivityAware; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; import io.flutter.plugin.common.BinaryMessenger; -import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.PluginRegistry; import io.flutter.plugins.googlesignin.Messages.FlutterError; import io.flutter.plugins.googlesignin.Messages.GoogleSignInApi; import java.util.ArrayList; -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; @@ -111,241 +108,16 @@ public void onDetachedFromActivity() { disposeActivity(); } - // TODO(stuartmorgan): Remove this, and convert the unit tests to IDelegate tests. This is left - // here only to allow the existing tests to continue to work unchanged during the Pigeon migration - // to ensure that the refactoring didn't change any behavior, and is not actually used by the - // plugin. - @VisibleForTesting - void onMethodCall( - @NonNull io.flutter.plugin.common.MethodCall call, @NonNull MethodChannel.Result result) { - switch (call.method) { - case "init": - 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 = - Objects.requireNonNull(call.argument("forceCodeForRefreshToken")); - delegate.init( - result, - signInOption, - requestedScopes, - hostedDomain, - clientId, - serverClientId, - forceCodeForRefreshToken); - break; - - case "signInSilently": - delegate.signInSilently(result); - break; - - case "signIn": - delegate.signIn(result); - break; - - case "getTokens": - String email = Objects.requireNonNull(call.argument("email")); - boolean shouldRecoverAuth = Objects.requireNonNull(call.argument("shouldRecoverAuth")); - delegate.getTokens(result, email, shouldRecoverAuth); - break; - - case "signOut": - delegate.signOut(result); - break; - - case "clearAuthCache": - String token = Objects.requireNonNull(call.argument("token")); - delegate.clearAuthCache(result, token); - break; - - case "disconnect": - delegate.disconnect(result); - break; - - case "isSignedIn": - delegate.isSignedIn(result); - break; - - case "requestScopes": - List scopes = Objects.requireNonNull(call.argument("scopes")); - delegate.requestScopes(result, scopes); - break; - - default: - result.notImplemented(); - } - } - - /** - * A delegate interface that exposes all of the sign-in functionality for other plugins to use. - * The below {@link Delegate} implementation should be used by any clients unless they need to - * override some of these functions, such as for testing. - */ - public interface IDelegate { - /** Initializes this delegate so that it is ready to perform other operations. */ - void init( - @NonNull MethodChannel.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(@NonNull MethodChannel.Result result); - - /** - * Signs the user in via the sign-in user interface, including the OAuth consent flow if scopes - * were requested. - */ - void signIn(@NonNull MethodChannel.Result result); - - /** - * Gets an OAuth access token with the scopes that were specified during initialization for the - * user with the specified email address. - * - *

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 @NonNull MethodChannel.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 @NonNull MethodChannel.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(@NonNull MethodChannel.Result result); - - /** Signs the user out, and revokes their credentials. */ - void disconnect(@NonNull MethodChannel.Result result); - - /** Checks if there is a signed in user. */ - void isSignedIn(@NonNull MethodChannel.Result result); - - /** Prompts the user to grant an additional Oauth scopes. */ - void requestScopes( - final @NonNull MethodChannel.Result result, final @NonNull List scopes); - } - - /** - * Helper class for supporting the legacy IDelegate interface based on raw method channels, which - * handles converting any FlutterErrors (or other {@code Throwable}s in case any non- FlutterError - * exceptions slip through) thrown by the new code paths into {@code error} callbacks. - */ - private abstract static class ErrorConvertingMethodChannelVoidResult - implements Messages.VoidResult { - final @NonNull MethodChannel.Result result; - - public ErrorConvertingMethodChannelVoidResult(@NonNull MethodChannel.Result result) { - this.result = result; - } - - @Override - public void error(@NonNull Throwable error) { - if (error instanceof FlutterError) { - FlutterError flutterError = (FlutterError) error; - result.error(flutterError.code, flutterError.getMessage(), flutterError.details); - } else { - result.error("exception", error.getMessage(), null); - } - } - } - - /** - * Helper class for supporting the legacy IDelegate interface based on raw method channels, which - * handles converting any FlutterErrors (or other {@code Throwable}s in case any non- FlutterError - * exceptions slip through) thrown by the new code paths into {@code error} callbacks. - * - * @param The Result type of the result to convert from. - */ - private abstract static class ErrorConvertingMethodChannelResult - implements Messages.Result { - final @NonNull MethodChannel.Result result; - - public ErrorConvertingMethodChannelResult(@NonNull MethodChannel.Result result) { - this.result = result; - } - - @Override - public void error(@NonNull Throwable error) { - if (error instanceof FlutterError) { - FlutterError flutterError = (FlutterError) error; - result.error(flutterError.code, flutterError.getMessage(), flutterError.details); - } else { - result.error("exception", error.getMessage(), null); - } - } - } - - /** - * Helper class for supporting the legacy IDelegate interface based on raw method channels, which - * handles converting responses from methods that return {@code Messages.UserData}. - */ - private static class UserDataMethodChannelResult - extends ErrorConvertingMethodChannelResult { - public UserDataMethodChannelResult(MethodChannel.Result result) { - super(result); - } - - @Override - public void success(Messages.UserData data) { - Map response = new HashMap<>(); - response.put("email", data.getEmail()); - response.put("id", data.getId()); - response.put("idToken", data.getIdToken()); - response.put("serverAuthCode", data.getServerAuthCode()); - response.put("displayName", data.getDisplayName()); - if (data.getPhotoUrl() != null) { - response.put("photoUrl", data.getPhotoUrl()); - } - result.success(response); - } - } - - /** - * Helper class for supporting the legacy IDelegate interface based on raw method channels, which - * handles converting responses from methods that return {@code Void}. - */ - private static class VoidMethodChannelResult extends ErrorConvertingMethodChannelVoidResult { - public VoidMethodChannelResult(MethodChannel.Result result) { - super(result); - } - - @Override - public void success() { - result.success(null); - } - } - /** * Delegate class that does the work for the Google sign-in plugin. This is exposed as a dedicated * class for use in other plugins that wrap basic sign-in functionality. * *

All methods in this class assume that they are run to completion before any other method is - * invoked. In this context, "run to completion" means that their {@link MethodChannel.Result} - * argument has been completed (either successfully or in error). This class provides no - * synchronization constructs to guarantee such behavior; callers are responsible for providing - * such guarantees. + * invoked. In this context, "run to completion" means that their {@link Messages.Result} argument + * has been completed (either successfully or in error). This class provides no synchronization + * constructs to guarantee such behavior; callers are responsible for providing such guarantees. */ - // TODO(stuartmorgan): Remove this in a breaking change, replacing it with something using - // structured types rather than strings and dictionaries left over from the pre-Pigeon method - // channel implementation. - public static class Delegate - implements IDelegate, PluginRegistry.ActivityResultListener, GoogleSignInApi { + public static class Delegate implements PluginRegistry.ActivityResultListener, GoogleSignInApi { private static final int REQUEST_CODE_SIGNIN = 53293; private static final int REQUEST_CODE_RECOVER_AUTH = 53294; @VisibleForTesting static final int REQUEST_CODE_REQUEST_SCOPE = 53295; @@ -360,9 +132,6 @@ public static class Delegate private static final String ERROR_FAILURE_TO_RECOVER_AUTH = "failed_to_recover_auth"; private static final String ERROR_USER_RECOVERABLE_AUTH = "user_recoverable_auth"; - private static final String DEFAULT_SIGN_IN = "SignInOption.standard"; - private static final String DEFAULT_GAMES_SIGN_IN = "SignInOption.games"; - private final @NonNull Context context; // Only set activity for v2 embedder. Always access activity from getActivity() method. private @Nullable Activity activity; @@ -496,43 +265,6 @@ public void init(@NonNull Messages.InitParams params) { } } - // IDelegate version, for backwards compatibility. - @Override - public void init( - @NonNull MethodChannel.Result result, - @NonNull String signInOption, - @NonNull List requestedScopes, - @Nullable String hostedDomain, - @Nullable String clientId, - @Nullable String serverClientId, - boolean forceCodeForRefreshToken) { - try { - Messages.SignInType type; - switch (signInOption) { - case DEFAULT_GAMES_SIGN_IN: - type = Messages.SignInType.GAMES; - break; - case DEFAULT_SIGN_IN: - type = Messages.SignInType.STANDARD; - break; - default: - throw new IllegalStateException("Unknown signInOption"); - } - init( - new Messages.InitParams.Builder() - .setSignInType(type) - .setScopes(requestedScopes) - .setHostedDomain(hostedDomain) - .setClientId(clientId) - .setServerClientId(serverClientId) - .setForceCodeForRefreshToken(forceCodeForRefreshToken) - .build()); - result.success(null); - } catch (FlutterError e) { - result.error(e.code, e.getMessage(), e.details); - } - } - /** * 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. @@ -549,12 +281,6 @@ public void signInSilently(@NonNull Messages.Result result) { } } - // IDelegate version, for backwards compatibility. - @Override - public void signInSilently(@NonNull MethodChannel.Result result) { - signInSilently(new UserDataMethodChannelResult(result)); - } - /** * Signs the user in via the sign-in user interface, including the OAuth consent flow if scopes * were requested. @@ -570,12 +296,6 @@ public void signIn(@NonNull Messages.Result result) { getActivity().startActivityForResult(signInIntent, REQUEST_CODE_SIGNIN); } - // IDelegate version, for backwards compatibility. - @Override - public void signIn(@NonNull MethodChannel.Result result) { - signIn(new UserDataMethodChannelResult(result)); - } - /** * Signs the user out. Their credentials may remain valid, meaning they'll be able to silently * sign back in. @@ -596,12 +316,6 @@ public void signOut(@NonNull Messages.VoidResult result) { }); } - // IDelegate version, for backwards compatibility. - @Override - public void signOut(@NonNull MethodChannel.Result result) { - signOut(new VoidMethodChannelResult(result)); - } - /** Signs the user out, and revokes their credentials. */ @Override public void disconnect(@NonNull Messages.VoidResult result) { @@ -619,12 +333,6 @@ public void disconnect(@NonNull Messages.VoidResult result) { }); } - // IDelegate version, for backwards compatibility. - @Override - public void disconnect(@NonNull MethodChannel.Result result) { - signOut(new VoidMethodChannelResult(result)); - } - /** Checks if there is a signed in user. */ @NonNull @Override @@ -632,12 +340,6 @@ public Boolean isSignedIn() { return GoogleSignIn.getLastSignedInAccount(context) != null; } - // IDelegate version, for backwards compatibility. - @Override - public void isSignedIn(final @NonNull MethodChannel.Result result) { - result.success(isSignedIn()); - } - @Override public void requestScopes( @NonNull List scopes, @NonNull Messages.Result result) { @@ -667,19 +369,6 @@ public void requestScopes( getActivity(), REQUEST_CODE_REQUEST_SCOPE, account, wrappedScopes.toArray(new Scope[0])); } - // IDelegate version, for backwards compatibility. - @Override - public void requestScopes(@NonNull MethodChannel.Result result, @NonNull List scopes) { - requestScopes( - scopes, - new ErrorConvertingMethodChannelResult(result) { - @Override - public void success(Boolean value) { - result.success(value); - } - }); - } - private void onSignInResult(Task completedTask) { try { GoogleSignInAccount account = completedTask.getResult(ApiException.class); @@ -816,13 +505,6 @@ public void clearAuthCache(@NonNull String token, @NonNull Messages.VoidResult r }); } - // IDelegate version, for backwards compatibility. - @Override - public void clearAuthCache( - final @NonNull MethodChannel.Result result, final @NonNull String token) { - clearAuthCache(token, new VoidMethodChannelResult(result)); - } - /** * Gets an OAuth access token with the scopes that were specified during initialization for the * user with the specified email address. @@ -884,25 +566,6 @@ public void getAccessToken( }); } - // IDelegate version, for backwards compatibility. - @Override - public void getTokens( - @NonNull final MethodChannel.Result result, - @NonNull final String email, - final boolean shouldRecoverAuth) { - getAccessToken( - email, - shouldRecoverAuth, - new ErrorConvertingMethodChannelResult(result) { - @Override - public void success(String value) { - HashMap tokenResult = new HashMap<>(); - tokenResult.put("accessToken", value); - result.success(tokenResult); - } - }); - } - @Override public boolean onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { if (pendingOperation == null) { diff --git a/packages/google_sign_in/google_sign_in_android/android/src/test/java/io/flutter/plugins/googlesignin/GoogleSignInLegacyMethodChannelTest.java b/packages/google_sign_in/google_sign_in_android/android/src/test/java/io/flutter/plugins/googlesignin/GoogleSignInLegacyMethodChannelTest.java deleted file mode 100644 index cd5b92217c65..000000000000 --- a/packages/google_sign_in/google_sign_in_android/android/src/test/java/io/flutter/plugins/googlesignin/GoogleSignInLegacyMethodChannelTest.java +++ /dev/null @@ -1,374 +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 static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import com.google.android.gms.auth.api.signin.GoogleSignInAccount; -import com.google.android.gms.auth.api.signin.GoogleSignInClient; -import com.google.android.gms.auth.api.signin.GoogleSignInOptions; -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.common.api.Status; -import com.google.android.gms.tasks.Task; -import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; -import io.flutter.plugin.common.BinaryMessenger; -import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugin.common.PluginRegistry; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -public class GoogleSignInLegacyMethodChannelTest { - @Mock Context mockContext; - @Mock Resources mockResources; - @Mock Activity mockActivity; - @Mock BinaryMessenger mockMessenger; - @Spy MethodChannel.Result result; - @Mock GoogleSignInWrapper mockGoogleSignIn; - @Mock GoogleSignInAccount account; - @Mock GoogleSignInClient mockClient; - @Mock Task mockSignInTask; - @Mock ActivityPluginBinding mockActivityPluginBinding; - - private GoogleSignInPlugin plugin; - private AutoCloseable mockCloseable; - - @Before - public void setUp() { - mockCloseable = MockitoAnnotations.openMocks(this); - when(mockContext.getResources()).thenReturn(mockResources); - when(mockActivityPluginBinding.getActivity()).thenReturn(mockActivity); - plugin = new GoogleSignInPlugin(); - plugin.initInstance(mockMessenger, mockContext, mockGoogleSignIn); - plugin.onAttachedToActivity(mockActivityPluginBinding); - } - - @After - public void tearDown() throws Exception { - mockCloseable.close(); - } - - @Test - public void requestScopes_ResultErrorIfAccountIsNull() { - 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); - } - - @Test - public void requestScopes_ResultTrueIfAlreadyGranted() { - HashMap> arguments = new HashMap<>(); - arguments.put("scopes", Collections.singletonList("requestedScope")); - - MethodCall methodCall = new MethodCall("requestScopes", arguments); - Scope requestedScope = new Scope("requestedScope"); - when(mockGoogleSignIn.getLastSignedInAccount(mockContext)).thenReturn(account); - when(account.getGrantedScopes()).thenReturn(Collections.singleton(requestedScope)); - when(mockGoogleSignIn.hasPermissions(account, requestedScope)).thenReturn(true); - - plugin.onMethodCall(methodCall, result); - verify(result).success(true); - } - - @Test - public void requestScopes_RequestsPermissionIfNotGranted() { - HashMap> arguments = new HashMap<>(); - arguments.put("scopes", Collections.singletonList("requestedScope")); - MethodCall methodCall = new MethodCall("requestScopes", arguments); - Scope requestedScope = new Scope("requestedScope"); - - when(mockGoogleSignIn.getLastSignedInAccount(mockContext)).thenReturn(account); - when(account.getGrantedScopes()).thenReturn(Collections.singleton(requestedScope)); - when(mockGoogleSignIn.hasPermissions(account, requestedScope)).thenReturn(false); - - plugin.onMethodCall(methodCall, result); - - verify(mockGoogleSignIn) - .requestPermissions(mockActivity, 53295, account, new Scope[] {requestedScope}); - } - - @Test - public void requestScopes_ReturnsFalseIfPermissionDenied() { - HashMap> arguments = new HashMap<>(); - arguments.put("scopes", Collections.singletonList("requestedScope")); - MethodCall methodCall = new MethodCall("requestScopes", arguments); - Scope requestedScope = new Scope("requestedScope"); - - ArgumentCaptor captor = - ArgumentCaptor.forClass(PluginRegistry.ActivityResultListener.class); - verify(mockActivityPluginBinding).addActivityResultListener(captor.capture()); - PluginRegistry.ActivityResultListener listener = captor.getValue(); - - when(mockGoogleSignIn.getLastSignedInAccount(mockContext)).thenReturn(account); - when(account.getGrantedScopes()).thenReturn(Collections.singleton(requestedScope)); - when(mockGoogleSignIn.hasPermissions(account, requestedScope)).thenReturn(false); - - plugin.onMethodCall(methodCall, result); - listener.onActivityResult( - GoogleSignInPlugin.Delegate.REQUEST_CODE_REQUEST_SCOPE, - Activity.RESULT_CANCELED, - new Intent()); - - verify(result).success(false); - } - - @Test - public void requestScopes_ReturnsTrueIfPermissionGranted() { - HashMap> arguments = new HashMap<>(); - arguments.put("scopes", Collections.singletonList("requestedScope")); - MethodCall methodCall = new MethodCall("requestScopes", arguments); - Scope requestedScope = new Scope("requestedScope"); - - ArgumentCaptor captor = - ArgumentCaptor.forClass(PluginRegistry.ActivityResultListener.class); - verify(mockActivityPluginBinding).addActivityResultListener(captor.capture()); - PluginRegistry.ActivityResultListener listener = captor.getValue(); - - when(mockGoogleSignIn.getLastSignedInAccount(mockContext)).thenReturn(account); - when(account.getGrantedScopes()).thenReturn(Collections.singleton(requestedScope)); - when(mockGoogleSignIn.hasPermissions(account, requestedScope)).thenReturn(false); - - plugin.onMethodCall(methodCall, result); - listener.onActivityResult( - GoogleSignInPlugin.Delegate.REQUEST_CODE_REQUEST_SCOPE, Activity.RESULT_OK, new Intent()); - - verify(result).success(true); - } - - @Test - public void requestScopes_mayBeCalledRepeatedly_ifAlreadyGranted() { - HashMap> arguments = new HashMap<>(); - arguments.put("scopes", Collections.singletonList("requestedScope")); - MethodCall methodCall = new MethodCall("requestScopes", arguments); - Scope requestedScope = new Scope("requestedScope"); - - ArgumentCaptor captor = - ArgumentCaptor.forClass(PluginRegistry.ActivityResultListener.class); - verify(mockActivityPluginBinding).addActivityResultListener(captor.capture()); - PluginRegistry.ActivityResultListener listener = captor.getValue(); - - when(mockGoogleSignIn.getLastSignedInAccount(mockContext)).thenReturn(account); - when(account.getGrantedScopes()).thenReturn(Collections.singleton(requestedScope)); - when(mockGoogleSignIn.hasPermissions(account, requestedScope)).thenReturn(false); - - plugin.onMethodCall(methodCall, result); - listener.onActivityResult( - GoogleSignInPlugin.Delegate.REQUEST_CODE_REQUEST_SCOPE, Activity.RESULT_OK, new Intent()); - plugin.onMethodCall(methodCall, result); - listener.onActivityResult( - GoogleSignInPlugin.Delegate.REQUEST_CODE_REQUEST_SCOPE, Activity.RESULT_OK, new Intent()); - - verify(result, times(2)).success(true); - } - - @Test - public void requestScopes_mayBeCalledRepeatedly_ifNotSignedIn() { - HashMap> arguments = new HashMap<>(); - arguments.put("scopes", Collections.singletonList("requestedScope")); - MethodCall methodCall = new MethodCall("requestScopes", arguments); - Scope requestedScope = new Scope("requestedScope"); - - ArgumentCaptor captor = - ArgumentCaptor.forClass(PluginRegistry.ActivityResultListener.class); - verify(mockActivityPluginBinding).addActivityResultListener(captor.capture()); - PluginRegistry.ActivityResultListener listener = captor.getValue(); - - when(mockGoogleSignIn.getLastSignedInAccount(mockContext)).thenReturn(null); - - plugin.onMethodCall(methodCall, result); - listener.onActivityResult( - GoogleSignInPlugin.Delegate.REQUEST_CODE_REQUEST_SCOPE, Activity.RESULT_OK, new Intent()); - plugin.onMethodCall(methodCall, result); - listener.onActivityResult( - GoogleSignInPlugin.Delegate.REQUEST_CODE_REQUEST_SCOPE, Activity.RESULT_OK, new Intent()); - - verify(result, times(2)).error("sign_in_required", "No account to grant scopes.", null); - } - - @Test(expected = IllegalStateException.class) - public void signInThrowsWithoutActivity() { - final GoogleSignInPlugin plugin = new GoogleSignInPlugin(); - plugin.initInstance( - mock(BinaryMessenger.class), mock(Context.class), mock(GoogleSignInWrapper.class)); - - plugin.onMethodCall(new MethodCall("signIn", null), null); - } - - @Test - public void signInSilentlyThatImmediatelyCompletesWithoutResultFinishesWithError() - throws ApiException { - final String clientId = "fakeClientId"; - MethodCall methodCall = buildInitMethodCall(clientId, null); - initAndAssertServerClientId(methodCall, clientId); - - ApiException exception = - new ApiException(new Status(CommonStatusCodes.SIGN_IN_REQUIRED, "Error text")); - when(mockClient.silentSignIn()).thenReturn(mockSignInTask); - when(mockSignInTask.isComplete()).thenReturn(true); - when(mockSignInTask.getResult(ApiException.class)).thenThrow(exception); - - plugin.onMethodCall(new MethodCall("signInSilently", null), result); - verify(result) - .error( - "sign_in_required", - "com.google.android.gms.common.api.ApiException: 4: Error text", - null); - } - - @Test - public void init_LoadsServerClientIdFromResources() { - final String packageName = "fakePackageName"; - final String serverClientId = "fakeServerClientId"; - final int resourceId = 1; - MethodCall methodCall = buildInitMethodCall(null, null); - when(mockContext.getPackageName()).thenReturn(packageName); - when(mockResources.getIdentifier("default_web_client_id", "string", packageName)) - .thenReturn(resourceId); - when(mockContext.getString(resourceId)).thenReturn(serverClientId); - initAndAssertServerClientId(methodCall, serverClientId); - } - - @Test - public void init_InterpretsClientIdAsServerClientId() { - final String clientId = "fakeClientId"; - MethodCall methodCall = buildInitMethodCall(clientId, null); - initAndAssertServerClientId(methodCall, clientId); - } - - @Test - public void init_ForwardsServerClientId() { - final String serverClientId = "fakeServerClientId"; - MethodCall methodCall = buildInitMethodCall(null, serverClientId); - initAndAssertServerClientId(methodCall, serverClientId); - } - - @Test - public void init_IgnoresClientIdIfServerClientIdIsProvided() { - final String clientId = "fakeClientId"; - final String serverClientId = "fakeServerClientId"; - MethodCall methodCall = buildInitMethodCall(clientId, serverClientId); - initAndAssertServerClientId(methodCall, serverClientId); - } - - @Test - public void init_PassesForceCodeForRefreshTokenFalseWithServerClientIdParameter() { - MethodCall methodCall = buildInitMethodCall("fakeClientId", "fakeServerClientId", false); - - initAndAssertForceCodeForRefreshToken(methodCall, false); - } - - @Test - public void init_PassesForceCodeForRefreshTokenTrueWithServerClientIdParameter() { - MethodCall methodCall = buildInitMethodCall("fakeClientId", "fakeServerClientId", true); - - initAndAssertForceCodeForRefreshToken(methodCall, true); - } - - @Test - public void init_PassesForceCodeForRefreshTokenFalseWithServerClientIdFromResources() { - final String packageName = "fakePackageName"; - final String serverClientId = "fakeServerClientId"; - final int resourceId = 1; - MethodCall methodCall = buildInitMethodCall(null, null, false); - when(mockContext.getPackageName()).thenReturn(packageName); - when(mockResources.getIdentifier("default_web_client_id", "string", packageName)) - .thenReturn(resourceId); - when(mockContext.getString(resourceId)).thenReturn(serverClientId); - - initAndAssertForceCodeForRefreshToken(methodCall, false); - } - - @Test - public void init_PassesForceCodeForRefreshTokenTrueWithServerClientIdFromResources() { - final String packageName = "fakePackageName"; - final String serverClientId = "fakeServerClientId"; - final int resourceId = 1; - MethodCall methodCall = buildInitMethodCall(null, null, true); - when(mockContext.getPackageName()).thenReturn(packageName); - when(mockResources.getIdentifier("default_web_client_id", "string", packageName)) - .thenReturn(resourceId); - when(mockContext.getString(resourceId)).thenReturn(serverClientId); - - initAndAssertForceCodeForRefreshToken(methodCall, true); - } - - public void initAndAssertServerClientId(MethodCall methodCall, String serverClientId) { - ArgumentCaptor optionsCaptor = - ArgumentCaptor.forClass(GoogleSignInOptions.class); - when(mockGoogleSignIn.getClient(any(Context.class), optionsCaptor.capture())) - .thenReturn(mockClient); - plugin.onMethodCall(methodCall, result); - verify(result).success(null); - Assert.assertEquals(serverClientId, optionsCaptor.getValue().getServerClientId()); - } - - public void initAndAssertForceCodeForRefreshToken( - MethodCall methodCall, boolean forceCodeForRefreshToken) { - ArgumentCaptor optionsCaptor = - ArgumentCaptor.forClass(GoogleSignInOptions.class); - when(mockGoogleSignIn.getClient(any(Context.class), optionsCaptor.capture())) - .thenReturn(mockClient); - plugin.onMethodCall(methodCall, result); - verify(result).success(null); - Assert.assertEquals( - forceCodeForRefreshToken, optionsCaptor.getValue().isForceCodeForRefreshToken()); - } - - private static MethodCall buildInitMethodCall(String clientId, String serverClientId) { - return buildInitMethodCall( - "SignInOption.standard", Collections.emptyList(), clientId, serverClientId, false); - } - - private static MethodCall buildInitMethodCall( - String clientId, String serverClientId, boolean forceCodeForRefreshToken) { - return buildInitMethodCall( - "SignInOption.standard", - Collections.emptyList(), - clientId, - serverClientId, - forceCodeForRefreshToken); - } - - private static MethodCall buildInitMethodCall( - String signInOption, - List scopes, - String clientId, - String serverClientId, - boolean forceCodeForRefreshToken) { - HashMap arguments = new HashMap<>(); - arguments.put("signInOption", signInOption); - arguments.put("scopes", scopes); - if (clientId != null) { - arguments.put("clientId", clientId); - } - if (serverClientId != null) { - arguments.put("serverClientId", serverClientId); - } - arguments.put("forceCodeForRefreshToken", forceCodeForRefreshToken); - return new MethodCall("init", arguments); - } -} 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 45dbae355008..03853740b4ec 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 @@ -22,7 +22,6 @@ import com.google.android.gms.common.api.Scope; import com.google.android.gms.common.api.Status; import com.google.android.gms.tasks.Task; -import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugins.googlesignin.Messages.FlutterError; import io.flutter.plugins.googlesignin.Messages.InitParams; import java.util.Collections; @@ -40,7 +39,6 @@ public class GoogleSignInTest { @Mock Context mockContext; @Mock Resources mockResources; @Mock Activity mockActivity; - @Mock BinaryMessenger mockMessenger; @Spy Messages.VoidResult voidResult; @Spy Messages.Result boolResult; @Spy Messages.Result userDataResult; 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 598eeb91a9df..b47fba900599 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.33 +version: 6.1.34 environment: sdk: ^3.5.0 From 9f6d5998784826a0741be8370c95a5ab458bba41 Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Mon, 9 Dec 2024 09:44:19 -0800 Subject: [PATCH 02/24] [path_provider] Clean up Java code (#8240) Minor cleanup in the native implementation code: - Removes a utility to map from index integers to directories, which hasn't been used since the Pigeon conversion but was accidentally left. - Inlines all the implementations of path getters; many methods were pointlessly delegating their implementation to another private method, which is a relic of the pre-Pigeon structure. All of the method implementations were moved without any changes. --- .../path_provider_android/CHANGELOG.md | 4 ++ .../pathprovider/PathProviderPlugin.java | 65 ++++++------------- .../pathprovider/StorageDirectoryMapper.java | 48 -------------- .../pathprovider/PathProviderPluginTest.java | 28 ++++++++ .../StorageDirectoryMapperTest.java | 42 ------------ .../path_provider_android/pubspec.yaml | 2 +- 6 files changed, 52 insertions(+), 137 deletions(-) delete mode 100644 packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/StorageDirectoryMapper.java create mode 100644 packages/path_provider/path_provider_android/android/src/test/java/io/flutter/plugins/pathprovider/PathProviderPluginTest.java delete mode 100644 packages/path_provider/path_provider_android/android/src/test/java/io/flutter/plugins/pathprovider/StorageDirectoryMapperTest.java diff --git a/packages/path_provider/path_provider_android/CHANGELOG.md b/packages/path_provider/path_provider_android/CHANGELOG.md index 44f692ed79a8..b5e2335b3685 100644 --- a/packages/path_provider/path_provider_android/CHANGELOG.md +++ b/packages/path_provider/path_provider_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.2.15 + +* Removes unnecessary native code. + ## 2.2.14 * Updates annotations lib to 1.9.1. diff --git a/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java b/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java index 1140875fd2bc..b7e0825e2e50 100644 --- a/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java +++ b/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java @@ -8,6 +8,7 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugins.pathprovider.Messages.PathProviderApi; @@ -44,17 +45,17 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { @Override public @Nullable String getTemporaryPath() { - return getPathProviderTemporaryDirectory(); + return context.getCacheDir().getPath(); } @Override public @Nullable String getApplicationSupportPath() { - return getApplicationSupportDirectory(); + return PathUtils.getFilesDir(context); } @Override public @Nullable String getApplicationDocumentsPath() { - return getPathProviderApplicationDocumentsDirectory(); + return PathUtils.getDataDirectory(context); } @Override @@ -64,33 +65,6 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { @Override public @Nullable String getExternalStoragePath() { - return getPathProviderStorageDirectory(); - } - - @Override - public @NonNull List getExternalCachePaths() { - return getPathProviderExternalCacheDirectories(); - } - - @Override - public @NonNull List getExternalStoragePaths( - @NonNull Messages.StorageDirectory directory) { - return getPathProviderExternalStorageDirectories(directory); - } - - private String getPathProviderTemporaryDirectory() { - return context.getCacheDir().getPath(); - } - - private String getApplicationSupportDirectory() { - return PathUtils.getFilesDir(context); - } - - private String getPathProviderApplicationDocumentsDirectory() { - return PathUtils.getDataDirectory(context); - } - - private String getPathProviderStorageDirectory() { final File dir = context.getExternalFilesDir(null); if (dir == null) { return null; @@ -98,19 +72,31 @@ private String getPathProviderStorageDirectory() { return dir.getAbsolutePath(); } - private List getPathProviderExternalCacheDirectories() { + @Override + public @NonNull List getExternalCachePaths() { final List paths = new ArrayList<>(); - for (File dir : context.getExternalCacheDirs()) { if (dir != null) { paths.add(dir.getAbsolutePath()); } } + return paths; + } + @Override + public @NonNull List getExternalStoragePaths( + @NonNull Messages.StorageDirectory directory) { + final List paths = new ArrayList<>(); + for (File dir : context.getExternalFilesDirs(getStorageDirectoryString(directory))) { + if (dir != null) { + paths.add(dir.getAbsolutePath()); + } + } return paths; } - private String getStorageDirectoryString(@NonNull Messages.StorageDirectory directory) { + @VisibleForTesting + String getStorageDirectoryString(@NonNull Messages.StorageDirectory directory) { switch (directory) { case ROOT: return null; @@ -138,17 +124,4 @@ private String getStorageDirectoryString(@NonNull Messages.StorageDirectory dire throw new RuntimeException("Unrecognized directory: " + directory); } } - - private List getPathProviderExternalStorageDirectories( - @NonNull Messages.StorageDirectory directory) { - final List paths = new ArrayList<>(); - - for (File dir : context.getExternalFilesDirs(getStorageDirectoryString(directory))) { - if (dir != null) { - paths.add(dir.getAbsolutePath()); - } - } - - return paths; - } } diff --git a/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/StorageDirectoryMapper.java b/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/StorageDirectoryMapper.java deleted file mode 100644 index 4cc12ddf5a97..000000000000 --- a/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/StorageDirectoryMapper.java +++ /dev/null @@ -1,48 +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.pathprovider; - -import android.os.Environment; - -/** Helps to map the Dart `StorageDirectory` enum to a Android system constant. */ -class StorageDirectoryMapper { - /** - * Return a Android Environment constant for a Dart Index. - * - * @return The correct Android Environment constant or null, if the index is null. - * @throws IllegalArgumentException If `dartIndex` is not null but also not matches any known - * index. - */ - static String androidType(Integer dartIndex) throws IllegalArgumentException { - if (dartIndex == null) { - return null; - } - - switch (dartIndex) { - case 0: - return Environment.DIRECTORY_MUSIC; - case 1: - return Environment.DIRECTORY_PODCASTS; - case 2: - return Environment.DIRECTORY_RINGTONES; - case 3: - return Environment.DIRECTORY_ALARMS; - case 4: - return Environment.DIRECTORY_NOTIFICATIONS; - case 5: - return Environment.DIRECTORY_PICTURES; - case 6: - return Environment.DIRECTORY_MOVIES; - case 7: - return Environment.DIRECTORY_DOWNLOADS; - case 8: - return Environment.DIRECTORY_DCIM; - case 9: - return Environment.DIRECTORY_DOCUMENTS; - default: - throw new IllegalArgumentException("Unknown index: " + dartIndex); - } - } -} diff --git a/packages/path_provider/path_provider_android/android/src/test/java/io/flutter/plugins/pathprovider/PathProviderPluginTest.java b/packages/path_provider/path_provider_android/android/src/test/java/io/flutter/plugins/pathprovider/PathProviderPluginTest.java new file mode 100644 index 000000000000..d19b7cab6a80 --- /dev/null +++ b/packages/path_provider/path_provider_android/android/src/test/java/io/flutter/plugins/pathprovider/PathProviderPluginTest.java @@ -0,0 +1,28 @@ +// 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.pathprovider; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +public class PathProviderPluginTest { + @org.junit.Test + public void testStorageDirectoryTypeTranslation() { + final PathProviderPlugin plugin = new PathProviderPlugin(); + assertNull(plugin.getStorageDirectoryString(Messages.StorageDirectory.ROOT)); + assertEquals("music", plugin.getStorageDirectoryString(Messages.StorageDirectory.MUSIC)); + assertEquals("podcasts", plugin.getStorageDirectoryString(Messages.StorageDirectory.PODCASTS)); + assertEquals( + "ringtones", plugin.getStorageDirectoryString(Messages.StorageDirectory.RINGTONES)); + assertEquals("alarms", plugin.getStorageDirectoryString(Messages.StorageDirectory.ALARMS)); + assertEquals( + "notifications", plugin.getStorageDirectoryString(Messages.StorageDirectory.NOTIFICATIONS)); + assertEquals("pictures", plugin.getStorageDirectoryString(Messages.StorageDirectory.PICTURES)); + assertEquals("movies", plugin.getStorageDirectoryString(Messages.StorageDirectory.MOVIES)); + assertEquals( + "downloads", plugin.getStorageDirectoryString(Messages.StorageDirectory.DOWNLOADS)); + assertEquals("dcim", plugin.getStorageDirectoryString(Messages.StorageDirectory.DCIM)); + } +} diff --git a/packages/path_provider/path_provider_android/android/src/test/java/io/flutter/plugins/pathprovider/StorageDirectoryMapperTest.java b/packages/path_provider/path_provider_android/android/src/test/java/io/flutter/plugins/pathprovider/StorageDirectoryMapperTest.java deleted file mode 100644 index 7469c545b817..000000000000 --- a/packages/path_provider/path_provider_android/android/src/test/java/io/flutter/plugins/pathprovider/StorageDirectoryMapperTest.java +++ /dev/null @@ -1,42 +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.pathprovider; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; - -import android.os.Environment; -import org.junit.Test; - -public class StorageDirectoryMapperTest { - @org.junit.Test - public void testAndroidType_null() { - assertNull(StorageDirectoryMapper.androidType(null)); - } - - @org.junit.Test - public void testAndroidType_valid() { - assertEquals(Environment.DIRECTORY_MUSIC, StorageDirectoryMapper.androidType(0)); - assertEquals(Environment.DIRECTORY_PODCASTS, StorageDirectoryMapper.androidType(1)); - assertEquals(Environment.DIRECTORY_RINGTONES, StorageDirectoryMapper.androidType(2)); - assertEquals(Environment.DIRECTORY_ALARMS, StorageDirectoryMapper.androidType(3)); - assertEquals(Environment.DIRECTORY_NOTIFICATIONS, StorageDirectoryMapper.androidType(4)); - assertEquals(Environment.DIRECTORY_PICTURES, StorageDirectoryMapper.androidType(5)); - assertEquals(Environment.DIRECTORY_MOVIES, StorageDirectoryMapper.androidType(6)); - assertEquals(Environment.DIRECTORY_DOWNLOADS, StorageDirectoryMapper.androidType(7)); - assertEquals(Environment.DIRECTORY_DCIM, StorageDirectoryMapper.androidType(8)); - } - - @Test - public void testAndroidType_invalid() { - try { - assertEquals(Environment.DIRECTORY_DCIM, StorageDirectoryMapper.androidType(10)); - fail(); - } catch (IllegalArgumentException e) { - assertEquals("Unknown index: " + 10, e.getMessage()); - } - } -} diff --git a/packages/path_provider/path_provider_android/pubspec.yaml b/packages/path_provider/path_provider_android/pubspec.yaml index 35b708386f20..9674e6a17036 100644 --- a/packages/path_provider/path_provider_android/pubspec.yaml +++ b/packages/path_provider/path_provider_android/pubspec.yaml @@ -2,7 +2,7 @@ name: path_provider_android description: Android implementation of the path_provider plugin. repository: https://github.com/flutter/packages/tree/main/packages/path_provider/path_provider_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22 -version: 2.2.14 +version: 2.2.15 environment: sdk: ^3.5.0 From 2dc8b98a2c0da9e7f44eaed385cca98e62c3093e Mon Sep 17 00:00:00 2001 From: David Iglesias Date: Mon, 9 Dec 2024 11:03:04 -0800 Subject: [PATCH 03/24] [google_adsense] Tighten exports and docs. (#8233) * **Breaking changes**: Reshuffles API exports: * Removes the `adUnit` method, and instead exports the `AdUnitWidget` directly. * Renames `experimental/google_adsense` to `experimental/ad_unit_widget.dart`. * Removes the `AdStatus` and `AdUnitParams` exports. * Removes the "stub" files, so this package is now web-only and must be used through a conditional import. * Tweaks several documentation pages to remove references to internal APIs. * Splits tests to reflect the new code structure. ## Issue * Continuation of: https://github.com/flutter/packages/pull/6871 * Part of: https://github.com/flutter/flutter/issues/40376 --- packages/google_adsense/CHANGELOG.md | 12 ++ packages/google_adsense/README.md | 96 +++++---- ...erop.dart => adsense_test_js_interop.dart} | 2 +- .../example/integration_test/core_test.dart | 74 +++++++ ... => experimental_ad_unit_widget_test.dart} | 110 ++++------- .../integration_test/script_tag_test.dart | 4 +- packages/google_adsense/example/lib/main.dart | 53 +++-- .../lib/experimental/ad_unit_widget.dart | 5 + .../lib/experimental/google_adsense.dart | 7 - .../google_adsense/lib/google_adsense.dart | 2 + .../lib/src/ad_unit_configuration.dart | 112 ----------- .../src/adsense/ad_unit_configuration.dart | 185 ++++++++++++++++++ .../lib/src/{ => adsense}/ad_unit_params.dart | 13 +- .../lib/src/{ => adsense}/ad_unit_widget.dart | 37 +++- .../lib/src/adsense/adsense.dart | 7 + .../lib/src/adsense/adsense_js_interop.dart | 15 ++ .../google_adsense/lib/src/adsense_stub.dart | 28 --- .../google_adsense.dart} | 39 ++-- .../lib/src/js_interop/adsbygoogle.dart | 12 +- .../lib/src/{ => utils}/logging.dart | 0 packages/google_adsense/pubspec.yaml | 2 +- 21 files changed, 489 insertions(+), 326 deletions(-) rename packages/google_adsense/example/integration_test/{test_js_interop.dart => adsense_test_js_interop.dart} (97%) create mode 100644 packages/google_adsense/example/integration_test/core_test.dart rename packages/google_adsense/example/integration_test/{ad_widget_test.dart => experimental_ad_unit_widget_test.dart} (64%) create mode 100644 packages/google_adsense/lib/experimental/ad_unit_widget.dart delete mode 100644 packages/google_adsense/lib/experimental/google_adsense.dart delete mode 100644 packages/google_adsense/lib/src/ad_unit_configuration.dart create mode 100644 packages/google_adsense/lib/src/adsense/ad_unit_configuration.dart rename packages/google_adsense/lib/src/{ => adsense}/ad_unit_params.dart (93%) rename packages/google_adsense/lib/src/{ => adsense}/ad_unit_widget.dart (83%) create mode 100644 packages/google_adsense/lib/src/adsense/adsense.dart create mode 100644 packages/google_adsense/lib/src/adsense/adsense_js_interop.dart delete mode 100644 packages/google_adsense/lib/src/adsense_stub.dart rename packages/google_adsense/lib/src/{adsense_web.dart => core/google_adsense.dart} (71%) rename packages/google_adsense/lib/src/{ => utils}/logging.dart (100%) diff --git a/packages/google_adsense/CHANGELOG.md b/packages/google_adsense/CHANGELOG.md index d0bd041d0ff6..a8f06137621f 100644 --- a/packages/google_adsense/CHANGELOG.md +++ b/packages/google_adsense/CHANGELOG.md @@ -1,3 +1,15 @@ +## 0.0.2 + +* **Breaking changes**: Reshuffles API exports: + * Makes `adSense.initialize` async. + * Removes the `adUnit` method, and instead exports the `AdUnitWidget` directly. + * Renames `experimental/google_adsense` to `experimental/ad_unit_widget.dart`. + * Removes the `AdStatus` and `AdUnitParams` exports. + * Removes the "stub" files, so this package is now web-only and must be used + through a conditional import. +* Tweaks several documentation pages to remove references to internal APIs. +* Splits tests to reflect the new code structure. + ## 0.0.1 * Initial release. diff --git a/packages/google_adsense/README.md b/packages/google_adsense/README.md index e7fb1b806938..c82209d480af 100644 --- a/packages/google_adsense/README.md +++ b/packages/google_adsense/README.md @@ -10,30 +10,42 @@ Please express interest joining Early Access program using [this form](https://d ## Usage ### Setup your AdSense account -1. [Make sure your site's pages are ready for AdSense](https://support.google.com/adsense/answer/7299563?hl=en&sjid=5790642343077592212-EU&visit_id=638657100661171978-1373860041&ref_topic=1319756&rd=1) -2. [Create your AdSense account](https://support.google.com/adsense/answer/10162?hl=en&sjid=5790642343077592212-EU&visit_id=638657100661171978-1373860041&ref_topic=1250103&rd=1) +1. [Make sure your site's pages are ready for AdSense](https://support.google.com/adsense/answer/7299563) +2. [Create your AdSense account](https://support.google.com/adsense/answer/10162) ### Initialize AdSense -To start displaying ads, initialize the AdSense with your [client/publisher ID](https://support.google.com/adsense/answer/105516?hl=en&sjid=5790642343077592212-EU) (only use numbers). +To start displaying ads, initialize AdSense with your [Publisher ID](https://support.google.com/adsense/answer/105516) (only use numbers). + ```dart -import 'package:google_adsense/experimental/google_adsense.dart'; +import 'package:google_adsense/experimental/ad_unit_widget.dart'; +import 'package:google_adsense/google_adsense.dart'; + +void main() async { + // Call `initialize` with your Publisher ID (pub-0123456789012345) + // (See: https://support.google.com/adsense/answer/105516) + await adSense.initialize('0123456789012345'); -void main() { - adSense.initialize( - '0123456789012345'); // TODO: Replace with your Publisher ID (pub-0123456789012345) - https://support.google.com/adsense/answer/105516?hl=en&sjid=5790642343077592212-EU runApp(const MyApp()); } - ``` -### Enable Auto Ads -In order to start displaying [Auto ads](https://support.google.com/adsense/answer/9261805?hl=en) make sure to configure this feature in your AdSense Console. If you want to display ad units within your app content, continue to the next step +### Displaying Auto Ads +In order to start displaying [Auto ads](https://support.google.com/adsense/answer/9261805): + +1. Configure this feature in your AdSense Console. -### Display ad unit Widget +Auto ads should start showing just with the call to `initialize`, when available. -1. Create [ad units](https://support.google.com/adsense/answer/9183549?hl=en&ref_topic=9183242&sjid=5790642343077592212-EU) in your AdSense account -2. Use relevant `AdUnitConfiguration` constructor as per table below +If you want to display ad units within your app content, continue to the next step + +### Display ad units (`AdUnitWidget`) + +To display an Ad unit in your Flutter application: + +1. Create [ad units](https://support.google.com/adsense/answer/9183549) in your AdSense account. + This will provide an HTML snippet, which you need to translate to Dart. +2. Pick the `AdUnitConfiguration` for your ad type: | Ad Unit Type | `AdUnitConfiguration` constructor method | |----------------|--------------------------------------------| @@ -42,12 +54,17 @@ In order to start displaying [Auto ads](https://support.google.com/adsense/answe | In-article Ads | `AdUnitConfiguration.inArticleAdUnit(...)` | | Multiplex Ads | `AdUnitConfiguration.multiplexAdUnit(...)` | -3. Translate data-attributes from snippet generated in AdSense Console into constructor arguments as described below: -- drop `data-` prefix -- translate kebab-case to camelCase -- no need to translate `data-ad-client` as it the value was already passed at initialization +3. The data-attributes from the generated snippet are available through the `AdUnitConfiguration` object. +Their Dart name is created as follows: + +- The `data-` prefix is **removed**. +- `kebab-case` becomes `camelCase` + +The only exception to this is `data-ad-client`, that is passed to `adSense.initialize`, +instead of through an `AdUnitConfiguration` object. + +For example snippet below: -For example snippet below ```html ``` -translates into +translates into: + ```dart -adSense.initialize( - '0123456789012345'); // TODO: Replace with your Publisher ID (pub-0123456789012345) - https://support.google.com/adsense/answer/105516?hl=en&sjid=5790642343077592212-EU +// Call `initialize` with your Publisher ID (pub-0123456789012345) +// (See: https://support.google.com/adsense/answer/105516) +await adSense.initialize('0123456789012345'); + ``` -and + +and: + ```dart - adSense.adUnit(AdUnitConfiguration.displayAdUnit( - adSlot: '1234567890', // TODO: Replace with your Ad Unit ID - adFormat: AdFormat - .AUTO, // Remove AdFormat to make ads limited by height -)) + AdUnitWidget( + configuration: AdUnitConfiguration.displayAdUnit( + // TODO: Replace with your Ad Unit ID + adSlot: '1234567890', + // Remove AdFormat to make ads limited by height + adFormat: AdFormat.AUTO, + ), +), ``` -#### Customize ad unit Widget +#### `AdUnitWidget` customizations + To [modify your responsive ad code](https://support.google.com/adsense/answer/9183363?hl=en&ref_topic=9183242&sjid=11551379421978541034-EU): 1. Make sure to follow [AdSense policies](https://support.google.com/adsense/answer/1346295?hl=en&sjid=18331098933308334645-EU&visit_id=638689380593964621-4184295127&ref_topic=1271508&rd=1) 2. Use Flutter instruments for [adaptive and responsive design](https://docs.flutter.dev/ui/adaptive-responsive) @@ -89,11 +115,14 @@ Container( constraints: const BoxConstraints(maxHeight: 100, maxWidth: 1200), padding: const EdgeInsets.only(bottom: 10), - child: adSense.adUnit(AdUnitConfiguration.displayAdUnit( - adSlot: '1234567890', // TODO: Replace with your Ad Unit ID - adFormat: AdFormat - .AUTO, // Not using AdFormat to make ad unit respect height constraint - )), + child: AdUnitWidget( + configuration: AdUnitConfiguration.displayAdUnit( + // TODO: Replace with your Ad Unit ID + adSlot: '1234567890', + // Do not use adFormat to make ad unit respect height constraint + // adFormat: AdFormat.AUTO, + ), + ), ), ``` ## Testing and common errors @@ -114,6 +143,7 @@ Make sure to set correct values to adSlot and adClient arguments ### Ad unfilled There is no deterministic way to make sure your ads are 100% filled even when testing. Some of the way to increase the fill rate: +- Ensure your ad units are correctly configured in AdSense - Try setting `adTest` parameter to `true` - Try setting AD_FORMAT to `auto` (default setting) - Try setting FULL_WIDTH_RESPONSIVE to `true` (default setting) diff --git a/packages/google_adsense/example/integration_test/test_js_interop.dart b/packages/google_adsense/example/integration_test/adsense_test_js_interop.dart similarity index 97% rename from packages/google_adsense/example/integration_test/test_js_interop.dart rename to packages/google_adsense/example/integration_test/adsense_test_js_interop.dart index d943ac980df9..aff8a4f4a55d 100644 --- a/packages/google_adsense/example/integration_test/test_js_interop.dart +++ b/packages/google_adsense/example/integration_test/adsense_test_js_interop.dart @@ -9,7 +9,7 @@ import 'dart:async'; import 'dart:js_interop'; import 'dart:ui'; -import 'package:google_adsense/experimental/google_adsense.dart'; +import 'package:google_adsense/src/adsense/ad_unit_params.dart'; import 'package:web/web.dart' as web; typedef VoidFn = void Function(); diff --git a/packages/google_adsense/example/integration_test/core_test.dart b/packages/google_adsense/example/integration_test/core_test.dart new file mode 100644 index 000000000000..e55f735e2714 --- /dev/null +++ b/packages/google_adsense/example/integration_test/core_test.dart @@ -0,0 +1,74 @@ +// 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. + +// TO run the test: +// 1. Run chrome driver with --port=4444 +// 2. Run the test from example folder with: flutter drive -d web-server --web-port 7357 --browser-name chrome --driver test_driver/integration_test.dart --target integration_test/ad_widget_test.dart + +import 'package:flutter_test/flutter_test.dart'; +import 'package:google_adsense/google_adsense.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:web/web.dart' as web; + +import 'adsense_test_js_interop.dart'; + +const String testClient = 'test_client'; +const String testScriptUrl = + 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-$testClient'; + +void main() async { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + late AdSense adSense; + + setUp(() async { + adSense = AdSense(); + }); + + tearDown(() { + clearAdsByGoogleMock(); + }); + + group('adSense.initialize', () { + testWidgets('adds AdSense script tag.', (WidgetTester _) async { + final web.HTMLElement target = web.HTMLDivElement(); + // Given + + await adSense.initialize(testClient, jsLoaderTarget: target); + + final web.HTMLScriptElement? injected = + target.lastElementChild as web.HTMLScriptElement?; + + expect(injected, isNotNull); + expect(injected!.src, testScriptUrl); + expect(injected.crossOrigin, 'anonymous'); + expect(injected.async, true); + }); + + testWidgets('Skips initialization if script is already present.', + (WidgetTester _) async { + final web.HTMLScriptElement script = web.HTMLScriptElement() + ..id = 'previously-injected' + ..src = testScriptUrl; + final web.HTMLElement target = web.HTMLDivElement()..appendChild(script); + + await adSense.initialize(testClient, jsLoaderTarget: target); + + expect(target.childElementCount, 1); + expect(target.firstElementChild?.id, 'previously-injected'); + }); + + testWidgets('Skips initialization if adsense object is already present.', + (WidgetTester _) async { + final web.HTMLElement target = web.HTMLDivElement(); + + // Write an empty noop object + mockAdsByGoogle(() {}); + + await adSense.initialize(testClient, jsLoaderTarget: target); + + expect(target.firstElementChild, isNull); + }); + }); +} diff --git a/packages/google_adsense/example/integration_test/ad_widget_test.dart b/packages/google_adsense/example/integration_test/experimental_ad_unit_widget_test.dart similarity index 64% rename from packages/google_adsense/example/integration_test/ad_widget_test.dart rename to packages/google_adsense/example/integration_test/experimental_ad_unit_widget_test.dart index 43b7dfb63041..12a1231b269a 100644 --- a/packages/google_adsense/example/integration_test/ad_widget_test.dart +++ b/packages/google_adsense/example/integration_test/experimental_ad_unit_widget_test.dart @@ -8,18 +8,16 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -// Ensure we don't use the singleton `adSense`, but the local copies to this plugin. -import 'package:google_adsense/experimental/google_adsense.dart' hide adSense; -import 'package:google_adsense/src/ad_unit_widget.dart'; +import 'package:google_adsense/experimental/ad_unit_widget.dart'; +// Ensure we don't use the `adSense` singleton for tests. +import 'package:google_adsense/google_adsense.dart' hide adSense; +import 'package:google_adsense/src/adsense/ad_unit_params.dart'; import 'package:integration_test/integration_test.dart'; -import 'package:web/web.dart' as web; -import 'test_js_interop.dart'; +import 'adsense_test_js_interop.dart'; const String testClient = 'test_client'; const String testSlot = 'test_slot'; -const String testScriptUrl = - 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-$testClient'; void main() async { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); @@ -34,49 +32,7 @@ void main() async { clearAdsByGoogleMock(); }); - group('initialization', () { - testWidgets('Initialization adds AdSense snippet.', (WidgetTester _) async { - final web.HTMLElement target = web.HTMLDivElement(); - // Given - - adSense.initialize(testClient, jsLoaderTarget: target); - - final web.HTMLScriptElement? injected = - target.lastElementChild as web.HTMLScriptElement?; - - expect(injected, isNotNull); - expect(injected!.src, testScriptUrl); - expect(injected.crossOrigin, 'anonymous'); - expect(injected.async, true); - }); - - testWidgets('Skips initialization if script is already present.', - (WidgetTester _) async { - final web.HTMLScriptElement script = web.HTMLScriptElement() - ..id = 'previously-injected' - ..src = testScriptUrl; - final web.HTMLElement target = web.HTMLDivElement()..appendChild(script); - - adSense.initialize(testClient, jsLoaderTarget: target); - - expect(target.childElementCount, 1); - expect(target.firstElementChild?.id, 'previously-injected'); - }); - - testWidgets('Skips initialization if adsense object is already present.', - (WidgetTester _) async { - final web.HTMLElement target = web.HTMLDivElement(); - - // Write an empty noop object - mockAdsByGoogle(() {}); - - adSense.initialize(testClient, jsLoaderTarget: target); - - expect(target.firstElementChild, isNull); - }); - }); - - group('adWidget', () { + group('adSense.adUnit', () { testWidgets('Responsive (with adFormat) ad units reflow flutter', (WidgetTester tester) async { // The size of the ad that we're going to "inject" @@ -89,13 +45,14 @@ void main() async { ), ); - adSense.initialize(testClient); + await adSense.initialize(testClient); - final Widget adUnitWidget = adSense.adUnit( - AdUnitConfiguration.displayAdUnit( + final Widget adUnitWidget = AdUnitWidget( + configuration: AdUnitConfiguration.displayAdUnit( adSlot: testSlot, adFormat: AdFormat.AUTO, // Important! ), + adClient: adSense.adClient, ); await pumpAdWidget(adUnitWidget, tester); @@ -122,12 +79,13 @@ void main() async { ), ); - adSense.initialize(testClient); + await adSense.initialize(testClient); - final Widget adUnitWidget = adSense.adUnit( - AdUnitConfiguration.displayAdUnit( + final Widget adUnitWidget = AdUnitWidget( + configuration: AdUnitConfiguration.displayAdUnit( adSlot: testSlot, ), + adClient: adSense.adClient, ); final Widget constrainedAd = Container( @@ -151,11 +109,12 @@ void main() async { // When mockAdsByGoogle(mockAd(adStatus: AdStatus.UNFILLED)); - adSense.initialize(testClient); - final Widget adUnitWidget = adSense.adUnit( - AdUnitConfiguration.displayAdUnit( + await adSense.initialize(testClient); + final Widget adUnitWidget = AdUnitWidget( + configuration: AdUnitConfiguration.displayAdUnit( adSlot: testSlot, ), + adClient: adSense.adClient, ); await pumpAdWidget(adUnitWidget, tester); @@ -181,23 +140,32 @@ void main() async { ]), ); - adSense.initialize(testClient); + await adSense.initialize(testClient); final Widget bunchOfAds = Column( children: [ - adSense.adUnit(AdUnitConfiguration.displayAdUnit( - adSlot: testSlot, - adFormat: AdFormat.AUTO, - )), - adSense.adUnit(AdUnitConfiguration.displayAdUnit( - adSlot: testSlot, - adFormat: AdFormat.AUTO, - )), + AdUnitWidget( + configuration: AdUnitConfiguration.displayAdUnit( + adSlot: testSlot, + adFormat: AdFormat.AUTO, + ), + adClient: adSense.adClient, + ), + AdUnitWidget( + configuration: AdUnitConfiguration.displayAdUnit( + adSlot: testSlot, + adFormat: AdFormat.AUTO, + ), + adClient: adSense.adClient, + ), Container( constraints: const BoxConstraints(maxHeight: 100), - child: adSense.adUnit(AdUnitConfiguration.displayAdUnit( - adSlot: testSlot, - )), + child: AdUnitWidget( + configuration: AdUnitConfiguration.displayAdUnit( + adSlot: testSlot, + ), + adClient: adSense.adClient, + ), ), ], ); diff --git a/packages/google_adsense/example/integration_test/script_tag_test.dart b/packages/google_adsense/example/integration_test/script_tag_test.dart index c4671eaaf531..499712470f39 100644 --- a/packages/google_adsense/example/integration_test/script_tag_test.dart +++ b/packages/google_adsense/example/integration_test/script_tag_test.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter_test/flutter_test.dart'; -import 'package:google_adsense/experimental/google_adsense.dart'; +import 'package:google_adsense/google_adsense.dart'; import 'package:integration_test/integration_test.dart'; import 'package:web/web.dart' as web; @@ -22,7 +22,7 @@ void main() async { 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-$testClient'; // When (using the singleton adSense from the plugin) - adSense.initialize(testClient); + await adSense.initialize(testClient); // Then final web.HTMLScriptElement? injected = diff --git a/packages/google_adsense/example/lib/main.dart b/packages/google_adsense/example/lib/main.dart index 91a4c3b2373d..88d6f83424ec 100644 --- a/packages/google_adsense/example/lib/main.dart +++ b/packages/google_adsense/example/lib/main.dart @@ -7,17 +7,20 @@ import 'package:flutter/material.dart'; // #docregion init -import 'package:google_adsense/experimental/google_adsense.dart'; +import 'package:google_adsense/experimental/ad_unit_widget.dart'; +import 'package:google_adsense/google_adsense.dart'; + +void main() async { +// #docregion init-min + // Call `initialize` with your Publisher ID (pub-0123456789012345) + // (See: https://support.google.com/adsense/answer/105516) + await adSense.initialize('0123456789012345'); -void main() { - // #docregion init-min - adSense.initialize( - '0123456789012345'); // TODO: Replace with your Publisher ID (pub-0123456789012345) - https://support.google.com/adsense/answer/105516?hl=en&sjid=5790642343077592212-EU // #enddocregion init-min runApp(const MyApp()); } - // #enddocregion init + /// The main app. class MyApp extends StatelessWidget { /// Constructs a [MyApp] @@ -66,13 +69,15 @@ class _MyHomePageState extends State { padding: const EdgeInsets.only(bottom: 10), child: // #docregion adUnit - adSense.adUnit(AdUnitConfiguration.displayAdUnit( - adSlot: '1234567890', // TODO: Replace with your Ad Unit ID - adFormat: AdFormat - .AUTO, // Remove AdFormat to make ads limited by height - )) + AdUnitWidget( + configuration: AdUnitConfiguration.displayAdUnit( + // TODO: Replace with your Ad Unit ID + adSlot: '1234567890', + // Remove AdFormat to make ads limited by height + adFormat: AdFormat.AUTO, + ), + ), // #enddocregion adUnit - , ), const Text( 'Responsive Ad Constrained by height of 100px and width of 1200px (to keep ad centered):', @@ -82,11 +87,14 @@ class _MyHomePageState extends State { constraints: const BoxConstraints(maxHeight: 100, maxWidth: 1200), padding: const EdgeInsets.only(bottom: 10), - child: adSense.adUnit(AdUnitConfiguration.displayAdUnit( - adSlot: '1234567890', // TODO: Replace with your Ad Unit ID - adFormat: AdFormat - .AUTO, // Not using AdFormat to make ad unit respect height constraint - )), + child: AdUnitWidget( + configuration: AdUnitConfiguration.displayAdUnit( + // TODO: Replace with your Ad Unit ID + adSlot: '1234567890', + // Do not use adFormat to make ad unit respect height constraint + // adFormat: AdFormat.AUTO, + ), + ), ), // #enddocregion constraints const Text( @@ -96,10 +104,13 @@ class _MyHomePageState extends State { height: 125, width: 125, padding: const EdgeInsets.only(bottom: 10), - child: adSense.adUnit(AdUnitConfiguration.displayAdUnit( - adSlot: '1234567890', // TODO: Replace with your Ad Unit ID - // adFormat: AdFormat.AUTO, // Not using AdFormat to make ad unit respect height constraint - isFullWidthResponsive: false)), + child: AdUnitWidget( + configuration: AdUnitConfiguration.displayAdUnit( + // TODO: Replace with your Ad Unit ID + adSlot: '1234567890', + isFullWidthResponsive: false, + ), + ), ), ], ), diff --git a/packages/google_adsense/lib/experimental/ad_unit_widget.dart b/packages/google_adsense/lib/experimental/ad_unit_widget.dart new file mode 100644 index 000000000000..9d165298d40d --- /dev/null +++ b/packages/google_adsense/lib/experimental/ad_unit_widget.dart @@ -0,0 +1,5 @@ +// 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. + +export '../src/adsense/adsense.dart'; diff --git a/packages/google_adsense/lib/experimental/google_adsense.dart b/packages/google_adsense/lib/experimental/google_adsense.dart deleted file mode 100644 index cbeabcc1418a..000000000000 --- a/packages/google_adsense/lib/experimental/google_adsense.dart +++ /dev/null @@ -1,7 +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. -export '../src/ad_unit_configuration.dart'; -export '../src/ad_unit_params.dart'; -export '../src/adsense_stub.dart' - if (dart.library.js_interop) '../src/adsense_web.dart'; diff --git a/packages/google_adsense/lib/google_adsense.dart b/packages/google_adsense/lib/google_adsense.dart index e7217c7d7b3f..ac0e7ae01c56 100644 --- a/packages/google_adsense/lib/google_adsense.dart +++ b/packages/google_adsense/lib/google_adsense.dart @@ -1,3 +1,5 @@ // 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. + +export 'src/core/google_adsense.dart'; diff --git a/packages/google_adsense/lib/src/ad_unit_configuration.dart b/packages/google_adsense/lib/src/ad_unit_configuration.dart deleted file mode 100644 index 94e34697358c..000000000000 --- a/packages/google_adsense/lib/src/ad_unit_configuration.dart +++ /dev/null @@ -1,112 +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. - -import 'package:flutter/foundation.dart'; - -import '../experimental/google_adsense.dart'; - -/// AdUnit configuration object. -/// -/// Arguments: -/// - `adSlot`: See [AdUnitParams.AD_SLOT] -/// - `adFormat`: See [AdUnitParams.AD_FORMAT] -/// - `adLayout`: See [AdUnitParams.AD_LAYOUT] -/// - `adLayoutKey`: See [AdUnitParams.AD_LAYOUT_KEY] -/// - `multiplexLayout`: See [AdUnitParams.MATCHED_CONTENT_UI_TYPE] -/// - `rowsNum`: See [AdUnitParams.MATCHED_CONTENT_ROWS_NUM] -/// - `columnsNum`: See [AdUnitParams.MATCHED_CONTENT_COLUMNS_NUM] -/// - `isFullWidthResponsive`: See [AdUnitParams.FULL_WIDTH_RESPONSIVE] -/// - `isAdTest`: See [AdUnitParams.AD_TEST] -class AdUnitConfiguration { - AdUnitConfiguration._internal({ - required String adSlot, - AdFormat? adFormat, - AdLayout? adLayout, - String? adLayoutKey, - MatchedContentUiType? matchedContentUiType, - int? rowsNum, - int? columnsNum, - bool? isFullWidthResponsive = true, - bool? isAdTest, - }) : _adUnitParams = { - AdUnitParams.AD_SLOT: adSlot, - if (adFormat != null) AdUnitParams.AD_FORMAT: adFormat.toString(), - if (adLayout != null) AdUnitParams.AD_LAYOUT: adLayout.toString(), - if (adLayoutKey != null) AdUnitParams.AD_LAYOUT_KEY: adLayoutKey, - if (isFullWidthResponsive != null) - AdUnitParams.FULL_WIDTH_RESPONSIVE: - isFullWidthResponsive.toString(), - if (matchedContentUiType != null) - AdUnitParams.MATCHED_CONTENT_UI_TYPE: - matchedContentUiType.toString(), - if (columnsNum != null) - AdUnitParams.MATCHED_CONTENT_COLUMNS_NUM: columnsNum.toString(), - if (rowsNum != null) - AdUnitParams.MATCHED_CONTENT_ROWS_NUM: rowsNum.toString(), - if (isAdTest != null && isAdTest) AdUnitParams.AD_TEST: 'on', - }; - - /// Creates In-article ad unit configuration object - AdUnitConfiguration.multiplexAdUnit({ - required String adSlot, - required AdFormat adFormat, - MatchedContentUiType? matchedContentUiType, - int? rowsNum, - int? columnsNum, - bool isFullWidthResponsive = true, - bool isAdTest = kDebugMode, - }) : this._internal( - adSlot: adSlot, - adFormat: adFormat, - matchedContentUiType: matchedContentUiType, - rowsNum: rowsNum, - columnsNum: columnsNum, - isFullWidthResponsive: isFullWidthResponsive, - isAdTest: isAdTest); - - /// Creates In-feed ad unit configuration object - AdUnitConfiguration.inFeedAdUnit({ - required String adSlot, - required String adLayoutKey, - AdFormat? adFormat, - bool isFullWidthResponsive = true, - bool isAdTest = kDebugMode, - }) : this._internal( - adSlot: adSlot, - adFormat: adFormat, - adLayoutKey: adLayoutKey, - isFullWidthResponsive: isFullWidthResponsive, - isAdTest: isAdTest); - - /// Creates In-article ad unit configuration object - AdUnitConfiguration.inArticleAdUnit({ - required String adSlot, - AdFormat? adFormat, - AdLayout adLayout = AdLayout.IN_ARTICLE, - bool isFullWidthResponsive = true, - bool isAdTest = kDebugMode, - }) : this._internal( - adSlot: adSlot, - adFormat: adFormat, - adLayout: adLayout, - isFullWidthResponsive: isFullWidthResponsive, - isAdTest: isAdTest); - - /// Creates Display ad unit configuration object - AdUnitConfiguration.displayAdUnit({ - required String adSlot, - AdFormat? adFormat, - bool isFullWidthResponsive = true, - bool isAdTest = kDebugMode, - }) : this._internal( - adSlot: adSlot, - adFormat: adFormat, - isFullWidthResponsive: isFullWidthResponsive, - isAdTest: isAdTest); - - Map _adUnitParams; - - /// Map containing all additional parameters of this configuration - Map get params => _adUnitParams; -} diff --git a/packages/google_adsense/lib/src/adsense/ad_unit_configuration.dart b/packages/google_adsense/lib/src/adsense/ad_unit_configuration.dart new file mode 100644 index 000000000000..740ce728a4a2 --- /dev/null +++ b/packages/google_adsense/lib/src/adsense/ad_unit_configuration.dart @@ -0,0 +1,185 @@ +// 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. + +import 'package:flutter/foundation.dart'; + +import 'ad_unit_params.dart'; + +/// Configuration to customize the [AdUnitWidget]. +/// +/// Contains named constructors for the following supported ad unit types: +/// +/// * Display (see: [AdUnitConfiguration.displayAdUnit]) +/// * In-feed (see: [AdUnitConfiguration.inFeedAdUnit]) +/// * In-article (see: [AdUnitConfiguration.inArticleAdUnit]) +/// * Multiplex (see: [AdUnitConfiguration.multiplexAdUnit]) +/// +/// Each constructor will use one or more of the following arguments: +/// +/// {@template pkg_google_adsense_parameter_adSlot} +/// * [adSlot]: Identifies a specific ad unit from the AdSense console. +/// {@endtemplate} +/// {@template pkg_google_adsense_parameter_adFormat} +/// * [adFormat]: (Desktop only) Specifies a general shape (horizontal, vertical, +/// and/or rectangle) that this ad unit should conform to. To learn more, check: +/// [How to use responsive ad tag parameters](https://support.google.com/adsense/answer/9183460). +/// {@endtemplate} +/// {@template pkg_google_adsense_parameter_adLayout} +/// * [adLayout]: Customizes the layout of this ad unit. See: +/// [Customize your in-feed ad](https://support.google.com/adsense/answer/9189957). +/// {@endtemplate} +/// {@template pkg_google_adsense_parameter_adLayoutKey} +/// * [adLayoutKey]: The key identifying the layout for this ad unit. +/// {@endtemplate} +/// {@template pkg_google_adsense_parameter_matchedContentUiType} +/// * [matchedContentUiType]: Controls the arrangement of the text and images in +/// this Multiplex ad unit. For example, you can choose to have the image and +/// text side by side, the image above the text, etc. More information: +/// [How to customize your responsive Multiplex ad unit](https://support.google.com/adsense/answer/7533385) +/// {@endtemplate} +/// {@template pkg_google_adsense_parameter_rowsNum} +/// * [rowsNum]: Specifies how many rows to show within the Multiplex ad unit grid. +/// Requires [matchedContentUiType] to be set. +/// {@endtemplate} +/// {@template pkg_google_adsense_parameter_columnsNum} +/// * [columnsNum]: Specifies how many columns to show within the Multiplex ad unit grid. +/// Requires [matchedContentUiType] to be set. +/// {@endtemplate} +/// {@template pkg_google_adsense_parameter_isFullWidthResponsive} +/// * [isFullWidthResponsive]: Determines whether this responsive ad unit expands +/// to use the full width of a visitor's mobile device screen. See: +/// [How to use responsive ad tag parameters](https://support.google.com/adsense/answer/9183460). +/// {@endtemplate} +/// {@template pkg_google_adsense_parameter_isAdTest} +/// * [isAdTest]: Whether this ad will be shown in a test environment. Defaults to `true` in debug mode. +/// {@endtemplate} +/// +/// For more information about ad units, check the +/// [Ad formats FAQ](https://support.google.com/adsense/answer/10734935) +/// in the Google AdSense Help. +class AdUnitConfiguration { + AdUnitConfiguration._internal({ + required String adSlot, + AdFormat? adFormat, + AdLayout? adLayout, + String? adLayoutKey, + MatchedContentUiType? matchedContentUiType, + int? rowsNum, + int? columnsNum, + bool? isFullWidthResponsive = true, + bool? isAdTest, + }) : _adUnitParams = { + AdUnitParams.AD_SLOT: adSlot, + if (adFormat != null) AdUnitParams.AD_FORMAT: adFormat.toString(), + if (adLayout != null) AdUnitParams.AD_LAYOUT: adLayout.toString(), + if (adLayoutKey != null) AdUnitParams.AD_LAYOUT_KEY: adLayoutKey, + if (isFullWidthResponsive != null) + AdUnitParams.FULL_WIDTH_RESPONSIVE: + isFullWidthResponsive.toString(), + if (matchedContentUiType != null) + AdUnitParams.MATCHED_CONTENT_UI_TYPE: + matchedContentUiType.toString(), + if (columnsNum != null) + AdUnitParams.MATCHED_CONTENT_COLUMNS_NUM: columnsNum.toString(), + if (rowsNum != null) + AdUnitParams.MATCHED_CONTENT_ROWS_NUM: rowsNum.toString(), + if (isAdTest != null && isAdTest) AdUnitParams.AD_TEST: 'on', + }; + + /// Creates a configuration object for a Multiplex ad. + /// + /// Arguments: + /// + /// {@macro pkg_google_adsense_parameter_adSlot} + /// {@macro pkg_google_adsense_parameter_adFormat} + /// {@macro pkg_google_adsense_parameter_matchedContentUiType} + /// {@macro pkg_google_adsense_parameter_rowsNum} + /// {@macro pkg_google_adsense_parameter_columnsNum} + /// {@macro pkg_google_adsense_parameter_isFullWidthResponsive} + /// {@macro pkg_google_adsense_parameter_isAdTest} + AdUnitConfiguration.multiplexAdUnit({ + required String adSlot, + required AdFormat adFormat, + MatchedContentUiType? matchedContentUiType, + int? rowsNum, + int? columnsNum, + bool isFullWidthResponsive = true, + bool isAdTest = kDebugMode, + }) : this._internal( + adSlot: adSlot, + adFormat: adFormat, + matchedContentUiType: matchedContentUiType, + rowsNum: rowsNum, + columnsNum: columnsNum, + isFullWidthResponsive: isFullWidthResponsive, + isAdTest: isAdTest); + + /// Creates a configuration object for an In-feed ad. + /// + /// Arguments: + /// + /// {@macro pkg_google_adsense_parameter_adSlot} + /// {@macro pkg_google_adsense_parameter_adLayoutKey} + /// {@macro pkg_google_adsense_parameter_adFormat} + /// {@macro pkg_google_adsense_parameter_isFullWidthResponsive} + /// {@macro pkg_google_adsense_parameter_isAdTest} + AdUnitConfiguration.inFeedAdUnit({ + required String adSlot, + required String adLayoutKey, + AdFormat? adFormat, + bool isFullWidthResponsive = true, + bool isAdTest = kDebugMode, + }) : this._internal( + adSlot: adSlot, + adFormat: adFormat, + adLayoutKey: adLayoutKey, + isFullWidthResponsive: isFullWidthResponsive, + isAdTest: isAdTest); + + /// Creates a configuration object for an In-article ad. + /// + /// Arguments: + /// + /// {@macro pkg_google_adsense_parameter_adSlot} + /// {@macro pkg_google_adsense_parameter_adFormat} + /// {@macro pkg_google_adsense_parameter_adLayout} + /// {@macro pkg_google_adsense_parameter_isFullWidthResponsive} + /// {@macro pkg_google_adsense_parameter_isAdTest} + AdUnitConfiguration.inArticleAdUnit({ + required String adSlot, + AdFormat? adFormat, + AdLayout adLayout = AdLayout.IN_ARTICLE, + bool isFullWidthResponsive = true, + bool isAdTest = kDebugMode, + }) : this._internal( + adSlot: adSlot, + adFormat: adFormat, + adLayout: adLayout, + isFullWidthResponsive: isFullWidthResponsive, + isAdTest: isAdTest); + + /// Creates a configuration object for a Display ad. + /// + /// Arguments: + /// + /// {@macro pkg_google_adsense_parameter_adSlot} + /// {@macro pkg_google_adsense_parameter_adFormat} + /// {@macro pkg_google_adsense_parameter_isFullWidthResponsive} + /// {@macro pkg_google_adsense_parameter_isAdTest} + AdUnitConfiguration.displayAdUnit({ + required String adSlot, + AdFormat? adFormat, + bool isFullWidthResponsive = true, + bool isAdTest = kDebugMode, + }) : this._internal( + adSlot: adSlot, + adFormat: adFormat, + isFullWidthResponsive: isFullWidthResponsive, + isAdTest: isAdTest); + + Map _adUnitParams; + + /// `Map` representation of this configuration object. + Map get params => _adUnitParams; +} diff --git a/packages/google_adsense/lib/src/ad_unit_params.dart b/packages/google_adsense/lib/src/adsense/ad_unit_params.dart similarity index 93% rename from packages/google_adsense/lib/src/ad_unit_params.dart rename to packages/google_adsense/lib/src/adsense/ad_unit_params.dart index 71a537fad8c4..d31a7c2c5fa7 100644 --- a/packages/google_adsense/lib/src/ad_unit_params.dart +++ b/packages/google_adsense/lib/src/adsense/ad_unit_params.dart @@ -7,7 +7,7 @@ class AdUnitParams { /// Identifies AdSense publisher account. Should be passed on initialization static const String AD_CLIENT = 'adClient'; - /// Identified specific ad unit from AdSense console. Can be taken from the ad unit HTML snippet under `data-ad-slot` parameter + /// Identifies a specific ad unit from AdSense console. Can be taken from the ad unit HTML snippet under `data-ad-slot` parameter static const String AD_SLOT = 'adSlot'; /// (Optional) Specify a general shape (desktop only) (horizontal, vertical, and/or rectangle) that your ad unit should conform to @@ -43,9 +43,9 @@ class AdUnitParams { static const String AD_TEST = 'adtest'; } -/// Possible values for [AdUnitParams.AD_FORMAT]. +/// Specifies the general shape that the ad unit should conform to. /// -/// See [docs](https://support.google.com/adsense/answer/9183460?hl=en&ref_topic=9183242&sjid=2004567335727763076-EU#:~:text=Specify%20a%20general%20shape%20(desktop%20only)) for details +/// See [docs](https://support.google.com/adsense/answer/9183460?hl=en&ref_topic=9183242&sjid=2004567335727763076-EU#:~:text=Specify%20a%20general%20shape%20(desktop%20only)) for details. enum AdFormat { /// Default which enables the auto-sizing behavior for the responsive ad unit AUTO('auto'), @@ -81,8 +81,7 @@ enum AdFormat { String toString() => _adFormat; } -/// Possible values for [AdUnitParams.AD_LAYOUT]. -/// +/// Controls the general layout of an in-feed/in-article ad unit. // TODO(sokoloff06): find docs link! enum AdLayout { /// @@ -107,9 +106,9 @@ enum AdLayout { String toString() => _adLayout; } -/// Possible values for [AdUnitParams.MATCHED_CONTENT_UI_TYPE]. +/// Controls the arrangement of the text and images in a Multiplex ad unit. /// -/// See [docs](https://support.google.com/adsense/answer/7533385?hl=en#:~:text=Change%20the%20layout%20of%20your%20Multiplex%20ad%20unit) +/// See [docs](https://support.google.com/adsense/answer/7533385?hl=en#:~:text=Change%20the%20layout%20of%20your%20Multiplex%20ad%20unit). enum MatchedContentUiType { /// In this layout, the image and text appear alongside each other. IMAGE_CARD_SIDEBYSIDE('image_card_sidebyside'), diff --git a/packages/google_adsense/lib/src/ad_unit_widget.dart b/packages/google_adsense/lib/src/adsense/ad_unit_widget.dart similarity index 83% rename from packages/google_adsense/lib/src/ad_unit_widget.dart rename to packages/google_adsense/lib/src/adsense/ad_unit_widget.dart index 97d42fbca45a..6771c468cc1c 100644 --- a/packages/google_adsense/lib/src/ad_unit_widget.dart +++ b/packages/google_adsense/lib/src/adsense/ad_unit_widget.dart @@ -8,21 +8,38 @@ import 'dart:js_interop_unsafe'; import 'package:flutter/widgets.dart'; import 'package:web/web.dart' as web; -import '../experimental/google_adsense.dart'; -import 'js_interop/adsbygoogle.dart'; -import 'logging.dart'; - -/// Widget displaying an ad unit +import '../core/google_adsense.dart'; +import '../js_interop/adsbygoogle.dart'; +import '../utils/logging.dart'; +import 'ad_unit_configuration.dart'; +import 'ad_unit_params.dart'; +import 'adsense_js_interop.dart'; + +/// Widget displaying an ad unit. +/// +/// See the [AdUnitConfiguration] object for a complete reference of the available +/// parameters. +/// +/// When specifying an [AdFormat], the widget will behave like a "responsive" +/// ad unit. Responsive ad units might attempt to overflow the container in which +/// they're rendered. +/// +/// To create a fully constrained widget (specific width/height), do *not* pass +/// an `AdFormat` value, and wrap the `AdUnitWidget` in a constrained box from +/// Flutter, like a [Container] or [SizedBox]. class AdUnitWidget extends StatefulWidget { /// Constructs [AdUnitWidget] - const AdUnitWidget({ + AdUnitWidget({ super.key, - required String adClient, required AdUnitConfiguration configuration, - }) : _adClient = adClient, - _adUnitConfiguration = configuration; + @visibleForTesting String? adClient, + }) : _adClient = adClient ?? adSense.adClient, + _adUnitConfiguration = configuration { + assert(_adClient != null, + 'Attempted to render an AdUnitWidget before calling adSense.initialize'); + } - final String _adClient; + final String? _adClient; final AdUnitConfiguration _adUnitConfiguration; diff --git a/packages/google_adsense/lib/src/adsense/adsense.dart b/packages/google_adsense/lib/src/adsense/adsense.dart new file mode 100644 index 000000000000..07781299c901 --- /dev/null +++ b/packages/google_adsense/lib/src/adsense/adsense.dart @@ -0,0 +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. + +export 'ad_unit_configuration.dart'; +export 'ad_unit_params.dart' hide AdStatus, AdUnitParams; +export 'ad_unit_widget.dart'; diff --git a/packages/google_adsense/lib/src/adsense/adsense_js_interop.dart b/packages/google_adsense/lib/src/adsense/adsense_js_interop.dart new file mode 100644 index 000000000000..d3b6fa53bb21 --- /dev/null +++ b/packages/google_adsense/lib/src/adsense/adsense_js_interop.dart @@ -0,0 +1,15 @@ +// 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. + +import 'dart:js_interop'; + +import '../js_interop/adsbygoogle.dart'; + +/// Adds a `requestAd` method to request an AdSense ad. +extension AdsByGoogleExtension on AdsByGoogle { + /// Convenience method for invoking push() with an empty object + void requestAd() { + push(JSObject()); + } +} diff --git a/packages/google_adsense/lib/src/adsense_stub.dart b/packages/google_adsense/lib/src/adsense_stub.dart deleted file mode 100644 index d01bc3304445..000000000000 --- a/packages/google_adsense/lib/src/adsense_stub.dart +++ /dev/null @@ -1,28 +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. - -import 'package:flutter/widgets.dart'; - -import '../experimental/google_adsense.dart'; - -/// A singleton instance of AdSense library public interface. -final AdSense adSense = AdSense(); - -/// AdSense package interface. -class AdSense { - /// Initialization API. Should be called ASAP, ideally in the main method of your app. - void initialize( - String adClient, { - @visibleForTesting bool skipJsLoader = false, - @visibleForTesting Object? jsLoaderTarget, - }) { - throw UnsupportedError('Only supported on web'); - } - - /// Returns a configurable [AdUnitWidget]
- /// `configuration`: see [AdUnitConfiguration] - Widget adUnit(AdUnitConfiguration configuration) { - throw UnsupportedError('Only supported on web'); - } -} diff --git a/packages/google_adsense/lib/src/adsense_web.dart b/packages/google_adsense/lib/src/core/google_adsense.dart similarity index 71% rename from packages/google_adsense/lib/src/adsense_web.dart rename to packages/google_adsense/lib/src/core/google_adsense.dart index 79434b1b616c..3a56b5af92dc 100644 --- a/packages/google_adsense/lib/src/adsense_web.dart +++ b/packages/google_adsense/lib/src/core/google_adsense.dart @@ -7,57 +7,47 @@ import 'dart:js_interop'; import 'package:flutter/widgets.dart'; import 'package:web/web.dart' as web; -import 'ad_unit_configuration.dart'; -import 'ad_unit_widget.dart'; -import 'js_interop/adsbygoogle.dart' show adsbygooglePresent; -import 'js_interop/package_web_tweaks.dart'; +import '../js_interop/adsbygoogle.dart' show adsbygooglePresent; +import '../js_interop/package_web_tweaks.dart'; -import 'logging.dart'; +import '../utils/logging.dart'; -/// Returns a singleton instance of Adsense library public interface -final AdSense adSense = AdSense(); - -/// Main class to work with the library +/// The web implementation of the AdSense API. class AdSense { bool _isInitialized = false; - /// The ad client ID used by this client. - late String _adClient; + /// The [Publisher ID](https://support.google.com/adsense/answer/2923881). + late String adClient; static const String _url = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-'; /// Initializes the AdSense SDK with your [adClient]. /// - /// Should be called ASAP, ideally in the main method of your app. + /// The [adClient] parameter is your AdSense [Publisher ID](https://support.google.com/adsense/answer/2923881). /// - /// Noops after the first call. - void initialize( + /// Should be called ASAP, ideally in the `main` method. + Future initialize( String adClient, { @visibleForTesting bool skipJsLoader = false, @visibleForTesting web.HTMLElement? jsLoaderTarget, - }) { + }) async { if (_isInitialized) { debugLog('adSense.initialize called multiple times. Skipping init.'); return; } - _adClient = adClient; + this.adClient = adClient; if (!(skipJsLoader || _sdkAlreadyLoaded(testingTarget: jsLoaderTarget))) { - _loadJsSdk(_adClient, jsLoaderTarget); + _loadJsSdk(adClient, jsLoaderTarget); } else { debugLog('SDK already on page. Skipping init.'); } _isInitialized = true; } - /// Returns an [AdUnitWidget] with the specified [configuration]. - Widget adUnit(AdUnitConfiguration configuration) { - return AdUnitWidget(adClient: _adClient, configuration: configuration); - } - bool _sdkAlreadyLoaded({ web.HTMLElement? testingTarget, }) { - final String selector = 'script[src*=ca-pub-$_adClient]'; + final String selector = 'script[src*=ca-pub-$adClient]'; return adsbygooglePresent || web.document.querySelector(selector) != null || testingTarget?.querySelector(selector) != null; @@ -91,3 +81,6 @@ class AdSense { (testingTarget ?? web.document.head)!.appendChild(script); } } + +/// The singleton instance of the AdSense SDK. +final AdSense adSense = AdSense(); diff --git a/packages/google_adsense/lib/src/js_interop/adsbygoogle.dart b/packages/google_adsense/lib/src/js_interop/adsbygoogle.dart index 1cdf98d6eadc..bf97d23e978c 100644 --- a/packages/google_adsense/lib/src/js_interop/adsbygoogle.dart +++ b/packages/google_adsense/lib/src/js_interop/adsbygoogle.dart @@ -9,16 +9,8 @@ import 'dart:js_interop'; /// JS-interop mappings to the window.adsbygoogle object. extension type AdsByGoogle._(JSObject _) implements JSObject { - @JS('push') - external void _push(JSObject params); -} - -/// Convenience methods for Dart users. -extension AdsByGoogleExtension on AdsByGoogle { - /// Convenience method for invoking push() with an empty object - void requestAd() { - _push(JSObject()); - } + /// Pushes some `params` to the `window.adsbygoogle` object. + external void push(JSObject params); } // window.adsbygoogle may be null if this package runs before the JS SDK loads. diff --git a/packages/google_adsense/lib/src/logging.dart b/packages/google_adsense/lib/src/utils/logging.dart similarity index 100% rename from packages/google_adsense/lib/src/logging.dart rename to packages/google_adsense/lib/src/utils/logging.dart diff --git a/packages/google_adsense/pubspec.yaml b/packages/google_adsense/pubspec.yaml index e9db445d5121..5739583d2689 100644 --- a/packages/google_adsense/pubspec.yaml +++ b/packages/google_adsense/pubspec.yaml @@ -2,7 +2,7 @@ name: google_adsense description: A wrapper plugin with convenience APIs allowing easier inserting Google Adsense HTML snippets withing a Flutter UI Web application repository: https://github.com/flutter/packages/tree/main/packages/google_adsense issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_adsense%22 -version: 0.0.1 +version: 0.0.2 environment: sdk: ^3.4.0 From 0f1fd493b893c02ac37544cfd31f5c4f184202db Mon Sep 17 00:00:00 2001 From: Camille Simon <43054281+camsim99@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:58:25 -0500 Subject: [PATCH 04/24] [dependabot] Generalizes dependabot commit message prefix (#8255) Changes dependabot commit message prefix from "[gradle]" to "[dependabot]" since dependabot handles more than Gradle updates. Also updates dependabot configuration docs link since the one included didn't work for me. --- .github/dependabot.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c15ca70a1e09..53ed01fbf7ca 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,5 +1,5 @@ # See Dependabot documentation for all configuration options: -# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file version: 2 updates: @@ -66,7 +66,7 @@ updates: - /packages/webview_flutter/webview_flutter_android/example/android/app - /third_party/packages/flutter_svg/example/android/app commit-message: - prefix: "[gradle]" + prefix: "[dependabot]" schedule: interval: "weekly" labels: @@ -99,7 +99,7 @@ updates: - /packages/video_player/video_player_android/android - /packages/webview_flutter/webview_flutter_android/android commit-message: - prefix: "[gradle]" + prefix: "[dependabot]" schedule: interval: "weekly" open-pull-requests-limit: 10 From a02deb49c1f6bcb8bb895dd67fbf36ac2c9738bd Mon Sep 17 00:00:00 2001 From: Sinyu Date: Tue, 10 Dec 2024 23:59:05 +0800 Subject: [PATCH 05/24] [quick_action_ios] add localizedSubtitle for iOS (#8149) This is prequel PR for: https://github.com/flutter/packages/pull/8038 Containing only changes to quick_action_ios package. Add the localizedSubtitle field on quick actions for iOS https://github.com/flutter/flutter/issues/129759 --- .../quick_actions_ios/CHANGELOG.md | 3 +- .../ios/RunnerUITests/RunnerUITests.swift | 3 +- .../quick_actions_ios/example/lib/main.dart | 1 + .../QuickActionsPlugin.swift | 9 ++---- .../quick_actions_ios/messages.g.swift | 10 ++++++- .../quick_actions_ios/lib/messages.g.dart | 8 +++++- .../lib/quick_actions_ios.dart | 1 + .../quick_actions_ios/pigeons/messages.dart | 4 +++ .../quick_actions_ios/pubspec.yaml | 4 +-- .../test/quick_actions_ios_test.dart | 28 +++++++++++++++---- 10 files changed, 53 insertions(+), 18 deletions(-) diff --git a/packages/quick_actions/quick_actions_ios/CHANGELOG.md b/packages/quick_actions/quick_actions_ios/CHANGELOG.md index 92d4fe6b1df7..b49fb3602909 100644 --- a/packages/quick_actions/quick_actions_ios/CHANGELOG.md +++ b/packages/quick_actions/quick_actions_ios/CHANGELOG.md @@ -1,5 +1,6 @@ -## NEXT +## 1.2.0 +* Adds localizedSubtitle field for iOS quick actions. * Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. ## 1.1.1 diff --git a/packages/quick_actions/quick_actions_ios/example/ios/RunnerUITests/RunnerUITests.swift b/packages/quick_actions/quick_actions_ios/example/ios/RunnerUITests/RunnerUITests.swift index ad4c03f008ea..3bc0d2109be9 100644 --- a/packages/quick_actions/quick_actions_ios/example/ios/RunnerUITests/RunnerUITests.swift +++ b/packages/quick_actions/quick_actions_ios/example/ios/RunnerUITests/RunnerUITests.swift @@ -75,7 +75,8 @@ class RunnerUITests: XCTestCase { } findAndTapQuickActionButton( - buttonName: "Action one", quickActionsAppIcon: quickActionsAppIcon, springboard: springboard) + buttonName: "Action one, Action one subtitle", quickActionsAppIcon: quickActionsAppIcon, + springboard: springboard) let actionOneConfirmation = exampleApp.otherElements["action_one"] if !actionOneConfirmation.waitForExistence(timeout: elementWaitingTime) { diff --git a/packages/quick_actions/quick_actions_ios/example/lib/main.dart b/packages/quick_actions/quick_actions_ios/example/lib/main.dart index f3e9f92b2cbb..a170376135d9 100644 --- a/packages/quick_actions/quick_actions_ios/example/lib/main.dart +++ b/packages/quick_actions/quick_actions_ios/example/lib/main.dart @@ -51,6 +51,7 @@ class _MyHomePageState extends State { const ShortcutItem( type: 'action_one', localizedTitle: 'Action one', + localizedSubtitle: 'Action one subtitle', icon: 'AppIcon', ), const ShortcutItem( diff --git a/packages/quick_actions/quick_actions_ios/ios/quick_actions_ios/Sources/quick_actions_ios/QuickActionsPlugin.swift b/packages/quick_actions/quick_actions_ios/ios/quick_actions_ios/Sources/quick_actions_ios/QuickActionsPlugin.swift index dc8ffb812f36..fb7938f7b54e 100644 --- a/packages/quick_actions/quick_actions_ios/ios/quick_actions_ios/Sources/quick_actions_ios/QuickActionsPlugin.swift +++ b/packages/quick_actions/quick_actions_ios/ios/quick_actions_ios/Sources/quick_actions_ios/QuickActionsPlugin.swift @@ -90,18 +90,15 @@ public final class QuickActionsPlugin: NSObject, FlutterPlugin, IOSQuickActionsA -> UIApplicationShortcutItem? { - let type = shortcut.type - let localizedTitle = shortcut.localizedTitle - let icon = (shortcut.icon).map { UIApplicationShortcutIcon(templateImageName: $0) } // type and localizedTitle are required. return UIApplicationShortcutItem( - type: type, - localizedTitle: localizedTitle, - localizedSubtitle: nil, + type: shortcut.type, + localizedTitle: shortcut.localizedTitle, + localizedSubtitle: shortcut.localizedSubtitle, icon: icon, userInfo: nil) } diff --git a/packages/quick_actions/quick_actions_ios/ios/quick_actions_ios/Sources/quick_actions_ios/messages.g.swift b/packages/quick_actions/quick_actions_ios/ios/quick_actions_ios/Sources/quick_actions_ios/messages.g.swift index f4a4091c333e..dbfea4f1e026 100644 --- a/packages/quick_actions/quick_actions_ios/ios/quick_actions_ios/Sources/quick_actions_ios/messages.g.swift +++ b/packages/quick_actions/quick_actions_ios/ios/quick_actions_ios/Sources/quick_actions_ios/messages.g.swift @@ -81,6 +81,8 @@ struct ShortcutItemMessage { var type: String /// Localized title of the item. var localizedTitle: String + /// Localized subtitle of the item. + var localizedSubtitle: String? = nil /// Name of native resource to be displayed as the icon for this item. var icon: String? = nil @@ -88,11 +90,13 @@ struct ShortcutItemMessage { static func fromList(_ __pigeon_list: [Any?]) -> ShortcutItemMessage? { let type = __pigeon_list[0] as! String let localizedTitle = __pigeon_list[1] as! String - let icon: String? = nilOrValue(__pigeon_list[2]) + let localizedSubtitle: String? = nilOrValue(__pigeon_list[2]) + let icon: String? = nilOrValue(__pigeon_list[3]) return ShortcutItemMessage( type: type, localizedTitle: localizedTitle, + localizedSubtitle: localizedSubtitle, icon: icon ) } @@ -100,10 +104,12 @@ struct ShortcutItemMessage { return [ type, localizedTitle, + localizedSubtitle, icon, ] } } + private class messagesPigeonCodecReader: FlutterStandardReader { override func readValue(ofType type: UInt8) -> Any? { switch type { @@ -195,12 +201,14 @@ class IOSQuickActionsApiSetup { } } } + /// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift. protocol IOSQuickActionsFlutterApiProtocol { /// Sends a string representing a shortcut from the native platform to the app. func launchAction( action actionArg: String, completion: @escaping (Result) -> Void) } + class IOSQuickActionsFlutterApi: IOSQuickActionsFlutterApiProtocol { private let binaryMessenger: FlutterBinaryMessenger private let messageChannelSuffix: String diff --git a/packages/quick_actions/quick_actions_ios/lib/messages.g.dart b/packages/quick_actions/quick_actions_ios/lib/messages.g.dart index 199871ff803c..6678bbc840be 100644 --- a/packages/quick_actions/quick_actions_ios/lib/messages.g.dart +++ b/packages/quick_actions/quick_actions_ios/lib/messages.g.dart @@ -34,6 +34,7 @@ class ShortcutItemMessage { ShortcutItemMessage({ required this.type, required this.localizedTitle, + this.localizedSubtitle, this.icon, }); @@ -43,6 +44,9 @@ class ShortcutItemMessage { /// Localized title of the item. String localizedTitle; + /// Localized subtitle of the item. + String? localizedSubtitle; + /// Name of native resource to be displayed as the icon for this item. String? icon; @@ -50,6 +54,7 @@ class ShortcutItemMessage { return [ type, localizedTitle, + localizedSubtitle, icon, ]; } @@ -59,7 +64,8 @@ class ShortcutItemMessage { return ShortcutItemMessage( type: result[0]! as String, localizedTitle: result[1]! as String, - icon: result[2] as String?, + localizedSubtitle: result[2] as String?, + icon: result[3] as String?, ); } } diff --git a/packages/quick_actions/quick_actions_ios/lib/quick_actions_ios.dart b/packages/quick_actions/quick_actions_ios/lib/quick_actions_ios.dart index b002e0ec136d..e90b68333ed4 100644 --- a/packages/quick_actions/quick_actions_ios/lib/quick_actions_ios.dart +++ b/packages/quick_actions/quick_actions_ios/lib/quick_actions_ios.dart @@ -47,6 +47,7 @@ class QuickActionsIos extends QuickActionsPlatform { return ShortcutItemMessage( type: item.type, localizedTitle: item.localizedTitle, + localizedSubtitle: item.localizedSubtitle, icon: item.icon, ); } diff --git a/packages/quick_actions/quick_actions_ios/pigeons/messages.dart b/packages/quick_actions/quick_actions_ios/pigeons/messages.dart index 7cf7d20d587f..043d4ba7cc3f 100644 --- a/packages/quick_actions/quick_actions_ios/pigeons/messages.dart +++ b/packages/quick_actions/quick_actions_ios/pigeons/messages.dart @@ -15,6 +15,7 @@ class ShortcutItemMessage { ShortcutItemMessage( this.type, this.localizedTitle, + this.localizedSubtitle, this.icon, ); @@ -24,6 +25,9 @@ class ShortcutItemMessage { /// Localized title of the item. String localizedTitle; + /// Localized subtitle of the item. + String? localizedSubtitle; + /// Name of native resource to be displayed as the icon for this item. String? icon; } diff --git a/packages/quick_actions/quick_actions_ios/pubspec.yaml b/packages/quick_actions/quick_actions_ios/pubspec.yaml index b4cc92f3a897..a3ba140e2e81 100644 --- a/packages/quick_actions/quick_actions_ios/pubspec.yaml +++ b/packages/quick_actions/quick_actions_ios/pubspec.yaml @@ -2,7 +2,7 @@ name: quick_actions_ios description: An implementation for the iOS platform of the Flutter `quick_actions` plugin. repository: https://github.com/flutter/packages/tree/main/packages/quick_actions/quick_actions_ios issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+in_app_purchase%22 -version: 1.1.1 +version: 1.2.0 environment: sdk: ^3.3.0 @@ -19,7 +19,7 @@ flutter: dependencies: flutter: sdk: flutter - quick_actions_platform_interface: ^1.0.0 + quick_actions_platform_interface: ^1.1.0 dev_dependencies: flutter_test: diff --git a/packages/quick_actions/quick_actions_ios/test/quick_actions_ios_test.dart b/packages/quick_actions/quick_actions_ios/test/quick_actions_ios_test.dart index eff84081274d..b53137dcc9db 100644 --- a/packages/quick_actions/quick_actions_ios/test/quick_actions_ios_test.dart +++ b/packages/quick_actions/quick_actions_ios/test/quick_actions_ios_test.dart @@ -26,19 +26,28 @@ void main() { test('setShortcutItems', () async { await quickActions.initialize((String type) {}); - const ShortcutItem item = - ShortcutItem(type: 'test', localizedTitle: 'title', icon: 'icon.svg'); + const ShortcutItem item = ShortcutItem( + type: 'test', + localizedTitle: 'title', + localizedSubtitle: 'subtitle', + icon: 'icon.svg', + ); await quickActions.setShortcutItems([item]); expect(api.items.first.type, item.type); expect(api.items.first.localizedTitle, item.localizedTitle); + expect(api.items.first.localizedSubtitle, item.localizedSubtitle); expect(api.items.first.icon, item.icon); }); test('clearShortCutItems', () { quickActions.initialize((String type) {}); - const ShortcutItem item = - ShortcutItem(type: 'test', localizedTitle: 'title', icon: 'icon.svg'); + const ShortcutItem item = ShortcutItem( + type: 'test', + localizedTitle: 'title', + localizedSubtitle: 'subtitle', + icon: 'icon.svg', + ); quickActions.setShortcutItems([item]); quickActions.clearShortcutItems(); @@ -48,13 +57,19 @@ void main() { test('Shortcut item can be constructed', () { const String type = 'type'; const String localizedTitle = 'title'; + const String localizedSubtitle = 'subtitle'; const String icon = 'foo'; - const ShortcutItem item = - ShortcutItem(type: type, localizedTitle: localizedTitle, icon: icon); + const ShortcutItem item = ShortcutItem( + type: type, + localizedTitle: localizedTitle, + localizedSubtitle: localizedSubtitle, + icon: icon, + ); expect(item.type, type); expect(item.localizedTitle, localizedTitle); + expect(item.localizedSubtitle, localizedSubtitle); expect(item.icon, icon); }); } @@ -83,6 +98,7 @@ ShortcutItem shortcutItemMessageToShortcutItem(ShortcutItemMessage item) { return ShortcutItem( type: item.type, localizedTitle: item.localizedTitle, + localizedSubtitle: item.localizedSubtitle, icon: item.icon, ); } From 16616ad588d7ad9c00958ec61022e5b5dde5f5dd Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Tue, 10 Dec 2024 16:13:19 -0500 Subject: [PATCH 06/24] Manual roll Flutter from ab5b20c16d56 to 456366232af9 (10 revisions) (#8264) Manual roll requested by tarrinneal@google.com https://github.com/flutter/flutter/compare/ab5b20c16d56...456366232af9 2024-12-05 ditman@gmail.com [ci] Add google_adsense to 9_first_party_packages.yml (flutter/flutter#159827) 2024-12-05 jonahwilliams@google.com [flutter_tools] configure shader compiler to output GLES3 shaders for Android. (flutter/flutter#159857) 2024-12-05 tessertaha@gmail.com Introduce Material 3 `year2023` flag to `ProgressIndicatorThemeData` (flutter/flutter#159720) 2024-12-05 tessertaha@gmail.com Updated Material 3 `Slider` Samples (flutter/flutter#159795) 2024-12-05 tessertaha@gmail.com Updated Material 3 Progress Indicators Samples (flutter/flutter#158925) 2024-12-05 andrewrkolos@gmail.com Remove some usages of package:usage (flutter/flutter#159705) 2024-12-05 anis.alibegic@gmail.com Fixed typos (flutter/flutter#159331) 2024-12-05 bruno.leroux@gmail.com Reland Fix Date picker overlay colors aren't applied on selected state (flutter/flutter#159839) 2024-12-05 mohellebiabdessalem@gmail.com fix failing lint in MainActivity.kt.tmpl (flutter/flutter#159441) 2024-12-05 engine-flutter-autoroll@skia.org Roll Flutter Engine from 05e2d6597cb2 to b4f52b275535 (1 revision) (flutter/flutter#159842) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC stuartmorgan@google.com,tarrinneal@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md --- .ci/flutter_master.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/flutter_master.version b/.ci/flutter_master.version index 56b0bf516de5..e0822338d97d 100644 --- a/.ci/flutter_master.version +++ b/.ci/flutter_master.version @@ -1 +1 @@ -ab5b20c16d56c8e608773ce65c3f7c39d515d4a5 +456366232af95b5cc447b7c42d0d5ef928347c45 From 374d1bef1033688165359ee7b76330139d9c3cb8 Mon Sep 17 00:00:00 2001 From: Naomi Watanabe Date: Thu, 12 Dec 2024 02:43:26 +0900 Subject: [PATCH 07/24] [video_player_avfoundation] Support the audio-only HLS (.m3u8) on iOS (#7890) Supports the audio-only HLS on iOS. After through https://github.com/flutter/plugins/pull/4639 and https://github.com/flutter/plugins/pull/4727, we can play HLS videos and audios, but it does not support audio-only HLS. When attempting to play that on iOS, it never finishes initialization. Show the before/after demonstration here: https://github.com/flutter/flutter/issues/156589#issuecomment-2408846446 Fixes: https://github.com/flutter/flutter/issues/156589 Test with https://github.com/flutter/assets-for-api-docs/pull/252 --- .../video_player_avfoundation/CHANGELOG.md | 4 ++++ .../darwin/RunnerTests/VideoPlayerTests.m | 16 ++++++++++++++++ .../video_player_avfoundation/FVPVideoPlayer.m | 4 +++- .../video_player_avfoundation/pubspec.yaml | 2 +- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/CHANGELOG.md b/packages/video_player/video_player_avfoundation/CHANGELOG.md index 55d1435a1188..eff85341000b 100644 --- a/packages/video_player/video_player_avfoundation/CHANGELOG.md +++ b/packages/video_player/video_player_avfoundation/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.6.5 + +* Bugfix to allow the audio-only HLS (.m3u8) on iOS. + ## 2.6.4 * Refactors native code structure. diff --git a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m index 02b9199a74fa..f35d38bd9895 100644 --- a/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m +++ b/packages/video_player/video_player_avfoundation/darwin/RunnerTests/VideoPlayerTests.m @@ -530,6 +530,22 @@ - (void)testHLSControls { XCTAssertEqualWithAccuracy([videoInitialization[@"duration"] intValue], 4000, 200); } +- (void)testAudioOnlyHLSControls { + NSObject *registrar = + [GetPluginRegistry() registrarForPlugin:@"TestAudioOnlyHLSControls"]; + + FVPVideoPlayerPlugin *videoPlayerPlugin = + (FVPVideoPlayerPlugin *)[[FVPVideoPlayerPlugin alloc] initWithRegistrar:registrar]; + + NSDictionary *videoInitialization = + [self testPlugin:videoPlayerPlugin + uri:@"https://flutter.github.io/assets-for-api-docs/assets/videos/hls/" + @"bee_audio_only.m3u8"]; + XCTAssertEqualObjects(videoInitialization[@"height"], @0); + XCTAssertEqualObjects(videoInitialization[@"width"], @0); + XCTAssertEqualWithAccuracy([videoInitialization[@"duration"] intValue], 4000, 200); +} + #if TARGET_OS_IOS - (void)testTransformFix { [self validateTransformFixForOrientation:UIImageOrientationUp]; diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m index 31573da4039f..5892274a37db 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation/FVPVideoPlayer.m @@ -383,7 +383,9 @@ - (void)setupEventSinkIfReadyToPlay { } BOOL hasVideoTracks = [asset tracksWithMediaType:AVMediaTypeVideo].count != 0; - BOOL hasNoTracks = asset.tracks.count == 0; + // Audio-only HLS files have no size, so `currentItem.tracks.count` must be used to check for + // track presence, as AVAsset does not always provide track information in HLS streams. + BOOL hasNoTracks = currentItem.tracks.count == 0 && asset.tracks.count == 0; // The player has not yet initialized when it has no size, unless it is an audio-only track. // HLS m3u8 video files never load any tracks, and are also not yet initialized until they have diff --git a/packages/video_player/video_player_avfoundation/pubspec.yaml b/packages/video_player/video_player_avfoundation/pubspec.yaml index 233a9b65e86b..632e59f60fd5 100644 --- a/packages/video_player/video_player_avfoundation/pubspec.yaml +++ b/packages/video_player/video_player_avfoundation/pubspec.yaml @@ -2,7 +2,7 @@ name: video_player_avfoundation description: iOS and macOS implementation of the video_player plugin. repository: https://github.com/flutter/packages/tree/main/packages/video_player/video_player_avfoundation issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22 -version: 2.6.4 +version: 2.6.5 environment: sdk: ^3.3.0 From 8238e1c5ada8c6a99f7fb6087484b52face33721 Mon Sep 17 00:00:00 2001 From: Sinyu Date: Thu, 12 Dec 2024 02:57:58 +0800 Subject: [PATCH 08/24] [quick_actions] add localizedSubtitle for iOS (#8038) Add the localizedSubtitle field on quick actions for iOS https://github.com/flutter/flutter/issues/129759 Pre-launch Checklist I read and followed the [relevant style guides](https://github.com/flutter/packages/blob/main/CONTRIBUTING.md#style) and ran the auto-formatter. (Unlike the flutter/flutter repo, the flutter/packages repo does use dart format.) --- packages/quick_actions/quick_actions/CHANGELOG.md | 4 ++++ packages/quick_actions/quick_actions/README.md | 2 +- .../quick_actions/quick_actions/example/lib/main.dart | 8 +++++--- packages/quick_actions/quick_actions/pubspec.yaml | 6 +++--- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/quick_actions/quick_actions/CHANGELOG.md b/packages/quick_actions/quick_actions/CHANGELOG.md index 8a2bccc7641e..b66476c12e18 100644 --- a/packages/quick_actions/quick_actions/CHANGELOG.md +++ b/packages/quick_actions/quick_actions/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.1.0 + +* Adds localizedSubtitle field for iOS quick actions. + ## 1.0.8 * Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. diff --git a/packages/quick_actions/quick_actions/README.md b/packages/quick_actions/quick_actions/README.md index d776be2a3bf7..563349daab0f 100644 --- a/packages/quick_actions/quick_actions/README.md +++ b/packages/quick_actions/quick_actions/README.md @@ -34,7 +34,7 @@ Finally, manage the app's quick actions, for instance: ```dart quickActions.setShortcutItems([ const ShortcutItem(type: 'action_main', localizedTitle: 'Main view', icon: 'icon_main'), - const ShortcutItem(type: 'action_help', localizedTitle: 'Help', icon: 'icon_help') + const ShortcutItem(type: 'action_help', localizedTitle: 'Help', localizedSubtitle: 'Tap to get help', icon: 'icon_help') ]); ``` diff --git a/packages/quick_actions/quick_actions/example/lib/main.dart b/packages/quick_actions/quick_actions/example/lib/main.dart index 14429284c621..d137710031a6 100644 --- a/packages/quick_actions/quick_actions/example/lib/main.dart +++ b/packages/quick_actions/quick_actions/example/lib/main.dart @@ -53,14 +53,16 @@ class _MyHomePageState extends State { const ShortcutItem( type: 'action_one', localizedTitle: 'Action one', + localizedSubtitle: 'Action one subtitle', icon: 'AppIcon', ), // NOTE: This second action icon will only work on Android. // In a real world project keep the same file name for both platforms. const ShortcutItem( - type: 'action_two', - localizedTitle: 'Action two', - icon: 'ic_launcher'), + type: 'action_two', + localizedTitle: 'Action two', + icon: 'ic_launcher', + ), ]).then((void _) { setState(() { if (shortcut == 'no action set') { diff --git a/packages/quick_actions/quick_actions/pubspec.yaml b/packages/quick_actions/quick_actions/pubspec.yaml index 65db456231d6..98fc3a3bf9f5 100644 --- a/packages/quick_actions/quick_actions/pubspec.yaml +++ b/packages/quick_actions/quick_actions/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for creating shortcuts on home screen, also known as Quick Actions on iOS and App Shortcuts on Android. repository: https://github.com/flutter/packages/tree/main/packages/quick_actions/quick_actions issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+quick_actions%22 -version: 1.0.8 +version: 1.1.0 environment: sdk: ^3.3.0 @@ -21,8 +21,8 @@ dependencies: flutter: sdk: flutter quick_actions_android: ^1.0.0 - quick_actions_ios: ^1.0.0 - quick_actions_platform_interface: ^1.0.0 + quick_actions_ios: ^1.2.0 + quick_actions_platform_interface: ^1.1.0 dev_dependencies: flutter_test: From 26373787d5c768a21befaec34300efb2df84cb52 Mon Sep 17 00:00:00 2001 From: Tarrin Neal Date: Wed, 11 Dec 2024 18:40:10 -0800 Subject: [PATCH 09/24] disable maps test and manual roll (#8275) Disables failing test while we wait for framework to look into bug https://github.com/flutter/flutter/issues/160115 manual roll --- .ci/flutter_master.version | 2 +- .../integration_test/src/maps_controller.dart | 105 +++++++++--------- 2 files changed, 56 insertions(+), 51 deletions(-) diff --git a/.ci/flutter_master.version b/.ci/flutter_master.version index e0822338d97d..b0267f8dd1c7 100644 --- a/.ci/flutter_master.version +++ b/.ci/flutter_master.version @@ -1 +1 @@ -456366232af95b5cc447b7c42d0d5ef928347c45 +918b2b9ddb437298dc5ff9e963ef139737371c4a \ No newline at end of file diff --git a/packages/google_maps_flutter/google_maps_flutter/example/integration_test/src/maps_controller.dart b/packages/google_maps_flutter/google_maps_flutter/example/integration_test/src/maps_controller.dart index 536adc32f07d..d44aa4d341e2 100644 --- a/packages/google_maps_flutter/google_maps_flutter/example/integration_test/src/maps_controller.dart +++ b/packages/google_maps_flutter/google_maps_flutter/example/integration_test/src/maps_controller.dart @@ -21,60 +21,65 @@ void main() { } void runTests() { - testWidgets('testInitialCenterLocationAtCenter', (WidgetTester tester) async { - await tester.binding.setSurfaceSize(const Size(800, 600)); + testWidgets( + 'testInitialCenterLocationAtCenter', + (WidgetTester tester) async { + await tester.binding.setSurfaceSize(const Size(800, 600)); - final Completer mapControllerCompleter = - Completer(); - final Key key = GlobalKey(); - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: GoogleMap( - key: key, - initialCameraPosition: kInitialCameraPosition, - onMapCreated: (GoogleMapController controller) { - mapControllerCompleter.complete(controller); - }, + final Completer mapControllerCompleter = + Completer(); + final Key key = GlobalKey(); + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: GoogleMap( + key: key, + initialCameraPosition: kInitialCameraPosition, + onMapCreated: (GoogleMapController controller) { + mapControllerCompleter.complete(controller); + }, + ), ), - ), - ); - final GoogleMapController mapController = - await mapControllerCompleter.future; - - await tester.pumpAndSettle(); + ); + final GoogleMapController mapController = + await mapControllerCompleter.future; - // TODO(cyanglaz): Remove this after we added `mapRendered` callback, and `mapControllerCompleter.complete(controller)` above should happen - // in `mapRendered`. - // https://github.com/flutter/flutter/issues/54758 - await Future.delayed(const Duration(seconds: 1)); + await tester.pumpAndSettle(); - final ScreenCoordinate coordinate = - await mapController.getScreenCoordinate(kInitialCameraPosition.target); - final Rect rect = tester.getRect(find.byKey(key)); - if (isIOS || isWeb) { - // On iOS, the coordinate value from the GoogleMapSdk doesn't include the devicePixelRatio`. - // So we don't need to do the conversion like we did below for other platforms. - expect(coordinate.x, (rect.center.dx - rect.topLeft.dx).round()); - expect(coordinate.y, (rect.center.dy - rect.topLeft.dy).round()); - } else { - expect( - coordinate.x, - ((rect.center.dx - rect.topLeft.dx) * tester.view.devicePixelRatio) - .round()); - expect( - coordinate.y, - ((rect.center.dy - rect.topLeft.dy) * tester.view.devicePixelRatio) - .round()); - } - await tester.binding.setSurfaceSize(null); - }, - // Android doesn't like the layout required for the web, so we skip web in this test. - // The equivalent web test already exists here: - // https://github.com/flutter/packages/blob/c43cc13498a1a1c4f3d1b8af2add9ce7c15bd6d0/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/projection_test.dart#L78 - skip: isWeb || - // TODO(stuartmorgan): Re-enable; see https://github.com/flutter/flutter/issues/139825 - isIOS); + // TODO(cyanglaz): Remove this after we added `mapRendered` callback, and `mapControllerCompleter.complete(controller)` above should happen + // in `mapRendered`. + // https://github.com/flutter/flutter/issues/54758 + await Future.delayed(const Duration(seconds: 1)); + + final ScreenCoordinate coordinate = await mapController + .getScreenCoordinate(kInitialCameraPosition.target); + final Rect rect = tester.getRect(find.byKey(key)); + if (isIOS || isWeb) { + // On iOS, the coordinate value from the GoogleMapSdk doesn't include the devicePixelRatio`. + // So we don't need to do the conversion like we did below for other platforms. + expect(coordinate.x, (rect.center.dx - rect.topLeft.dx).round()); + expect(coordinate.y, (rect.center.dy - rect.topLeft.dy).round()); + } else { + expect( + coordinate.x, + ((rect.center.dx - rect.topLeft.dx) * tester.view.devicePixelRatio) + .round()); + expect( + coordinate.y, + ((rect.center.dy - rect.topLeft.dy) * tester.view.devicePixelRatio) + .round()); + } + await tester.binding.setSurfaceSize(null); + }, + // Android doesn't like the layout required for the web, so we skip web in this test. + // The equivalent web test already exists here: + // https://github.com/flutter/packages/blob/c43cc13498a1a1c4f3d1b8af2add9ce7c15bd6d0/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/projection_test.dart#L78 + skip: isWeb || + // TODO(stuartmorgan): Re-enable; see https://github.com/flutter/flutter/issues/139825 + isIOS || + // TODO(tarrinneal): Re-enable; see https://github.com/flutter/flutter/issues/160115 + isAndroid, + ); testWidgets('testGetVisibleRegion', (WidgetTester tester) async { final Key key = GlobalKey(); From cbdb48a0bcee5865e6e5d29826d6f44cc1f0984d Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Wed, 11 Dec 2024 23:50:26 -0500 Subject: [PATCH 10/24] Manual roll Flutter from 918b2b9ddb43 to f559e16010a0 (4 revisions) (#8277) Manual roll requested by tarrinneal@google.com https://github.com/flutter/flutter/compare/918b2b9ddb43...f559e16010a0 2024-12-12 engine-flutter-autoroll@skia.org Roll Flutter Engine from e3524615fb69 to 92de3d0f8830 (1 revision) (flutter/flutter#160132) 2024-12-12 engine-flutter-autoroll@skia.org Roll Flutter Engine from b8034f152711 to e3524615fb69 (2 revisions) (flutter/flutter#160128) 2024-12-11 engine-flutter-autoroll@skia.org Roll Flutter Engine from ba7ad8719733 to b8034f152711 (3 revisions) (flutter/flutter#160126) 2024-12-11 engine-flutter-autoroll@skia.org Roll Flutter Engine from 3cdd84160baa to ba7ad8719733 (1 revision) (flutter/flutter#160117) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC stuartmorgan@google.com,tarrinneal@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md --- .ci/flutter_master.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/flutter_master.version b/.ci/flutter_master.version index b0267f8dd1c7..8b6b17564afc 100644 --- a/.ci/flutter_master.version +++ b/.ci/flutter_master.version @@ -1 +1 @@ -918b2b9ddb437298dc5ff9e963ef139737371c4a \ No newline at end of file +f559e16010a059d8b86f30cd7f0b033205adb627 From 2ad45023cbc4183a3ed798f0a8b2137fd2c74815 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Thu, 12 Dec 2024 10:40:57 -0500 Subject: [PATCH 11/24] Roll Flutter (stable) from dec2ee5c1f98 to 8495dee1fd4a (1318 revisions) (#8280) https://github.com/flutter/flutter/compare/dec2ee5c1f98...8495dee1fd4a If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-stable-packages Please CC stuartmorgan@google.com,tarrinneal@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter (stable): https://github.com/flutter/flutter/issues/new/choose To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md --- .ci/flutter_stable.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/flutter_stable.version b/.ci/flutter_stable.version index 7b7e72bcc6c8..c2957055b002 100644 --- a/.ci/flutter_stable.version +++ b/.ci/flutter_stable.version @@ -1 +1 @@ -dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668 +8495dee1fd4aacbe9de707e7581203232f591b2f From 4bb45fcc1a843812c555095a416e03342d5a7ac9 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Thu, 12 Dec 2024 15:45:18 -0500 Subject: [PATCH 12/24] Manual roll Flutter from f559e16010a0 to 6966a2eef1e9 (5 revisions) (#8283) Manual roll requested by tarrinneal@google.com https://github.com/flutter/flutter/compare/f559e16010a0...6966a2eef1e9 2024-12-12 engine-flutter-autoroll@skia.org Roll Packages from 16616ad588d7 to cbdb48a0bcee (4 revisions) (flutter/flutter#160170) 2024-12-12 engine-flutter-autoroll@skia.org Roll Flutter Engine from 4d8488f02cd8 to 0bcea845cd31 (1 revision) (flutter/flutter#160171) 2024-12-12 sstrickl@google.com Add entry-point annotations for test-only code. (flutter/flutter#160158) 2024-12-12 engine-flutter-autoroll@skia.org Roll Flutter Engine from 847deb2089a3 to 4d8488f02cd8 (2 revisions) (flutter/flutter#160165) 2024-12-12 engine-flutter-autoroll@skia.org Roll Flutter Engine from 92de3d0f8830 to 847deb2089a3 (2 revisions) (flutter/flutter#160134) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC stuartmorgan@google.com,tarrinneal@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md --- .ci/flutter_master.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/flutter_master.version b/.ci/flutter_master.version index 8b6b17564afc..d52e94304bb7 100644 --- a/.ci/flutter_master.version +++ b/.ci/flutter_master.version @@ -1 +1 @@ -f559e16010a059d8b86f30cd7f0b033205adb627 +6966a2eef1e98fc326ea240525f1d42e0b4a4806 From a77fb8171c9e9cd7507d91f240d6bfd245128c9b Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Thu, 12 Dec 2024 13:48:38 -0800 Subject: [PATCH 13/24] [ci] Update for 3.27 stable release (#8284) Updates CI with the steps from [the stable release playbook](https://github.com/flutter/flutter/blob/master/docs/ecosystem/release/Updating-Packages-repo-for-a-stable-release.md) to account for the new 3.27 stable release. --- .ci.yaml | 8 ++++---- .ci/targets/repo_checks.yaml | 2 +- .github/workflows/release.yml | 2 +- packages/animations/CHANGELOG.md | 2 +- packages/animations/example/pubspec.yaml | 4 ++-- packages/animations/pubspec.yaml | 4 ++-- packages/camera/camera/CHANGELOG.md | 4 ++++ packages/camera/camera/example/pubspec.yaml | 4 ++-- packages/camera/camera/pubspec.yaml | 4 ++-- packages/camera/camera_avfoundation/CHANGELOG.md | 4 ++++ packages/camera/camera_avfoundation/example/pubspec.yaml | 4 ++-- packages/camera/camera_avfoundation/pubspec.yaml | 4 ++-- packages/camera/camera_platform_interface/CHANGELOG.md | 2 +- packages/camera/camera_platform_interface/pubspec.yaml | 4 ++-- packages/camera/camera_windows/CHANGELOG.md | 4 ++++ packages/camera/camera_windows/example/pubspec.yaml | 4 ++-- packages/camera/camera_windows/pubspec.yaml | 4 ++-- packages/cross_file/CHANGELOG.md | 2 +- packages/cross_file/example/pubspec.yaml | 2 +- packages/cross_file/pubspec.yaml | 2 +- packages/css_colors/CHANGELOG.md | 2 +- packages/css_colors/pubspec.yaml | 4 ++-- .../CHANGELOG.md | 2 +- .../example/pubspec.yaml | 4 ++-- .../pubspec.yaml | 4 ++-- packages/file_selector/file_selector/CHANGELOG.md | 2 +- packages/file_selector/file_selector/example/pubspec.yaml | 4 ++-- packages/file_selector/file_selector/pubspec.yaml | 4 ++-- packages/file_selector/file_selector_ios/CHANGELOG.md | 4 ++++ .../file_selector/file_selector_ios/example/pubspec.yaml | 4 ++-- packages/file_selector/file_selector_ios/pubspec.yaml | 4 ++-- packages/file_selector/file_selector_linux/CHANGELOG.md | 4 ++++ .../file_selector_linux/example/pubspec.yaml | 4 ++-- packages/file_selector/file_selector_linux/pubspec.yaml | 4 ++-- packages/file_selector/file_selector_macos/CHANGELOG.md | 4 ++++ .../file_selector_macos/example/pubspec.yaml | 4 ++-- packages/file_selector/file_selector_macos/pubspec.yaml | 4 ++-- .../file_selector_platform_interface/CHANGELOG.md | 2 +- .../file_selector_platform_interface/pubspec.yaml | 4 ++-- packages/file_selector/file_selector_windows/CHANGELOG.md | 4 ++++ .../file_selector_windows/example/pubspec.yaml | 4 ++-- packages/file_selector/file_selector_windows/pubspec.yaml | 4 ++-- packages/flutter_image/CHANGELOG.md | 2 +- packages/flutter_image/example/pubspec.yaml | 4 ++-- packages/flutter_image/pubspec.yaml | 4 ++-- packages/flutter_lints/CHANGELOG.md | 4 ++++ packages/flutter_lints/example/pubspec.yaml | 2 +- packages/flutter_markdown/CHANGELOG.md | 4 ++++ packages/flutter_markdown/example/pubspec.yaml | 4 ++-- packages/flutter_markdown/pubspec.yaml | 4 ++-- packages/flutter_migrate/CHANGELOG.md | 4 ++++ packages/flutter_migrate/pubspec.yaml | 2 +- packages/flutter_template_images/CHANGELOG.md | 2 +- packages/flutter_template_images/pubspec.yaml | 2 +- packages/go_router/CHANGELOG.md | 4 ++++ packages/go_router/example/pubspec.yaml | 4 ++-- packages/go_router/pubspec.yaml | 4 ++-- packages/go_router_builder/CHANGELOG.md | 2 +- packages/go_router_builder/example/pubspec.yaml | 2 +- packages/go_router_builder/pubspec.yaml | 4 ++-- .../google_maps_flutter/google_maps_flutter/CHANGELOG.md | 4 ++++ .../google_maps_flutter/example/pubspec.yaml | 4 ++-- .../google_maps_flutter_ios/CHANGELOG.md | 4 ++++ .../google_maps_flutter_ios/example/ios14/pubspec.yaml | 4 ++-- .../google_maps_flutter_ios/example/ios15/pubspec.yaml | 4 ++-- .../example/shared/maps_example_dart/pubspec.yaml | 4 ++-- .../google_maps_flutter_ios/pubspec.yaml | 4 ++-- .../google_maps_flutter_platform_interface/CHANGELOG.md | 4 ++++ .../google_maps_flutter_platform_interface/pubspec.yaml | 4 ++-- packages/google_sign_in/google_sign_in/CHANGELOG.md | 4 ++++ .../google_sign_in/google_sign_in/example/pubspec.yaml | 4 ++-- packages/google_sign_in/google_sign_in/pubspec.yaml | 4 ++-- packages/google_sign_in/google_sign_in_ios/CHANGELOG.md | 4 ++++ .../google_sign_in_ios/example/pubspec.yaml | 4 ++-- packages/google_sign_in/google_sign_in_ios/pubspec.yaml | 4 ++-- .../google_sign_in_platform_interface/CHANGELOG.md | 2 +- .../google_sign_in_platform_interface/pubspec.yaml | 4 ++-- packages/google_sign_in/google_sign_in_web/CHANGELOG.md | 4 ++++ .../google_sign_in_web/example/pubspec.yaml | 4 ++-- packages/google_sign_in/google_sign_in_web/pubspec.yaml | 4 ++-- packages/image_picker/image_picker/CHANGELOG.md | 4 ++++ packages/image_picker/image_picker/example/pubspec.yaml | 4 ++-- packages/image_picker/image_picker/pubspec.yaml | 4 ++-- packages/image_picker/image_picker_ios/CHANGELOG.md | 4 ++++ .../image_picker/image_picker_ios/example/pubspec.yaml | 4 ++-- packages/image_picker/image_picker_ios/pubspec.yaml | 4 ++-- packages/image_picker/image_picker_linux/CHANGELOG.md | 2 +- .../image_picker/image_picker_linux/example/pubspec.yaml | 4 ++-- packages/image_picker/image_picker_linux/pubspec.yaml | 4 ++-- packages/image_picker/image_picker_macos/CHANGELOG.md | 2 +- .../image_picker/image_picker_macos/example/pubspec.yaml | 4 ++-- packages/image_picker/image_picker_macos/pubspec.yaml | 4 ++-- .../image_picker_platform_interface/CHANGELOG.md | 4 ++++ .../image_picker_platform_interface/pubspec.yaml | 4 ++-- packages/image_picker/image_picker_windows/CHANGELOG.md | 2 +- .../image_picker_windows/example/pubspec.yaml | 4 ++-- packages/image_picker/image_picker_windows/pubspec.yaml | 4 ++-- packages/in_app_purchase/in_app_purchase/CHANGELOG.md | 2 +- .../in_app_purchase/in_app_purchase/example/pubspec.yaml | 4 ++-- packages/in_app_purchase/in_app_purchase/pubspec.yaml | 4 ++-- .../in_app_purchase_platform_interface/CHANGELOG.md | 2 +- .../in_app_purchase_platform_interface/pubspec.yaml | 4 ++-- .../in_app_purchase/in_app_purchase_storekit/CHANGELOG.md | 4 ++++ .../in_app_purchase_storekit/example/pubspec.yaml | 4 ++-- .../in_app_purchase/in_app_purchase_storekit/pubspec.yaml | 4 ++-- packages/ios_platform_images/CHANGELOG.md | 4 ++++ packages/ios_platform_images/example/pubspec.yaml | 4 ++-- packages/ios_platform_images/pubspec.yaml | 4 ++-- packages/local_auth/local_auth/CHANGELOG.md | 2 +- packages/local_auth/local_auth/example/pubspec.yaml | 4 ++-- packages/local_auth/local_auth/pubspec.yaml | 4 ++-- packages/local_auth/local_auth_darwin/CHANGELOG.md | 4 ++++ .../local_auth/local_auth_darwin/example/pubspec.yaml | 4 ++-- packages/local_auth/local_auth_darwin/pubspec.yaml | 4 ++-- .../local_auth/local_auth_platform_interface/CHANGELOG.md | 2 +- .../local_auth/local_auth_platform_interface/pubspec.yaml | 4 ++-- packages/local_auth/local_auth_windows/CHANGELOG.md | 2 +- .../local_auth/local_auth_windows/example/pubspec.yaml | 4 ++-- packages/local_auth/local_auth_windows/pubspec.yaml | 4 ++-- packages/metrics_center/CHANGELOG.md | 2 +- packages/metrics_center/pubspec.yaml | 2 +- packages/multicast_dns/CHANGELOG.md | 2 +- packages/multicast_dns/pubspec.yaml | 2 +- packages/palette_generator/CHANGELOG.md | 4 ++++ packages/palette_generator/example/pubspec.yaml | 4 ++-- packages/palette_generator/pubspec.yaml | 4 ++-- packages/path_provider/path_provider/CHANGELOG.md | 4 ++++ packages/path_provider/path_provider/example/pubspec.yaml | 4 ++-- .../path_provider/path_provider_foundation/CHANGELOG.md | 4 ++++ .../path_provider_foundation/example/pubspec.yaml | 4 ++-- .../path_provider/path_provider_foundation/pubspec.yaml | 4 ++-- packages/path_provider/path_provider_linux/CHANGELOG.md | 2 +- .../path_provider_linux/example/pubspec.yaml | 4 ++-- packages/path_provider/path_provider_linux/pubspec.yaml | 4 ++-- .../path_provider_platform_interface/CHANGELOG.md | 2 +- .../path_provider_platform_interface/pubspec.yaml | 4 ++-- packages/path_provider/path_provider_windows/CHANGELOG.md | 2 +- .../path_provider_windows/example/pubspec.yaml | 4 ++-- packages/path_provider/path_provider_windows/pubspec.yaml | 4 ++-- packages/pigeon/CHANGELOG.md | 4 ++++ packages/pigeon/example/app/pubspec.yaml | 2 +- .../alternate_language_test_plugin/example/pubspec.yaml | 2 +- .../alternate_language_test_plugin/pubspec.yaml | 4 ++-- .../platform_tests/shared_test_plugin_code/pubspec.yaml | 4 ++-- .../platform_tests/test_plugin/example/pubspec.yaml | 2 +- packages/pigeon/platform_tests/test_plugin/pubspec.yaml | 4 ++-- packages/pigeon/pubspec.yaml | 2 +- packages/plugin_platform_interface/CHANGELOG.md | 2 +- packages/plugin_platform_interface/pubspec.yaml | 2 +- .../pointer_interceptor/pointer_interceptor/CHANGELOG.md | 2 +- .../pointer_interceptor/example/pubspec.yaml | 4 ++-- .../pointer_interceptor/pointer_interceptor/pubspec.yaml | 4 ++-- .../pointer_interceptor_ios/CHANGELOG.md | 2 +- .../pointer_interceptor_ios/example/pubspec.yaml | 4 ++-- .../pointer_interceptor_ios/pubspec.yaml | 4 ++-- .../pointer_interceptor_platform_interface/CHANGELOG.md | 2 +- .../pointer_interceptor_platform_interface/pubspec.yaml | 4 ++-- packages/process/CHANGELOG.md | 4 ++++ packages/process/pubspec.yaml | 2 +- packages/quick_actions/quick_actions/CHANGELOG.md | 4 ++++ packages/quick_actions/quick_actions/example/pubspec.yaml | 4 ++-- packages/quick_actions/quick_actions/pubspec.yaml | 4 ++-- packages/quick_actions/quick_actions_ios/CHANGELOG.md | 4 ++++ .../quick_actions/quick_actions_ios/example/pubspec.yaml | 4 ++-- packages/quick_actions/quick_actions_ios/pubspec.yaml | 4 ++-- .../quick_actions_platform_interface/CHANGELOG.md | 4 ++++ .../quick_actions_platform_interface/pubspec.yaml | 4 ++-- packages/rfw/CHANGELOG.md | 4 ++++ packages/rfw/example/hello/pubspec.yaml | 4 ++-- packages/rfw/example/local/pubspec.yaml | 4 ++-- packages/rfw/example/remote/pubspec.yaml | 4 ++-- packages/rfw/example/wasm/pubspec.yaml | 4 ++-- packages/rfw/pubspec.yaml | 4 ++-- packages/rfw/test_coverage/pubspec.yaml | 2 +- .../shared_preferences_foundation/CHANGELOG.md | 4 ++++ .../shared_preferences_foundation/example/pubspec.yaml | 4 ++-- .../shared_preferences_foundation/pubspec.yaml | 4 ++-- .../shared_preferences_linux/CHANGELOG.md | 4 ++++ .../shared_preferences_linux/example/pubspec.yaml | 4 ++-- .../shared_preferences_linux/pubspec.yaml | 4 ++-- .../shared_preferences_platform_interface/CHANGELOG.md | 2 +- .../shared_preferences_platform_interface/pubspec.yaml | 4 ++-- .../shared_preferences_windows/CHANGELOG.md | 4 ++++ .../shared_preferences_windows/example/pubspec.yaml | 4 ++-- .../shared_preferences_windows/pubspec.yaml | 4 ++-- packages/standard_message_codec/CHANGELOG.md | 2 +- packages/standard_message_codec/example/pubspec.yaml | 2 +- packages/standard_message_codec/pubspec.yaml | 2 +- packages/two_dimensional_scrollables/CHANGELOG.md | 4 ++++ packages/two_dimensional_scrollables/example/pubspec.yaml | 4 ++-- packages/two_dimensional_scrollables/pubspec.yaml | 4 ++-- packages/url_launcher/url_launcher/CHANGELOG.md | 4 ++++ packages/url_launcher/url_launcher/example/pubspec.yaml | 4 ++-- packages/url_launcher/url_launcher/pubspec.yaml | 4 ++-- packages/url_launcher/url_launcher_ios/CHANGELOG.md | 4 ++++ .../url_launcher/url_launcher_ios/example/pubspec.yaml | 4 ++-- packages/url_launcher/url_launcher_ios/pubspec.yaml | 4 ++-- packages/url_launcher/url_launcher_linux/CHANGELOG.md | 4 ++++ .../url_launcher/url_launcher_linux/example/pubspec.yaml | 4 ++-- packages/url_launcher/url_launcher_linux/pubspec.yaml | 4 ++-- packages/url_launcher/url_launcher_macos/CHANGELOG.md | 4 ++++ .../url_launcher/url_launcher_macos/example/pubspec.yaml | 4 ++-- packages/url_launcher/url_launcher_macos/pubspec.yaml | 4 ++-- .../url_launcher_platform_interface/CHANGELOG.md | 2 +- .../url_launcher_platform_interface/pubspec.yaml | 4 ++-- packages/url_launcher/url_launcher_web/CHANGELOG.md | 4 ++++ .../url_launcher/url_launcher_web/example/pubspec.yaml | 4 ++-- packages/url_launcher/url_launcher_web/pubspec.yaml | 4 ++-- packages/url_launcher/url_launcher_windows/CHANGELOG.md | 4 ++++ .../url_launcher_windows/example/pubspec.yaml | 4 ++-- packages/url_launcher/url_launcher_windows/pubspec.yaml | 4 ++-- packages/video_player/video_player/CHANGELOG.md | 4 ++++ packages/video_player/video_player/example/pubspec.yaml | 4 ++-- packages/video_player/video_player/pubspec.yaml | 4 ++-- .../video_player/video_player_avfoundation/CHANGELOG.md | 4 ++++ .../video_player_avfoundation/example/pubspec.yaml | 4 ++-- .../video_player/video_player_avfoundation/pubspec.yaml | 4 ++-- .../video_player_platform_interface/CHANGELOG.md | 4 ++++ .../video_player_platform_interface/pubspec.yaml | 4 ++-- packages/web_benchmarks/CHANGELOG.md | 4 ++++ packages/web_benchmarks/pubspec.yaml | 4 ++-- packages/web_benchmarks/testing/test_app/pubspec.yaml | 2 +- packages/webview_flutter/webview_flutter/CHANGELOG.md | 4 ++++ .../webview_flutter/webview_flutter/example/pubspec.yaml | 4 ++-- .../webview_flutter_platform_interface/CHANGELOG.md | 2 +- .../webview_flutter_platform_interface/pubspec.yaml | 4 ++-- .../webview_flutter_wkwebview/CHANGELOG.md | 4 ++++ .../webview_flutter_wkwebview/example/pubspec.yaml | 4 ++-- packages/xdg_directories/CHANGELOG.md | 4 ++++ packages/xdg_directories/example/pubspec.yaml | 4 ++-- packages/xdg_directories/pubspec.yaml | 2 +- script/tool/lib/src/common/core.dart | 2 ++ third_party/packages/cupertino_icons/CHANGELOG.md | 2 +- third_party/packages/cupertino_icons/pubspec.yaml | 2 +- third_party/packages/path_parsing/CHANGELOG.md | 4 ++++ third_party/packages/path_parsing/example/pubspec.yaml | 2 +- third_party/packages/path_parsing/pubspec.yaml | 2 +- 237 files changed, 519 insertions(+), 317 deletions(-) diff --git a/.ci.yaml b/.ci.yaml index 0cc83481ae62..3310b3129aaf 100644 --- a/.ci.yaml +++ b/.ci.yaml @@ -292,10 +292,10 @@ targets: timeout: 30 properties: target_file: analyze_legacy.yaml - channel: "3.22.3" + channel: "3.24.5" env_variables: >- { - "CHANNEL": "3.22.3" + "CHANNEL": "3.24.5" } - name: Linux analyze_legacy N-2 @@ -303,10 +303,10 @@ targets: timeout: 30 properties: target_file: analyze_legacy.yaml - channel: "3.19.6" + channel: "3.22.3" env_variables: >- { - "CHANNEL": "3.19.6" + "CHANNEL": "3.22.3" } - name: Linux_android custom_package_tests master diff --git a/.ci/targets/repo_checks.yaml b/.ci/targets/repo_checks.yaml index 090548718e8a..7f7dbe1f249b 100644 --- a/.ci/targets/repo_checks.yaml +++ b/.ci/targets/repo_checks.yaml @@ -28,7 +28,7 @@ tasks: script: .ci/scripts/tool_runner.sh args: - "pubspec-check" - - "--min-min-flutter-version=3.19.0" + - "--min-min-flutter-version=3.22.0" - "--allow-dependencies=script/configs/allowed_unpinned_deps.yaml" - "--allow-pinned-dependencies=script/configs/allowed_pinned_deps.yaml" always: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b8b866e72f34..84bf40686db4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,7 +31,7 @@ jobs: # the change if it doesn't. run: | cd $HOME - git clone https://github.com/flutter/flutter.git --depth 1 -b 3.24.0 _flutter + git clone https://github.com/flutter/flutter.git --depth 1 -b 3.27.0 _flutter echo "$HOME/_flutter/bin" >> $GITHUB_PATH cd $GITHUB_WORKSPACE # Checks out a copy of the repo. diff --git a/packages/animations/CHANGELOG.md b/packages/animations/CHANGELOG.md index 76db6b8ed283..dcbed7e7cc05 100644 --- a/packages/animations/CHANGELOG.md +++ b/packages/animations/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 2.0.11 diff --git a/packages/animations/example/pubspec.yaml b/packages/animations/example/pubspec.yaml index 812702238da7..433d849800d5 100644 --- a/packages/animations/example/pubspec.yaml +++ b/packages/animations/example/pubspec.yaml @@ -6,8 +6,8 @@ publish_to: none version: 0.0.1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: animations: diff --git a/packages/animations/pubspec.yaml b/packages/animations/pubspec.yaml index bc208969964e..b697723d18e5 100644 --- a/packages/animations/pubspec.yaml +++ b/packages/animations/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.0.11 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index d018f4941993..f0de02ef0cd8 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 0.11.0+2 * Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. diff --git a/packages/camera/camera/example/pubspec.yaml b/packages/camera/camera/example/pubspec.yaml index 5dd02b696866..9f37495145e1 100644 --- a/packages/camera/camera/example/pubspec.yaml +++ b/packages/camera/camera/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the camera plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: camera: diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index 0b8ebb4a3b5c..fb4e49510968 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -7,8 +7,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.11.0+2 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/camera/camera_avfoundation/CHANGELOG.md b/packages/camera/camera_avfoundation/CHANGELOG.md index a1b18e61ed4c..34de3bf88e46 100644 --- a/packages/camera/camera_avfoundation/CHANGELOG.md +++ b/packages/camera/camera_avfoundation/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 0.9.17+5 * Adds ability to use any supported FPS and fixes crash when using unsupported FPS. diff --git a/packages/camera/camera_avfoundation/example/pubspec.yaml b/packages/camera/camera_avfoundation/example/pubspec.yaml index d855135a5c8f..9f82d7faf625 100644 --- a/packages/camera/camera_avfoundation/example/pubspec.yaml +++ b/packages/camera/camera_avfoundation/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the camera plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: camera_avfoundation: diff --git a/packages/camera/camera_avfoundation/pubspec.yaml b/packages/camera/camera_avfoundation/pubspec.yaml index 6ceb0b934f6e..8ba11828e97d 100644 --- a/packages/camera/camera_avfoundation/pubspec.yaml +++ b/packages/camera/camera_avfoundation/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.9.17+5 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/camera/camera_platform_interface/CHANGELOG.md b/packages/camera/camera_platform_interface/CHANGELOG.md index 4ae1a540978c..d5a1fe3d9343 100644 --- a/packages/camera/camera_platform_interface/CHANGELOG.md +++ b/packages/camera/camera_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 2.8.0 diff --git a/packages/camera/camera_platform_interface/pubspec.yaml b/packages/camera/camera_platform_interface/pubspec.yaml index 8ed6c9e70c61..647146d980be 100644 --- a/packages/camera/camera_platform_interface/pubspec.yaml +++ b/packages/camera/camera_platform_interface/pubspec.yaml @@ -7,8 +7,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.8.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: cross_file: ^0.3.1 diff --git a/packages/camera/camera_windows/CHANGELOG.md b/packages/camera/camera_windows/CHANGELOG.md index 8fe3c0dff2d7..1ff3ffe4186a 100644 --- a/packages/camera/camera_windows/CHANGELOG.md +++ b/packages/camera/camera_windows/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 0.2.6+1 * Fixes black bars on camera preview [#122966](https://github.com/flutter/flutter/issues/122966). diff --git a/packages/camera/camera_windows/example/pubspec.yaml b/packages/camera/camera_windows/example/pubspec.yaml index 201cf9df581e..7eabccf3d652 100644 --- a/packages/camera/camera_windows/example/pubspec.yaml +++ b/packages/camera/camera_windows/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the camera_windows plugin. publish_to: 'none' environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: camera_platform_interface: ^2.6.0 diff --git a/packages/camera/camera_windows/pubspec.yaml b/packages/camera/camera_windows/pubspec.yaml index a2a9efb321f8..0db033af0ac0 100644 --- a/packages/camera/camera_windows/pubspec.yaml +++ b/packages/camera/camera_windows/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.2.6+1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/cross_file/CHANGELOG.md b/packages/cross_file/CHANGELOG.md index 016abd18b62a..377b84f0fa32 100644 --- a/packages/cross_file/CHANGELOG.md +++ b/packages/cross_file/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 0.3.4+2 diff --git a/packages/cross_file/example/pubspec.yaml b/packages/cross_file/example/pubspec.yaml index 5e12d44dc13f..2724404b75f3 100644 --- a/packages/cross_file/example/pubspec.yaml +++ b/packages/cross_file/example/pubspec.yaml @@ -3,7 +3,7 @@ description: Demonstrates how to use cross files. publish_to: none environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dependencies: cross_file: diff --git a/packages/cross_file/pubspec.yaml b/packages/cross_file/pubspec.yaml index 0de3c0cfa24a..2b56f8b51a42 100644 --- a/packages/cross_file/pubspec.yaml +++ b/packages/cross_file/pubspec.yaml @@ -5,7 +5,7 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.3.4+2 environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dependencies: meta: ^1.3.0 diff --git a/packages/css_colors/CHANGELOG.md b/packages/css_colors/CHANGELOG.md index 5f464a2c0730..04926b3de95e 100644 --- a/packages/css_colors/CHANGELOG.md +++ b/packages/css_colors/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 1.1.5 diff --git a/packages/css_colors/pubspec.yaml b/packages/css_colors/pubspec.yaml index a8e646c95b8e..368bd89b9542 100644 --- a/packages/css_colors/pubspec.yaml +++ b/packages/css_colors/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 1.1.5 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/extension_google_sign_in_as_googleapis_auth/CHANGELOG.md b/packages/extension_google_sign_in_as_googleapis_auth/CHANGELOG.md index 50c7ff16dc9d..c5dc18b149b8 100644 --- a/packages/extension_google_sign_in_as_googleapis_auth/CHANGELOG.md +++ b/packages/extension_google_sign_in_as_googleapis_auth/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 2.0.12 diff --git a/packages/extension_google_sign_in_as_googleapis_auth/example/pubspec.yaml b/packages/extension_google_sign_in_as_googleapis_auth/example/pubspec.yaml index c8de67d9e71b..2cae99f0f900 100644 --- a/packages/extension_google_sign_in_as_googleapis_auth/example/pubspec.yaml +++ b/packages/extension_google_sign_in_as_googleapis_auth/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Example of Google Sign-In plugin and googleapis. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: extension_google_sign_in_as_googleapis_auth: diff --git a/packages/extension_google_sign_in_as_googleapis_auth/pubspec.yaml b/packages/extension_google_sign_in_as_googleapis_auth/pubspec.yaml index 6e03593de6d1..3a75e11a010c 100644 --- a/packages/extension_google_sign_in_as_googleapis_auth/pubspec.yaml +++ b/packages/extension_google_sign_in_as_googleapis_auth/pubspec.yaml @@ -11,8 +11,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.0.12 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/file_selector/file_selector/CHANGELOG.md b/packages/file_selector/file_selector/CHANGELOG.md index a4a62d47790a..565150b325ce 100644 --- a/packages/file_selector/file_selector/CHANGELOG.md +++ b/packages/file_selector/file_selector/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 1.0.3 diff --git a/packages/file_selector/file_selector/example/pubspec.yaml b/packages/file_selector/file_selector/example/pubspec.yaml index 6cf19c83de6c..5dcc8c0b3609 100644 --- a/packages/file_selector/file_selector/example/pubspec.yaml +++ b/packages/file_selector/file_selector/example/pubspec.yaml @@ -5,8 +5,8 @@ publish_to: none version: 1.0.0+1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: file_selector: diff --git a/packages/file_selector/file_selector/pubspec.yaml b/packages/file_selector/file_selector/pubspec.yaml index 9825bd4af478..31f2ea5310bc 100644 --- a/packages/file_selector/file_selector/pubspec.yaml +++ b/packages/file_selector/file_selector/pubspec.yaml @@ -6,8 +6,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 1.0.3 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/file_selector/file_selector_ios/CHANGELOG.md b/packages/file_selector/file_selector_ios/CHANGELOG.md index ea488f88a0b0..c41fcf2ea8d9 100644 --- a/packages/file_selector/file_selector_ios/CHANGELOG.md +++ b/packages/file_selector/file_selector_ios/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 0.5.3+1 * Updates Pigeon for non-nullable collection type support. diff --git a/packages/file_selector/file_selector_ios/example/pubspec.yaml b/packages/file_selector/file_selector_ios/example/pubspec.yaml index b4fd81c7de2a..c14f51da9e31 100644 --- a/packages/file_selector/file_selector_ios/example/pubspec.yaml +++ b/packages/file_selector/file_selector_ios/example/pubspec.yaml @@ -4,8 +4,8 @@ publish_to: 'none' version: 1.0.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: # The following adds the Cupertino Icons font to your application. diff --git a/packages/file_selector/file_selector_ios/pubspec.yaml b/packages/file_selector/file_selector_ios/pubspec.yaml index d86a09d9d7fd..d968e9580f25 100644 --- a/packages/file_selector/file_selector_ios/pubspec.yaml +++ b/packages/file_selector/file_selector_ios/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.5.3+1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/file_selector/file_selector_linux/CHANGELOG.md b/packages/file_selector/file_selector_linux/CHANGELOG.md index 3bed8134b193..dc3da9d55faa 100644 --- a/packages/file_selector/file_selector_linux/CHANGELOG.md +++ b/packages/file_selector/file_selector_linux/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 0.9.3+2 * Updates Pigeon to resolve a compilation failure with some versions of glib. diff --git a/packages/file_selector/file_selector_linux/example/pubspec.yaml b/packages/file_selector/file_selector_linux/example/pubspec.yaml index d29d3dac64c5..b54dd9953df8 100644 --- a/packages/file_selector/file_selector_linux/example/pubspec.yaml +++ b/packages/file_selector/file_selector_linux/example/pubspec.yaml @@ -4,8 +4,8 @@ publish_to: 'none' version: 1.0.0+1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: file_selector_linux: diff --git a/packages/file_selector/file_selector_linux/pubspec.yaml b/packages/file_selector/file_selector_linux/pubspec.yaml index 7284b0106bda..4f3f17626446 100644 --- a/packages/file_selector/file_selector_linux/pubspec.yaml +++ b/packages/file_selector/file_selector_linux/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.9.3+2 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/file_selector/file_selector_macos/CHANGELOG.md b/packages/file_selector/file_selector_macos/CHANGELOG.md index c2c48c5f8485..62d1616ed2f7 100644 --- a/packages/file_selector/file_selector_macos/CHANGELOG.md +++ b/packages/file_selector/file_selector_macos/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 0.9.4+2 * Updates Pigeon for non-nullable collection type support. diff --git a/packages/file_selector/file_selector_macos/example/pubspec.yaml b/packages/file_selector/file_selector_macos/example/pubspec.yaml index 70e64c7a83b9..734fa9c03620 100644 --- a/packages/file_selector/file_selector_macos/example/pubspec.yaml +++ b/packages/file_selector/file_selector_macos/example/pubspec.yaml @@ -4,8 +4,8 @@ publish_to: 'none' version: 1.0.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: file_selector_macos: diff --git a/packages/file_selector/file_selector_macos/pubspec.yaml b/packages/file_selector/file_selector_macos/pubspec.yaml index 580eca085ee7..7afb9ab32f82 100644 --- a/packages/file_selector/file_selector_macos/pubspec.yaml +++ b/packages/file_selector/file_selector_macos/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.9.4+2 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/file_selector/file_selector_platform_interface/CHANGELOG.md b/packages/file_selector/file_selector_platform_interface/CHANGELOG.md index 0f90a92eda3c..8af2e407da17 100644 --- a/packages/file_selector/file_selector_platform_interface/CHANGELOG.md +++ b/packages/file_selector/file_selector_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 2.6.2 diff --git a/packages/file_selector/file_selector_platform_interface/pubspec.yaml b/packages/file_selector/file_selector_platform_interface/pubspec.yaml index e34e752c31da..9d7cae498903 100644 --- a/packages/file_selector/file_selector_platform_interface/pubspec.yaml +++ b/packages/file_selector/file_selector_platform_interface/pubspec.yaml @@ -7,8 +7,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.6.2 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: cross_file: ^0.3.0 diff --git a/packages/file_selector/file_selector_windows/CHANGELOG.md b/packages/file_selector/file_selector_windows/CHANGELOG.md index 77b5c11c4754..a895174e5e84 100644 --- a/packages/file_selector/file_selector_windows/CHANGELOG.md +++ b/packages/file_selector/file_selector_windows/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 0.9.3+3 * Updates Pigeon for non-nullable collection type support. diff --git a/packages/file_selector/file_selector_windows/example/pubspec.yaml b/packages/file_selector/file_selector_windows/example/pubspec.yaml index 6d0a226b5128..2382adc542b2 100644 --- a/packages/file_selector/file_selector_windows/example/pubspec.yaml +++ b/packages/file_selector/file_selector_windows/example/pubspec.yaml @@ -4,8 +4,8 @@ publish_to: 'none' version: 1.0.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: file_selector_platform_interface: ^2.6.0 diff --git a/packages/file_selector/file_selector_windows/pubspec.yaml b/packages/file_selector/file_selector_windows/pubspec.yaml index f2631787d6fe..4508b9d7cb16 100644 --- a/packages/file_selector/file_selector_windows/pubspec.yaml +++ b/packages/file_selector/file_selector_windows/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.9.3+3 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/flutter_image/CHANGELOG.md b/packages/flutter_image/CHANGELOG.md index 89538cfc0dde..225f9ce71ffc 100644 --- a/packages/flutter_image/CHANGELOG.md +++ b/packages/flutter_image/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 4.1.11 diff --git a/packages/flutter_image/example/pubspec.yaml b/packages/flutter_image/example/pubspec.yaml index a7a03cb89c89..70ef7e73bd41 100644 --- a/packages/flutter_image/example/pubspec.yaml +++ b/packages/flutter_image/example/pubspec.yaml @@ -6,8 +6,8 @@ publish_to: "none" version: 1.0.0+1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: cupertino_icons: ^1.0.2 diff --git a/packages/flutter_image/pubspec.yaml b/packages/flutter_image/pubspec.yaml index d721eb89c37d..458d2506a695 100644 --- a/packages/flutter_image/pubspec.yaml +++ b/packages/flutter_image/pubspec.yaml @@ -6,8 +6,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 4.1.11 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/flutter_lints/CHANGELOG.md b/packages/flutter_lints/CHANGELOG.md index a65e7e221228..2724963c3cd9 100644 --- a/packages/flutter_lints/CHANGELOG.md +++ b/packages/flutter_lints/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 5.0.0 * Updates `package:lints` dependency to version 5.0.0, with the following changes: diff --git a/packages/flutter_lints/example/pubspec.yaml b/packages/flutter_lints/example/pubspec.yaml index 472307f440dd..08ee423dbd7d 100644 --- a/packages/flutter_lints/example/pubspec.yaml +++ b/packages/flutter_lints/example/pubspec.yaml @@ -4,7 +4,7 @@ description: A project that showcases how to enable the recommended lints for Fl publish_to: none environment: - sdk: ^3.3.0 + sdk: ^3.4.0 # Add the latest version of `package:flutter_lints` as a dev_dependency. The # lint set provided by this package is activated in the `analysis_options.yaml` diff --git a/packages/flutter_markdown/CHANGELOG.md b/packages/flutter_markdown/CHANGELOG.md index 0c43f4fa88c9..30e4a3804970 100644 --- a/packages/flutter_markdown/CHANGELOG.md +++ b/packages/flutter_markdown/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 0.7.4+3 * Passes a default error builder to image widgets. diff --git a/packages/flutter_markdown/example/pubspec.yaml b/packages/flutter_markdown/example/pubspec.yaml index 390eb0d27f26..f6c1960aa816 100644 --- a/packages/flutter_markdown/example/pubspec.yaml +++ b/packages/flutter_markdown/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the flutter_markdown package. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/flutter_markdown/pubspec.yaml b/packages/flutter_markdown/pubspec.yaml index b78c0dce3ddf..3c8f7b6ffff7 100644 --- a/packages/flutter_markdown/pubspec.yaml +++ b/packages/flutter_markdown/pubspec.yaml @@ -7,8 +7,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.7.4+3 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/flutter_migrate/CHANGELOG.md b/packages/flutter_migrate/CHANGELOG.md index 2d132e53fc13..1cbeac241051 100644 --- a/packages/flutter_migrate/CHANGELOG.md +++ b/packages/flutter_migrate/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 0.0.1+4 * Adds `missing_code_block_language_in_doc_comment` lint. diff --git a/packages/flutter_migrate/pubspec.yaml b/packages/flutter_migrate/pubspec.yaml index f1aafdf48cf0..caa3d9403fe5 100644 --- a/packages/flutter_migrate/pubspec.yaml +++ b/packages/flutter_migrate/pubspec.yaml @@ -6,7 +6,7 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ publish_to: none environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dependencies: args: ^2.3.1 diff --git a/packages/flutter_template_images/CHANGELOG.md b/packages/flutter_template_images/CHANGELOG.md index 6cf915b7ff90..efc23cd17b13 100644 --- a/packages/flutter_template_images/CHANGELOG.md +++ b/packages/flutter_template_images/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 4.2.1 diff --git a/packages/flutter_template_images/pubspec.yaml b/packages/flutter_template_images/pubspec.yaml index 411d285db25d..737ae29b76a3 100644 --- a/packages/flutter_template_images/pubspec.yaml +++ b/packages/flutter_template_images/pubspec.yaml @@ -5,7 +5,7 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 4.2.1 environment: - sdk: ^3.3.0 + sdk: ^3.4.0 topics: - assets diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md index e2f174dbef07..9327b97442bb 100644 --- a/packages/go_router/CHANGELOG.md +++ b/packages/go_router/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 14.6.2 - Replaces deprecated collection method usage. diff --git a/packages/go_router/example/pubspec.yaml b/packages/go_router/example/pubspec.yaml index 40a65efc4311..5bcef78c499d 100644 --- a/packages/go_router/example/pubspec.yaml +++ b/packages/go_router/example/pubspec.yaml @@ -4,8 +4,8 @@ version: 3.0.1 publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: adaptive_navigation: ^0.0.4 diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml index a5e2e26b3cf6..1113c4cbea93 100644 --- a/packages/go_router/pubspec.yaml +++ b/packages/go_router/pubspec.yaml @@ -6,8 +6,8 @@ repository: https://github.com/flutter/packages/tree/main/packages/go_router issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router%22 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: collection: ^1.15.0 diff --git a/packages/go_router_builder/CHANGELOG.md b/packages/go_router_builder/CHANGELOG.md index 9367f706ae68..260f6e2d10e6 100644 --- a/packages/go_router_builder/CHANGELOG.md +++ b/packages/go_router_builder/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 2.7.1 diff --git a/packages/go_router_builder/example/pubspec.yaml b/packages/go_router_builder/example/pubspec.yaml index a4d0efc279db..46d64d191886 100644 --- a/packages/go_router_builder/example/pubspec.yaml +++ b/packages/go_router_builder/example/pubspec.yaml @@ -3,7 +3,7 @@ description: go_router_builder examples publish_to: none environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dependencies: collection: ^1.15.0 diff --git a/packages/go_router_builder/pubspec.yaml b/packages/go_router_builder/pubspec.yaml index 6686ec3ba126..8de1e3cc10e8 100644 --- a/packages/go_router_builder/pubspec.yaml +++ b/packages/go_router_builder/pubspec.yaml @@ -7,8 +7,8 @@ repository: https://github.com/flutter/packages/tree/main/packages/go_router_bui issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router_builder%22 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: analyzer: ">=5.2.0 <7.0.0" diff --git a/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md index 75614efbf0db..ef5c348d68b7 100644 --- a/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 2.10.0 * Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. diff --git a/packages/google_maps_flutter/google_maps_flutter/example/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter/example/pubspec.yaml index 3326cbae3e5e..0a949e262bbe 100644 --- a/packages/google_maps_flutter/google_maps_flutter/example/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the google_maps_flutter plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: cupertino_icons: ^1.0.5 diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md index a42fa3d3076e..b09f2f375b20 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 2.13.2 * Updates most objects passed from Dart to native to use typed data. diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/pubspec.yaml index a130acf4b348..f0a241192822 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the google_maps_flutter plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: cupertino_icons: ^1.0.5 diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios15/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios15/pubspec.yaml index a130acf4b348..f0a241192822 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios15/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios15/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the google_maps_flutter plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: cupertino_icons: ^1.0.5 diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/pubspec.yaml index 47faec4a495f..9e6466288a92 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/pubspec.yaml @@ -3,8 +3,8 @@ description: Shared Dart code for the example apps. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: cupertino_icons: ^1.0.5 diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_ios/pubspec.yaml index b90fc561e983..2020ec8940ef 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_ios/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.13.2 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md index 49c12ebbbdab..8638e83c6ce3 100644 --- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 2.9.5 * Converts `BitmapDescriptor` to typesafe structures. diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml index 67e6a64f1c0f..1ffc34717c91 100644 --- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml @@ -7,8 +7,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.9.5 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: collection: ^1.15.0 diff --git a/packages/google_sign_in/google_sign_in/CHANGELOG.md b/packages/google_sign_in/google_sign_in/CHANGELOG.md index 24564442c8f9..eee5a932cf69 100644 --- a/packages/google_sign_in/google_sign_in/CHANGELOG.md +++ b/packages/google_sign_in/google_sign_in/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 6.2.2 * Adds `missing_code_block_language_in_doc_comment` lint. diff --git a/packages/google_sign_in/google_sign_in/example/pubspec.yaml b/packages/google_sign_in/google_sign_in/example/pubspec.yaml index e4fe3eae18f2..5335068734a8 100644 --- a/packages/google_sign_in/google_sign_in/example/pubspec.yaml +++ b/packages/google_sign_in/google_sign_in/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Example of Google Sign-In plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/google_sign_in/google_sign_in/pubspec.yaml b/packages/google_sign_in/google_sign_in/pubspec.yaml index c19b4c2b0974..ee1a1e0b61d6 100644 --- a/packages/google_sign_in/google_sign_in/pubspec.yaml +++ b/packages/google_sign_in/google_sign_in/pubspec.yaml @@ -6,8 +6,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 6.2.2 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/google_sign_in/google_sign_in_ios/CHANGELOG.md b/packages/google_sign_in/google_sign_in_ios/CHANGELOG.md index d6ab31e98763..f7b0e5617160 100644 --- a/packages/google_sign_in/google_sign_in_ios/CHANGELOG.md +++ b/packages/google_sign_in/google_sign_in_ios/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 5.7.8 * Updates Pigeon for non-nullable collection type support. diff --git a/packages/google_sign_in/google_sign_in_ios/example/pubspec.yaml b/packages/google_sign_in/google_sign_in_ios/example/pubspec.yaml index 7e9558b3d73a..03c1172bde92 100644 --- a/packages/google_sign_in/google_sign_in_ios/example/pubspec.yaml +++ b/packages/google_sign_in/google_sign_in_ios/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Example of Google Sign-In plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/google_sign_in/google_sign_in_ios/pubspec.yaml b/packages/google_sign_in/google_sign_in_ios/pubspec.yaml index b4d782f97a98..8b64480c6622 100644 --- a/packages/google_sign_in/google_sign_in_ios/pubspec.yaml +++ b/packages/google_sign_in/google_sign_in_ios/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 5.7.8 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/google_sign_in/google_sign_in_platform_interface/CHANGELOG.md b/packages/google_sign_in/google_sign_in_platform_interface/CHANGELOG.md index 09c84c72eb15..fda470243542 100644 --- a/packages/google_sign_in/google_sign_in_platform_interface/CHANGELOG.md +++ b/packages/google_sign_in/google_sign_in_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 2.4.5 diff --git a/packages/google_sign_in/google_sign_in_platform_interface/pubspec.yaml b/packages/google_sign_in/google_sign_in_platform_interface/pubspec.yaml index 7826912ca88d..2581773c69df 100644 --- a/packages/google_sign_in/google_sign_in_platform_interface/pubspec.yaml +++ b/packages/google_sign_in/google_sign_in_platform_interface/pubspec.yaml @@ -7,8 +7,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.4.5 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md index 7c3db8fd4da4..52e161969d1f 100644 --- a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md +++ b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 0.12.4+3 * Fixes callback types for `TokenClientConfig`. diff --git a/packages/google_sign_in/google_sign_in_web/example/pubspec.yaml b/packages/google_sign_in/google_sign_in_web/example/pubspec.yaml index 756f725fe74d..81b6dd8bad3f 100644 --- a/packages/google_sign_in/google_sign_in_web/example/pubspec.yaml +++ b/packages/google_sign_in/google_sign_in_web/example/pubspec.yaml @@ -2,8 +2,8 @@ name: google_sign_in_web_integration_tests publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: cupertino_icons: ^1.0.2 diff --git a/packages/google_sign_in/google_sign_in_web/pubspec.yaml b/packages/google_sign_in/google_sign_in_web/pubspec.yaml index 85aa2ba45a09..ef52f4f3e41c 100644 --- a/packages/google_sign_in/google_sign_in_web/pubspec.yaml +++ b/packages/google_sign_in/google_sign_in_web/pubspec.yaml @@ -6,8 +6,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.12.4+3 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/image_picker/image_picker/CHANGELOG.md b/packages/image_picker/image_picker/CHANGELOG.md index 29fb408f8b45..ee08d0510f3c 100644 --- a/packages/image_picker/image_picker/CHANGELOG.md +++ b/packages/image_picker/image_picker/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 1.1.2 * Adds comment for the limit parameter. diff --git a/packages/image_picker/image_picker/example/pubspec.yaml b/packages/image_picker/image_picker/example/pubspec.yaml index 12e6350a9523..d064fb0f7e87 100644 --- a/packages/image_picker/image_picker/example/pubspec.yaml +++ b/packages/image_picker/image_picker/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the image_picker plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/image_picker/image_picker/pubspec.yaml b/packages/image_picker/image_picker/pubspec.yaml index 6c5676a60e0d..d2f49724c883 100755 --- a/packages/image_picker/image_picker/pubspec.yaml +++ b/packages/image_picker/image_picker/pubspec.yaml @@ -6,8 +6,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 1.1.2 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/image_picker/image_picker_ios/CHANGELOG.md b/packages/image_picker/image_picker_ios/CHANGELOG.md index f31aa5c36662..8fd9f953c285 100644 --- a/packages/image_picker/image_picker_ios/CHANGELOG.md +++ b/packages/image_picker/image_picker_ios/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 0.8.12+1 * Updates Pigeon for non-nullable collection type support. diff --git a/packages/image_picker/image_picker_ios/example/pubspec.yaml b/packages/image_picker/image_picker_ios/example/pubspec.yaml index dbfe54d4420f..bcb238256489 100755 --- a/packages/image_picker/image_picker_ios/example/pubspec.yaml +++ b/packages/image_picker/image_picker_ios/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the image_picker plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/image_picker/image_picker_ios/pubspec.yaml b/packages/image_picker/image_picker_ios/pubspec.yaml index a1f752f33bce..694a7a8cf3bd 100755 --- a/packages/image_picker/image_picker_ios/pubspec.yaml +++ b/packages/image_picker/image_picker_ios/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.8.12+1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/image_picker/image_picker_linux/CHANGELOG.md b/packages/image_picker/image_picker_linux/CHANGELOG.md index 50d3dd738917..1fa9bff8eba9 100644 --- a/packages/image_picker/image_picker_linux/CHANGELOG.md +++ b/packages/image_picker/image_picker_linux/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 0.2.1+1 diff --git a/packages/image_picker/image_picker_linux/example/pubspec.yaml b/packages/image_picker/image_picker_linux/example/pubspec.yaml index 5db5fb085f8c..30f2d208a69e 100644 --- a/packages/image_picker/image_picker_linux/example/pubspec.yaml +++ b/packages/image_picker/image_picker_linux/example/pubspec.yaml @@ -4,8 +4,8 @@ publish_to: 'none' version: 1.0.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/image_picker/image_picker_linux/pubspec.yaml b/packages/image_picker/image_picker_linux/pubspec.yaml index 8e44fac8d48a..860d59846bf8 100644 --- a/packages/image_picker/image_picker_linux/pubspec.yaml +++ b/packages/image_picker/image_picker_linux/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.2.1+1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/image_picker/image_picker_macos/CHANGELOG.md b/packages/image_picker/image_picker_macos/CHANGELOG.md index 6012fff8dbcd..f1b3bd3f1597 100644 --- a/packages/image_picker/image_picker_macos/CHANGELOG.md +++ b/packages/image_picker/image_picker_macos/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 0.2.1+1 diff --git a/packages/image_picker/image_picker_macos/example/pubspec.yaml b/packages/image_picker/image_picker_macos/example/pubspec.yaml index ab0d82bbc305..66435a80756b 100644 --- a/packages/image_picker/image_picker_macos/example/pubspec.yaml +++ b/packages/image_picker/image_picker_macos/example/pubspec.yaml @@ -4,8 +4,8 @@ publish_to: 'none' version: 1.0.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/image_picker/image_picker_macos/pubspec.yaml b/packages/image_picker/image_picker_macos/pubspec.yaml index 3b11740e8d86..d5f7181c903a 100644 --- a/packages/image_picker/image_picker_macos/pubspec.yaml +++ b/packages/image_picker/image_picker_macos/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.2.1+1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/image_picker/image_picker_platform_interface/CHANGELOG.md b/packages/image_picker/image_picker_platform_interface/CHANGELOG.md index 28a9d4b2e1a8..efbec138c57a 100644 --- a/packages/image_picker/image_picker_platform_interface/CHANGELOG.md +++ b/packages/image_picker/image_picker_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 2.10.0 * Adds limit parameter to `MediaOptions` and `MultiImagePickerOptions`. diff --git a/packages/image_picker/image_picker_platform_interface/pubspec.yaml b/packages/image_picker/image_picker_platform_interface/pubspec.yaml index 9af992c7c7bf..3f56e0e394d8 100644 --- a/packages/image_picker/image_picker_platform_interface/pubspec.yaml +++ b/packages/image_picker/image_picker_platform_interface/pubspec.yaml @@ -7,8 +7,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.10.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: cross_file: ^0.3.1+1 diff --git a/packages/image_picker/image_picker_windows/CHANGELOG.md b/packages/image_picker/image_picker_windows/CHANGELOG.md index 8195bb8a66af..1f41748ce99c 100644 --- a/packages/image_picker/image_picker_windows/CHANGELOG.md +++ b/packages/image_picker/image_picker_windows/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 0.2.1+1 diff --git a/packages/image_picker/image_picker_windows/example/pubspec.yaml b/packages/image_picker/image_picker_windows/example/pubspec.yaml index 744a9e61ba0f..204177a5a9a5 100644 --- a/packages/image_picker/image_picker_windows/example/pubspec.yaml +++ b/packages/image_picker/image_picker_windows/example/pubspec.yaml @@ -4,8 +4,8 @@ publish_to: 'none' version: 1.0.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/image_picker/image_picker_windows/pubspec.yaml b/packages/image_picker/image_picker_windows/pubspec.yaml index 51d9a94ee6e4..73e2c59478c0 100644 --- a/packages/image_picker/image_picker_windows/pubspec.yaml +++ b/packages/image_picker/image_picker_windows/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.2.1+1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/in_app_purchase/in_app_purchase/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase/CHANGELOG.md index d4a2e5ab131d..385b79f69dcf 100644 --- a/packages/in_app_purchase/in_app_purchase/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 3.2.0 diff --git a/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml b/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml index c9c79cf63bc4..8423035ea9df 100644 --- a/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the in_app_purchase plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/in_app_purchase/in_app_purchase/pubspec.yaml b/packages/in_app_purchase/in_app_purchase/pubspec.yaml index c5ff3bf3b588..409bfafffcdd 100644 --- a/packages/in_app_purchase/in_app_purchase/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 3.2.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/in_app_purchase/in_app_purchase_platform_interface/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_platform_interface/CHANGELOG.md index d8fef6189343..c10788bd48ba 100644 --- a/packages/in_app_purchase/in_app_purchase_platform_interface/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 1.4.0 diff --git a/packages/in_app_purchase/in_app_purchase_platform_interface/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_platform_interface/pubspec.yaml index 9de0b0133408..29760d63412b 100644 --- a/packages/in_app_purchase/in_app_purchase_platform_interface/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase_platform_interface/pubspec.yaml @@ -7,8 +7,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 1.4.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md index 181db40db5e6..225bcc0c1ddb 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 0.3.20+2 * Fixes price not being displayed correctly. diff --git a/packages/in_app_purchase/in_app_purchase_storekit/example/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_storekit/example/pubspec.yaml index a59dafe8df95..40534c1c6c0f 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/example/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase_storekit/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the in_app_purchase_storekit plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml index e7ecbc0ebc1b..dc4444926bb4 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.3.20+2 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/ios_platform_images/CHANGELOG.md b/packages/ios_platform_images/CHANGELOG.md index 2dda63366d01..5a1f5490b9e7 100644 --- a/packages/ios_platform_images/CHANGELOG.md +++ b/packages/ios_platform_images/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 0.2.4+1 * Updates to Pigeon v22. diff --git a/packages/ios_platform_images/example/pubspec.yaml b/packages/ios_platform_images/example/pubspec.yaml index 65fa44b71154..612017fbd7b9 100644 --- a/packages/ios_platform_images/example/pubspec.yaml +++ b/packages/ios_platform_images/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the ios_platform_images plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: cupertino_icons: ^1.0.2 diff --git a/packages/ios_platform_images/pubspec.yaml b/packages/ios_platform_images/pubspec.yaml index dc5925b42f7d..2e40b7298aee 100644 --- a/packages/ios_platform_images/pubspec.yaml +++ b/packages/ios_platform_images/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.2.4+1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/local_auth/local_auth/CHANGELOG.md b/packages/local_auth/local_auth/CHANGELOG.md index a830dbc1cd6f..262015eb5e91 100644 --- a/packages/local_auth/local_auth/CHANGELOG.md +++ b/packages/local_auth/local_auth/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 2.3.0 diff --git a/packages/local_auth/local_auth/example/pubspec.yaml b/packages/local_auth/local_auth/example/pubspec.yaml index 8bcf50db130d..9b7b87fb44a3 100644 --- a/packages/local_auth/local_auth/example/pubspec.yaml +++ b/packages/local_auth/local_auth/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the local_auth plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/local_auth/local_auth/pubspec.yaml b/packages/local_auth/local_auth/pubspec.yaml index 0ebc00c4d3d4..e81560670869 100644 --- a/packages/local_auth/local_auth/pubspec.yaml +++ b/packages/local_auth/local_auth/pubspec.yaml @@ -6,8 +6,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.3.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/local_auth/local_auth_darwin/CHANGELOG.md b/packages/local_auth/local_auth_darwin/CHANGELOG.md index 3caab70bf454..c5fcf90d34a0 100644 --- a/packages/local_auth/local_auth_darwin/CHANGELOG.md +++ b/packages/local_auth/local_auth_darwin/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 1.4.2 * Adds compatibility with `intl` 0.20.0. diff --git a/packages/local_auth/local_auth_darwin/example/pubspec.yaml b/packages/local_auth/local_auth_darwin/example/pubspec.yaml index ab0ca6e62cce..4f204a5b9f82 100644 --- a/packages/local_auth/local_auth_darwin/example/pubspec.yaml +++ b/packages/local_auth/local_auth_darwin/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the local_auth_darwin plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/local_auth/local_auth_darwin/pubspec.yaml b/packages/local_auth/local_auth_darwin/pubspec.yaml index 4ee718f645cf..8aff58fe3698 100644 --- a/packages/local_auth/local_auth_darwin/pubspec.yaml +++ b/packages/local_auth/local_auth_darwin/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 1.4.2 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/local_auth/local_auth_platform_interface/CHANGELOG.md b/packages/local_auth/local_auth_platform_interface/CHANGELOG.md index 30dd66f1c3d1..d0f416c9f277 100644 --- a/packages/local_auth/local_auth_platform_interface/CHANGELOG.md +++ b/packages/local_auth/local_auth_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 1.0.10 diff --git a/packages/local_auth/local_auth_platform_interface/pubspec.yaml b/packages/local_auth/local_auth_platform_interface/pubspec.yaml index 471978598642..62774c28fe68 100644 --- a/packages/local_auth/local_auth_platform_interface/pubspec.yaml +++ b/packages/local_auth/local_auth_platform_interface/pubspec.yaml @@ -7,8 +7,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 1.0.10 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/local_auth/local_auth_windows/CHANGELOG.md b/packages/local_auth/local_auth_windows/CHANGELOG.md index d8654c0a2e79..d9ec70257e69 100644 --- a/packages/local_auth/local_auth_windows/CHANGELOG.md +++ b/packages/local_auth/local_auth_windows/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 1.0.11 diff --git a/packages/local_auth/local_auth_windows/example/pubspec.yaml b/packages/local_auth/local_auth_windows/example/pubspec.yaml index e953214f9853..9bdd40ae5a3c 100644 --- a/packages/local_auth/local_auth_windows/example/pubspec.yaml +++ b/packages/local_auth/local_auth_windows/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the local_auth_windows plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/local_auth/local_auth_windows/pubspec.yaml b/packages/local_auth/local_auth_windows/pubspec.yaml index 1919a989f0c4..8546c20951aa 100644 --- a/packages/local_auth/local_auth_windows/pubspec.yaml +++ b/packages/local_auth/local_auth_windows/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 1.0.11 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/metrics_center/CHANGELOG.md b/packages/metrics_center/CHANGELOG.md index 904f9775a932..703cfadff97d 100644 --- a/packages/metrics_center/CHANGELOG.md +++ b/packages/metrics_center/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. * Update dependency `http: ^1.0.0` ## 1.0.13 diff --git a/packages/metrics_center/pubspec.yaml b/packages/metrics_center/pubspec.yaml index a1ef1bebcf93..fc89d6ce4125 100644 --- a/packages/metrics_center/pubspec.yaml +++ b/packages/metrics_center/pubspec.yaml @@ -6,7 +6,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/metrics_cente issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+metrics_center%22 environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dependencies: _discoveryapis_commons: ^1.0.0 diff --git a/packages/multicast_dns/CHANGELOG.md b/packages/multicast_dns/CHANGELOG.md index b6956e0acbc4..4b23be31ce2d 100644 --- a/packages/multicast_dns/CHANGELOG.md +++ b/packages/multicast_dns/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 0.3.2+7 diff --git a/packages/multicast_dns/pubspec.yaml b/packages/multicast_dns/pubspec.yaml index 8683b680c98a..6f0f3052cc0e 100644 --- a/packages/multicast_dns/pubspec.yaml +++ b/packages/multicast_dns/pubspec.yaml @@ -5,7 +5,7 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.3.2+7 environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dependencies: meta: ^1.3.0 diff --git a/packages/palette_generator/CHANGELOG.md b/packages/palette_generator/CHANGELOG.md index 73b2ee0f5a47..a1f7ccf282ab 100644 --- a/packages/palette_generator/CHANGELOG.md +++ b/packages/palette_generator/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 0.3.3+5 * Updates README to link to the published example. diff --git a/packages/palette_generator/example/pubspec.yaml b/packages/palette_generator/example/pubspec.yaml index b0d61af8345c..8f1a28f036bf 100644 --- a/packages/palette_generator/example/pubspec.yaml +++ b/packages/palette_generator/example/pubspec.yaml @@ -4,8 +4,8 @@ publish_to: none version: 0.1.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/palette_generator/pubspec.yaml b/packages/palette_generator/pubspec.yaml index ed67a31c72c9..e43844311d9b 100644 --- a/packages/palette_generator/pubspec.yaml +++ b/packages/palette_generator/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.3.3+5 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: collection: ^1.15.0 diff --git a/packages/path_provider/path_provider/CHANGELOG.md b/packages/path_provider/path_provider/CHANGELOG.md index 6a8b2aeacd09..1c8d48672e4d 100644 --- a/packages/path_provider/path_provider/CHANGELOG.md +++ b/packages/path_provider/path_provider/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 2.1.5 * Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. diff --git a/packages/path_provider/path_provider/example/pubspec.yaml b/packages/path_provider/path_provider/example/pubspec.yaml index 154e969ce49e..0e22c7b18093 100644 --- a/packages/path_provider/path_provider/example/pubspec.yaml +++ b/packages/path_provider/path_provider/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the path_provider plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/path_provider/path_provider_foundation/CHANGELOG.md b/packages/path_provider/path_provider_foundation/CHANGELOG.md index 39374d87dcb6..9cd88d4f38ff 100644 --- a/packages/path_provider/path_provider_foundation/CHANGELOG.md +++ b/packages/path_provider/path_provider_foundation/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 2.4.1 * Updates to Pigeon v22. diff --git a/packages/path_provider/path_provider_foundation/example/pubspec.yaml b/packages/path_provider/path_provider_foundation/example/pubspec.yaml index 860c9124c923..559ddef197d9 100644 --- a/packages/path_provider/path_provider_foundation/example/pubspec.yaml +++ b/packages/path_provider/path_provider_foundation/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the path_provider plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/path_provider/path_provider_foundation/pubspec.yaml b/packages/path_provider/path_provider_foundation/pubspec.yaml index 02a4dcbdb4af..c274352bfdf0 100644 --- a/packages/path_provider/path_provider_foundation/pubspec.yaml +++ b/packages/path_provider/path_provider_foundation/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.4.1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/path_provider/path_provider_linux/CHANGELOG.md b/packages/path_provider/path_provider_linux/CHANGELOG.md index 68d613ba43a4..b3b8ab37287b 100644 --- a/packages/path_provider/path_provider_linux/CHANGELOG.md +++ b/packages/path_provider/path_provider_linux/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 2.2.1 diff --git a/packages/path_provider/path_provider_linux/example/pubspec.yaml b/packages/path_provider/path_provider_linux/example/pubspec.yaml index 3eb9843ede65..27efc9bbe341 100644 --- a/packages/path_provider/path_provider_linux/example/pubspec.yaml +++ b/packages/path_provider/path_provider_linux/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the path_provider_linux plugin. publish_to: "none" environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/path_provider/path_provider_linux/pubspec.yaml b/packages/path_provider/path_provider_linux/pubspec.yaml index 02e6d6f2bbd7..dd1c058522e7 100644 --- a/packages/path_provider/path_provider_linux/pubspec.yaml +++ b/packages/path_provider/path_provider_linux/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.2.1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/path_provider/path_provider_platform_interface/CHANGELOG.md b/packages/path_provider/path_provider_platform_interface/CHANGELOG.md index 9c60b4e0db93..9754a3ff4deb 100644 --- a/packages/path_provider/path_provider_platform_interface/CHANGELOG.md +++ b/packages/path_provider/path_provider_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 2.1.2 diff --git a/packages/path_provider/path_provider_platform_interface/pubspec.yaml b/packages/path_provider/path_provider_platform_interface/pubspec.yaml index 2ea8166ed613..0f3d2abad5da 100644 --- a/packages/path_provider/path_provider_platform_interface/pubspec.yaml +++ b/packages/path_provider/path_provider_platform_interface/pubspec.yaml @@ -7,8 +7,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.1.2 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/path_provider/path_provider_windows/CHANGELOG.md b/packages/path_provider/path_provider_windows/CHANGELOG.md index d3c880d9afa7..b165081a4475 100644 --- a/packages/path_provider/path_provider_windows/CHANGELOG.md +++ b/packages/path_provider/path_provider_windows/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 2.3.0 diff --git a/packages/path_provider/path_provider_windows/example/pubspec.yaml b/packages/path_provider/path_provider_windows/example/pubspec.yaml index b5a73980e783..1dafd876e9ee 100644 --- a/packages/path_provider/path_provider_windows/example/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the path_provider plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/path_provider/path_provider_windows/pubspec.yaml b/packages/path_provider/path_provider_windows/pubspec.yaml index 8a9d00c42aeb..d507aa329f28 100644 --- a/packages/path_provider/path_provider_windows/pubspec.yaml +++ b/packages/path_provider/path_provider_windows/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.3.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/pigeon/CHANGELOG.md b/packages/pigeon/CHANGELOG.md index f7157e5867c4..e8226fe98562 100644 --- a/packages/pigeon/CHANGELOG.md +++ b/packages/pigeon/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 22.7.0 * [swift, kotlin] Adds event channel support. diff --git a/packages/pigeon/example/app/pubspec.yaml b/packages/pigeon/example/app/pubspec.yaml index ab11f4fa8293..afdc8a9ba37a 100644 --- a/packages/pigeon/example/app/pubspec.yaml +++ b/packages/pigeon/example/app/pubspec.yaml @@ -4,7 +4,7 @@ publish_to: 'none' version: 1.0.0 environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dependencies: flutter: diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/example/pubspec.yaml b/packages/pigeon/platform_tests/alternate_language_test_plugin/example/pubspec.yaml index d40ce1efd995..4839db95cc04 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/example/pubspec.yaml +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/example/pubspec.yaml @@ -3,7 +3,7 @@ description: Pigeon test harness for alternate plugin languages. publish_to: 'none' environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dependencies: alternate_language_test_plugin: diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/pubspec.yaml b/packages/pigeon/platform_tests/alternate_language_test_plugin/pubspec.yaml index eefdc514fd1e..9e4625dd0378 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/pubspec.yaml +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/pubspec.yaml @@ -4,8 +4,8 @@ version: 0.0.1 publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/pubspec.yaml b/packages/pigeon/platform_tests/shared_test_plugin_code/pubspec.yaml index f0ab70f80712..a345c4c7d304 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/pubspec.yaml +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/pubspec.yaml @@ -4,8 +4,8 @@ version: 0.0.1 publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: build_runner: ^2.1.10 diff --git a/packages/pigeon/platform_tests/test_plugin/example/pubspec.yaml b/packages/pigeon/platform_tests/test_plugin/example/pubspec.yaml index f37ef3a035f0..9b5f46bcb780 100644 --- a/packages/pigeon/platform_tests/test_plugin/example/pubspec.yaml +++ b/packages/pigeon/platform_tests/test_plugin/example/pubspec.yaml @@ -3,7 +3,7 @@ description: Pigeon test harness for primary plugin languages. publish_to: 'none' environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dependencies: flutter: diff --git a/packages/pigeon/platform_tests/test_plugin/pubspec.yaml b/packages/pigeon/platform_tests/test_plugin/pubspec.yaml index 2a06f09d03fc..f7a7075da110 100644 --- a/packages/pigeon/platform_tests/test_plugin/pubspec.yaml +++ b/packages/pigeon/platform_tests/test_plugin/pubspec.yaml @@ -4,8 +4,8 @@ version: 0.0.1 publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/pigeon/pubspec.yaml b/packages/pigeon/pubspec.yaml index a7b5056bac10..d525aba2f223 100644 --- a/packages/pigeon/pubspec.yaml +++ b/packages/pigeon/pubspec.yaml @@ -5,7 +5,7 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 22.7.0 # This must match the version in lib/generator_tools.dart environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dependencies: analyzer: ">=5.13.0 <7.0.0" diff --git a/packages/plugin_platform_interface/CHANGELOG.md b/packages/plugin_platform_interface/CHANGELOG.md index 6db60355d829..3b258aa2a0bb 100644 --- a/packages/plugin_platform_interface/CHANGELOG.md +++ b/packages/plugin_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 2.1.8 diff --git a/packages/plugin_platform_interface/pubspec.yaml b/packages/plugin_platform_interface/pubspec.yaml index 2285d41f9173..387a1de6fc0d 100644 --- a/packages/plugin_platform_interface/pubspec.yaml +++ b/packages/plugin_platform_interface/pubspec.yaml @@ -18,7 +18,7 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.1.8 environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dependencies: meta: ^1.3.0 diff --git a/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md b/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md index 5affc8fbeff8..bcf1983c780f 100644 --- a/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md +++ b/packages/pointer_interceptor/pointer_interceptor/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 0.10.1+2 diff --git a/packages/pointer_interceptor/pointer_interceptor/example/pubspec.yaml b/packages/pointer_interceptor/pointer_interceptor/example/pubspec.yaml index 1f4e8d771035..e63f87ce5e75 100644 --- a/packages/pointer_interceptor/pointer_interceptor/example/pubspec.yaml +++ b/packages/pointer_interceptor/pointer_interceptor/example/pubspec.yaml @@ -4,8 +4,8 @@ publish_to: 'none' version: 1.0.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/pointer_interceptor/pointer_interceptor/pubspec.yaml b/packages/pointer_interceptor/pointer_interceptor/pubspec.yaml index e7021029913f..16a9325e2ce9 100644 --- a/packages/pointer_interceptor/pointer_interceptor/pubspec.yaml +++ b/packages/pointer_interceptor/pointer_interceptor/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.10.1+2 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/pointer_interceptor/pointer_interceptor_ios/CHANGELOG.md b/packages/pointer_interceptor/pointer_interceptor_ios/CHANGELOG.md index 714b5cd05fbc..cfb73d094dd3 100644 --- a/packages/pointer_interceptor/pointer_interceptor_ios/CHANGELOG.md +++ b/packages/pointer_interceptor/pointer_interceptor_ios/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 0.10.1 diff --git a/packages/pointer_interceptor/pointer_interceptor_ios/example/pubspec.yaml b/packages/pointer_interceptor/pointer_interceptor_ios/example/pubspec.yaml index ffbda428f10e..fa15122d1e2e 100644 --- a/packages/pointer_interceptor/pointer_interceptor_ios/example/pubspec.yaml +++ b/packages/pointer_interceptor/pointer_interceptor_ios/example/pubspec.yaml @@ -3,8 +3,8 @@ description: "Demonstrates how to use the pointer_interceptor_ios plugin." publish_to: 'none' environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: cupertino_icons: ^1.0.2 diff --git a/packages/pointer_interceptor/pointer_interceptor_ios/pubspec.yaml b/packages/pointer_interceptor/pointer_interceptor_ios/pubspec.yaml index 194337f8a021..09e124b1a048 100644 --- a/packages/pointer_interceptor/pointer_interceptor_ios/pubspec.yaml +++ b/packages/pointer_interceptor/pointer_interceptor_ios/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.10.1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/pointer_interceptor/pointer_interceptor_platform_interface/CHANGELOG.md b/packages/pointer_interceptor/pointer_interceptor_platform_interface/CHANGELOG.md index 4bafe7e9352d..843fb21366c4 100644 --- a/packages/pointer_interceptor/pointer_interceptor_platform_interface/CHANGELOG.md +++ b/packages/pointer_interceptor/pointer_interceptor_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 0.10.0+1 diff --git a/packages/pointer_interceptor/pointer_interceptor_platform_interface/pubspec.yaml b/packages/pointer_interceptor/pointer_interceptor_platform_interface/pubspec.yaml index 6f5a475c3b63..f778a44d5e22 100644 --- a/packages/pointer_interceptor/pointer_interceptor_platform_interface/pubspec.yaml +++ b/packages/pointer_interceptor/pointer_interceptor_platform_interface/pubspec.yaml @@ -6,8 +6,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.10.0+1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/process/CHANGELOG.md b/packages/process/CHANGELOG.md index 603c5efc8aec..098292abbb44 100644 --- a/packages/process/CHANGELOG.md +++ b/packages/process/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 5.0.3 * Adds `missing_code_block_language_in_doc_comment` lint. diff --git a/packages/process/pubspec.yaml b/packages/process/pubspec.yaml index 4c5296dc7da8..489272b3d1e7 100644 --- a/packages/process/pubspec.yaml +++ b/packages/process/pubspec.yaml @@ -5,7 +5,7 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 5.0.3 environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dependencies: file: '>=6.0.0 <8.0.0' diff --git a/packages/quick_actions/quick_actions/CHANGELOG.md b/packages/quick_actions/quick_actions/CHANGELOG.md index b66476c12e18..c30222dd4da1 100644 --- a/packages/quick_actions/quick_actions/CHANGELOG.md +++ b/packages/quick_actions/quick_actions/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 1.1.0 * Adds localizedSubtitle field for iOS quick actions. diff --git a/packages/quick_actions/quick_actions/example/pubspec.yaml b/packages/quick_actions/quick_actions/example/pubspec.yaml index 7573f5bbf814..1fb3314fdfb1 100644 --- a/packages/quick_actions/quick_actions/example/pubspec.yaml +++ b/packages/quick_actions/quick_actions/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the quick_actions plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/quick_actions/quick_actions/pubspec.yaml b/packages/quick_actions/quick_actions/pubspec.yaml index 98fc3a3bf9f5..a8e9f4e1c245 100644 --- a/packages/quick_actions/quick_actions/pubspec.yaml +++ b/packages/quick_actions/quick_actions/pubspec.yaml @@ -6,8 +6,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 1.1.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/quick_actions/quick_actions_ios/CHANGELOG.md b/packages/quick_actions/quick_actions_ios/CHANGELOG.md index b49fb3602909..c53807404a26 100644 --- a/packages/quick_actions/quick_actions_ios/CHANGELOG.md +++ b/packages/quick_actions/quick_actions_ios/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 1.2.0 * Adds localizedSubtitle field for iOS quick actions. diff --git a/packages/quick_actions/quick_actions_ios/example/pubspec.yaml b/packages/quick_actions/quick_actions_ios/example/pubspec.yaml index d73d5160171b..ead7ff0d0481 100644 --- a/packages/quick_actions/quick_actions_ios/example/pubspec.yaml +++ b/packages/quick_actions/quick_actions_ios/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the quick_actions plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/quick_actions/quick_actions_ios/pubspec.yaml b/packages/quick_actions/quick_actions_ios/pubspec.yaml index a3ba140e2e81..973b5f9cdb5c 100644 --- a/packages/quick_actions/quick_actions_ios/pubspec.yaml +++ b/packages/quick_actions/quick_actions_ios/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 1.2.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/quick_actions/quick_actions_platform_interface/CHANGELOG.md b/packages/quick_actions/quick_actions_platform_interface/CHANGELOG.md index 941bed1ba610..5850f30bedc6 100644 --- a/packages/quick_actions/quick_actions_platform_interface/CHANGELOG.md +++ b/packages/quick_actions/quick_actions_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 1.1.0 * Adds localizedSubtitle field for iOS quick actions. diff --git a/packages/quick_actions/quick_actions_platform_interface/pubspec.yaml b/packages/quick_actions/quick_actions_platform_interface/pubspec.yaml index 11ff5823bba1..9635dcb73a1f 100644 --- a/packages/quick_actions/quick_actions_platform_interface/pubspec.yaml +++ b/packages/quick_actions/quick_actions_platform_interface/pubspec.yaml @@ -7,8 +7,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 1.1.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/rfw/CHANGELOG.md b/packages/rfw/CHANGELOG.md index e3fbedffe13d..5fd395e374ed 100644 --- a/packages/rfw/CHANGELOG.md +++ b/packages/rfw/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 1.0.30 * Adds `missing_code_block_language_in_doc_comment` lint. diff --git a/packages/rfw/example/hello/pubspec.yaml b/packages/rfw/example/hello/pubspec.yaml index 54a79fd6effe..398c8041c42f 100644 --- a/packages/rfw/example/hello/pubspec.yaml +++ b/packages/rfw/example/hello/pubspec.yaml @@ -4,8 +4,8 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/rfw/example/local/pubspec.yaml b/packages/rfw/example/local/pubspec.yaml index 7d05f298d00c..5fb34053db8e 100644 --- a/packages/rfw/example/local/pubspec.yaml +++ b/packages/rfw/example/local/pubspec.yaml @@ -4,8 +4,8 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/rfw/example/remote/pubspec.yaml b/packages/rfw/example/remote/pubspec.yaml index 946a8d00ac21..4a2a992f3751 100644 --- a/packages/rfw/example/remote/pubspec.yaml +++ b/packages/rfw/example/remote/pubspec.yaml @@ -4,8 +4,8 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/rfw/example/wasm/pubspec.yaml b/packages/rfw/example/wasm/pubspec.yaml index 04ebcb5402d3..81f2d9549ffe 100644 --- a/packages/rfw/example/wasm/pubspec.yaml +++ b/packages/rfw/example/wasm/pubspec.yaml @@ -4,8 +4,8 @@ publish_to: none # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/rfw/pubspec.yaml b/packages/rfw/pubspec.yaml index 76afa865e101..d152a36c700d 100644 --- a/packages/rfw/pubspec.yaml +++ b/packages/rfw/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 1.0.30 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/rfw/test_coverage/pubspec.yaml b/packages/rfw/test_coverage/pubspec.yaml index bb29e27c7543..ffee438d8182 100644 --- a/packages/rfw/test_coverage/pubspec.yaml +++ b/packages/rfw/test_coverage/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0 publish_to: none environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dependencies: lcov_parser: 0.1.1 diff --git a/packages/shared_preferences/shared_preferences_foundation/CHANGELOG.md b/packages/shared_preferences/shared_preferences_foundation/CHANGELOG.md index 42722fe4b182..6d2bdd8ab8a3 100644 --- a/packages/shared_preferences/shared_preferences_foundation/CHANGELOG.md +++ b/packages/shared_preferences/shared_preferences_foundation/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 2.5.3 * Updates Pigeon for non-nullable collection type support. diff --git a/packages/shared_preferences/shared_preferences_foundation/example/pubspec.yaml b/packages/shared_preferences/shared_preferences_foundation/example/pubspec.yaml index ac1ef988c6d8..931e2c7ac7db 100644 --- a/packages/shared_preferences/shared_preferences_foundation/example/pubspec.yaml +++ b/packages/shared_preferences/shared_preferences_foundation/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Testbed for the shared_preferences_foundation implementation. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/shared_preferences/shared_preferences_foundation/pubspec.yaml b/packages/shared_preferences/shared_preferences_foundation/pubspec.yaml index 50b73b1264bb..300fc87fe3b8 100644 --- a/packages/shared_preferences/shared_preferences_foundation/pubspec.yaml +++ b/packages/shared_preferences/shared_preferences_foundation/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.5.3 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/shared_preferences/shared_preferences_linux/CHANGELOG.md b/packages/shared_preferences/shared_preferences_linux/CHANGELOG.md index 43c46f51a84f..d769156bd35e 100644 --- a/packages/shared_preferences/shared_preferences_linux/CHANGELOG.md +++ b/packages/shared_preferences/shared_preferences_linux/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 2.4.1 * Fixes `getStringList` returning immutable list. diff --git a/packages/shared_preferences/shared_preferences_linux/example/pubspec.yaml b/packages/shared_preferences/shared_preferences_linux/example/pubspec.yaml index 35da7cfab3c9..0bf7bd8255b9 100644 --- a/packages/shared_preferences/shared_preferences_linux/example/pubspec.yaml +++ b/packages/shared_preferences/shared_preferences_linux/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the shared_preferences_linux plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/shared_preferences/shared_preferences_linux/pubspec.yaml b/packages/shared_preferences/shared_preferences_linux/pubspec.yaml index c43a21bdb95f..065e439e44b6 100644 --- a/packages/shared_preferences/shared_preferences_linux/pubspec.yaml +++ b/packages/shared_preferences/shared_preferences_linux/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.4.1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/shared_preferences/shared_preferences_platform_interface/CHANGELOG.md b/packages/shared_preferences/shared_preferences_platform_interface/CHANGELOG.md index b52c8c962bfc..36fa52e4bc8a 100644 --- a/packages/shared_preferences/shared_preferences_platform_interface/CHANGELOG.md +++ b/packages/shared_preferences/shared_preferences_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 2.4.1 diff --git a/packages/shared_preferences/shared_preferences_platform_interface/pubspec.yaml b/packages/shared_preferences/shared_preferences_platform_interface/pubspec.yaml index 6161a5882e1d..d8df0ac2bc60 100644 --- a/packages/shared_preferences/shared_preferences_platform_interface/pubspec.yaml +++ b/packages/shared_preferences/shared_preferences_platform_interface/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.4.1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/shared_preferences/shared_preferences_windows/CHANGELOG.md b/packages/shared_preferences/shared_preferences_windows/CHANGELOG.md index d2cf5d62ace9..c6ce11b9f6eb 100644 --- a/packages/shared_preferences/shared_preferences_windows/CHANGELOG.md +++ b/packages/shared_preferences/shared_preferences_windows/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 2.4.1 * Fixes `getStringList` returning immutable list. diff --git a/packages/shared_preferences/shared_preferences_windows/example/pubspec.yaml b/packages/shared_preferences/shared_preferences_windows/example/pubspec.yaml index dbbf7c7530ef..031474415774 100644 --- a/packages/shared_preferences/shared_preferences_windows/example/pubspec.yaml +++ b/packages/shared_preferences/shared_preferences_windows/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the shared_preferences_windows plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/shared_preferences/shared_preferences_windows/pubspec.yaml b/packages/shared_preferences/shared_preferences_windows/pubspec.yaml index 59c3274488b4..6c4f02e3e006 100644 --- a/packages/shared_preferences/shared_preferences_windows/pubspec.yaml +++ b/packages/shared_preferences/shared_preferences_windows/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.4.1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/standard_message_codec/CHANGELOG.md b/packages/standard_message_codec/CHANGELOG.md index 9da834b04cba..a87ddfe2a326 100644 --- a/packages/standard_message_codec/CHANGELOG.md +++ b/packages/standard_message_codec/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 0.0.1+4 diff --git a/packages/standard_message_codec/example/pubspec.yaml b/packages/standard_message_codec/example/pubspec.yaml index 40b4f7fc7f04..24edd8179688 100644 --- a/packages/standard_message_codec/example/pubspec.yaml +++ b/packages/standard_message_codec/example/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.0.1 publish_to: none environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dependencies: standard_message_codec: diff --git a/packages/standard_message_codec/pubspec.yaml b/packages/standard_message_codec/pubspec.yaml index f27690918b32..60343a8d508f 100644 --- a/packages/standard_message_codec/pubspec.yaml +++ b/packages/standard_message_codec/pubspec.yaml @@ -5,7 +5,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/standard_mess issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3Astandard_message_codec environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dev_dependencies: test: ^1.16.0 diff --git a/packages/two_dimensional_scrollables/CHANGELOG.md b/packages/two_dimensional_scrollables/CHANGELOG.md index 31ecdfdcdb66..cb4b895d5843 100644 --- a/packages/two_dimensional_scrollables/CHANGELOG.md +++ b/packages/two_dimensional_scrollables/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 0.3.3 * Fixes an issue where collapsing nodes in the TreeView didn't work correctly. diff --git a/packages/two_dimensional_scrollables/example/pubspec.yaml b/packages/two_dimensional_scrollables/example/pubspec.yaml index c7786ae10c6f..b96157acb18c 100644 --- a/packages/two_dimensional_scrollables/example/pubspec.yaml +++ b/packages/two_dimensional_scrollables/example/pubspec.yaml @@ -6,8 +6,8 @@ publish_to: 'none' version: 2.0.0 environment: - sdk: '>=3.3.0 <4.0.0' - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/two_dimensional_scrollables/pubspec.yaml b/packages/two_dimensional_scrollables/pubspec.yaml index 3cd575a8c76a..9cdd89917b33 100644 --- a/packages/two_dimensional_scrollables/pubspec.yaml +++ b/packages/two_dimensional_scrollables/pubspec.yaml @@ -5,8 +5,8 @@ repository: https://github.com/flutter/packages/tree/main/packages/two_dimension issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+two_dimensional_scrollables%22+ environment: - sdk: '>=3.3.0 <4.0.0' - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/url_launcher/url_launcher/CHANGELOG.md b/packages/url_launcher/url_launcher/CHANGELOG.md index 859646fbe7b3..83f67b28e596 100644 --- a/packages/url_launcher/url_launcher/CHANGELOG.md +++ b/packages/url_launcher/url_launcher/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 6.3.1 * Removes incorrect SMS instructions from README. diff --git a/packages/url_launcher/url_launcher/example/pubspec.yaml b/packages/url_launcher/url_launcher/example/pubspec.yaml index a20fb1f84d10..e3eae2544bf8 100644 --- a/packages/url_launcher/url_launcher/example/pubspec.yaml +++ b/packages/url_launcher/url_launcher/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the url_launcher plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/url_launcher/url_launcher/pubspec.yaml b/packages/url_launcher/url_launcher/pubspec.yaml index 3b594e883fba..5845ac4927d6 100644 --- a/packages/url_launcher/url_launcher/pubspec.yaml +++ b/packages/url_launcher/url_launcher/pubspec.yaml @@ -6,8 +6,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 6.3.1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/url_launcher/url_launcher_ios/CHANGELOG.md b/packages/url_launcher/url_launcher_ios/CHANGELOG.md index d0953fd61766..a7a283075d4c 100644 --- a/packages/url_launcher/url_launcher_ios/CHANGELOG.md +++ b/packages/url_launcher/url_launcher_ios/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 6.3.2 * Updates to Pigeon v22. diff --git a/packages/url_launcher/url_launcher_ios/example/pubspec.yaml b/packages/url_launcher/url_launcher_ios/example/pubspec.yaml index 3e259987a104..0416298beaca 100644 --- a/packages/url_launcher/url_launcher_ios/example/pubspec.yaml +++ b/packages/url_launcher/url_launcher_ios/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the url_launcher plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/url_launcher/url_launcher_ios/pubspec.yaml b/packages/url_launcher/url_launcher_ios/pubspec.yaml index 2069aa0931e3..4d11751a4a99 100644 --- a/packages/url_launcher/url_launcher_ios/pubspec.yaml +++ b/packages/url_launcher/url_launcher_ios/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 6.3.2 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/url_launcher/url_launcher_linux/CHANGELOG.md b/packages/url_launcher/url_launcher_linux/CHANGELOG.md index 7ba11785c092..8f20acefde26 100644 --- a/packages/url_launcher/url_launcher_linux/CHANGELOG.md +++ b/packages/url_launcher/url_launcher_linux/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 3.2.1 * Updates Pigeon to resolve a compilation failure with some versions of glib. diff --git a/packages/url_launcher/url_launcher_linux/example/pubspec.yaml b/packages/url_launcher/url_launcher_linux/example/pubspec.yaml index 0a3b93f5c21b..e9dfe5651d8b 100644 --- a/packages/url_launcher/url_launcher_linux/example/pubspec.yaml +++ b/packages/url_launcher/url_launcher_linux/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the url_launcher plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/url_launcher/url_launcher_linux/pubspec.yaml b/packages/url_launcher/url_launcher_linux/pubspec.yaml index fa1b45191043..60037197e8f2 100644 --- a/packages/url_launcher/url_launcher_linux/pubspec.yaml +++ b/packages/url_launcher/url_launcher_linux/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 3.2.1 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/url_launcher/url_launcher_macos/CHANGELOG.md b/packages/url_launcher/url_launcher_macos/CHANGELOG.md index 5da4d7951ec7..72aef5b6a002 100644 --- a/packages/url_launcher/url_launcher_macos/CHANGELOG.md +++ b/packages/url_launcher/url_launcher_macos/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 3.2.2 * Updates to Pigeon v22. diff --git a/packages/url_launcher/url_launcher_macos/example/pubspec.yaml b/packages/url_launcher/url_launcher_macos/example/pubspec.yaml index 4fa890968d27..9ae117df8c0a 100644 --- a/packages/url_launcher/url_launcher_macos/example/pubspec.yaml +++ b/packages/url_launcher/url_launcher_macos/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the url_launcher plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/url_launcher/url_launcher_macos/pubspec.yaml b/packages/url_launcher/url_launcher_macos/pubspec.yaml index 7f6505c702b5..fc9409038602 100644 --- a/packages/url_launcher/url_launcher_macos/pubspec.yaml +++ b/packages/url_launcher/url_launcher_macos/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 3.2.2 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/url_launcher/url_launcher_platform_interface/CHANGELOG.md b/packages/url_launcher/url_launcher_platform_interface/CHANGELOG.md index 680ce1a23db8..521687f1a78f 100644 --- a/packages/url_launcher/url_launcher_platform_interface/CHANGELOG.md +++ b/packages/url_launcher/url_launcher_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 2.3.2 diff --git a/packages/url_launcher/url_launcher_platform_interface/pubspec.yaml b/packages/url_launcher/url_launcher_platform_interface/pubspec.yaml index b31502a3d6c5..837277694458 100644 --- a/packages/url_launcher/url_launcher_platform_interface/pubspec.yaml +++ b/packages/url_launcher/url_launcher_platform_interface/pubspec.yaml @@ -7,8 +7,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.3.2 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/url_launcher/url_launcher_web/CHANGELOG.md b/packages/url_launcher/url_launcher_web/CHANGELOG.md index b891293c005f..0baf6389c8b9 100644 --- a/packages/url_launcher/url_launcher_web/CHANGELOG.md +++ b/packages/url_launcher/url_launcher_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 2.3.3 * Changes `launchUrl` so it always returns `true`, except for disallowed URL schemes. diff --git a/packages/url_launcher/url_launcher_web/example/pubspec.yaml b/packages/url_launcher/url_launcher_web/example/pubspec.yaml index 606f477b4a40..a70f27951b9e 100644 --- a/packages/url_launcher/url_launcher_web/example/pubspec.yaml +++ b/packages/url_launcher/url_launcher_web/example/pubspec.yaml @@ -2,8 +2,8 @@ name: regular_integration_tests publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/url_launcher/url_launcher_web/pubspec.yaml b/packages/url_launcher/url_launcher_web/pubspec.yaml index 3730a4dd90e4..7b9068d19153 100644 --- a/packages/url_launcher/url_launcher_web/pubspec.yaml +++ b/packages/url_launcher/url_launcher_web/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.3.3 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/url_launcher/url_launcher_windows/CHANGELOG.md b/packages/url_launcher/url_launcher_windows/CHANGELOG.md index 668ee6eff6ac..05a2acbd6b16 100644 --- a/packages/url_launcher/url_launcher_windows/CHANGELOG.md +++ b/packages/url_launcher/url_launcher_windows/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 3.1.3 * Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. diff --git a/packages/url_launcher/url_launcher_windows/example/pubspec.yaml b/packages/url_launcher/url_launcher_windows/example/pubspec.yaml index d76188c383ec..f00c0ba76132 100644 --- a/packages/url_launcher/url_launcher_windows/example/pubspec.yaml +++ b/packages/url_launcher/url_launcher_windows/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates the Windows implementation of the url_launcher plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/url_launcher/url_launcher_windows/pubspec.yaml b/packages/url_launcher/url_launcher_windows/pubspec.yaml index 629e9dc71963..5c81c7786754 100644 --- a/packages/url_launcher/url_launcher_windows/pubspec.yaml +++ b/packages/url_launcher/url_launcher_windows/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 3.1.3 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/video_player/video_player/CHANGELOG.md b/packages/video_player/video_player/CHANGELOG.md index 5e448be001b3..22a4bc0ed80a 100644 --- a/packages/video_player/video_player/CHANGELOG.md +++ b/packages/video_player/video_player/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 2.9.2 * Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. diff --git a/packages/video_player/video_player/example/pubspec.yaml b/packages/video_player/video_player/example/pubspec.yaml index 25f812abeeee..5755db029dd6 100644 --- a/packages/video_player/video_player/example/pubspec.yaml +++ b/packages/video_player/video_player/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the video_player plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/video_player/video_player/pubspec.yaml b/packages/video_player/video_player/pubspec.yaml index 6e8b92684d7c..c19f6c6f77ca 100644 --- a/packages/video_player/video_player/pubspec.yaml +++ b/packages/video_player/video_player/pubspec.yaml @@ -6,8 +6,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.9.2 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/video_player/video_player_avfoundation/CHANGELOG.md b/packages/video_player/video_player_avfoundation/CHANGELOG.md index eff85341000b..0f0b4dabac26 100644 --- a/packages/video_player/video_player_avfoundation/CHANGELOG.md +++ b/packages/video_player/video_player_avfoundation/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 2.6.5 * Bugfix to allow the audio-only HLS (.m3u8) on iOS. diff --git a/packages/video_player/video_player_avfoundation/example/pubspec.yaml b/packages/video_player/video_player_avfoundation/example/pubspec.yaml index ea24144202f9..ab457872a0d8 100644 --- a/packages/video_player/video_player_avfoundation/example/pubspec.yaml +++ b/packages/video_player/video_player_avfoundation/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the video_player plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/video_player/video_player_avfoundation/pubspec.yaml b/packages/video_player/video_player_avfoundation/pubspec.yaml index 632e59f60fd5..e6e72fefab27 100644 --- a/packages/video_player/video_player_avfoundation/pubspec.yaml +++ b/packages/video_player/video_player_avfoundation/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.6.5 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" flutter: plugin: diff --git a/packages/video_player/video_player_platform_interface/CHANGELOG.md b/packages/video_player/video_player_platform_interface/CHANGELOG.md index 471cde8298d4..3c1e70fec40a 100644 --- a/packages/video_player/video_player_platform_interface/CHANGELOG.md +++ b/packages/video_player/video_player_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 6.2.3 * Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. diff --git a/packages/video_player/video_player_platform_interface/pubspec.yaml b/packages/video_player/video_player_platform_interface/pubspec.yaml index 7ed49e9e2d3d..6a0f1e65c210 100644 --- a/packages/video_player/video_player_platform_interface/pubspec.yaml +++ b/packages/video_player/video_player_platform_interface/pubspec.yaml @@ -7,8 +7,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 6.2.3 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/web_benchmarks/CHANGELOG.md b/packages/web_benchmarks/CHANGELOG.md index 934507cfbde3..b724d0ef2f80 100644 --- a/packages/web_benchmarks/CHANGELOG.md +++ b/packages/web_benchmarks/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 4.0.0 * **Breaking change:** Removes `CompilationOptions.renderer` and the diff --git a/packages/web_benchmarks/pubspec.yaml b/packages/web_benchmarks/pubspec.yaml index ed3ca89f9ffa..3c10d9047153 100644 --- a/packages/web_benchmarks/pubspec.yaml +++ b/packages/web_benchmarks/pubspec.yaml @@ -5,8 +5,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 4.0.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: collection: ^1.18.0 diff --git a/packages/web_benchmarks/testing/test_app/pubspec.yaml b/packages/web_benchmarks/testing/test_app/pubspec.yaml index 902f1e0ba9cb..27458c3d704f 100644 --- a/packages/web_benchmarks/testing/test_app/pubspec.yaml +++ b/packages/web_benchmarks/testing/test_app/pubspec.yaml @@ -6,7 +6,7 @@ publish_to: 'none' version: 1.0.0+1 environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dependencies: flutter: diff --git a/packages/webview_flutter/webview_flutter/CHANGELOG.md b/packages/webview_flutter/webview_flutter/CHANGELOG.md index f52c4cbce1ce..1d95b3b902a4 100644 --- a/packages/webview_flutter/webview_flutter/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 4.10.0 * Updates minimum supported `webview_flutter_android` from 3.16.0 to 4.0.0. diff --git a/packages/webview_flutter/webview_flutter/example/pubspec.yaml b/packages/webview_flutter/webview_flutter/example/pubspec.yaml index 1eb34f957ea0..e6152419a9a9 100644 --- a/packages/webview_flutter/webview_flutter/example/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the webview_flutter plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md b/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md index f6b57b5e1a5c..5b3a1ba25b39 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 2.10.0 diff --git a/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml b/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml index c7cb7f96eba1..6bfcad34aa5e 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml @@ -7,8 +7,8 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.10.0 environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md index 11e104865443..0cd1ce8e29be 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 3.16.3 * Fixes re-registering existing channels while removing Javascript channels. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml index 2212808e098e..051e60afa666 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the webview_flutter_wkwebview plugin. publish_to: none environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/xdg_directories/CHANGELOG.md b/packages/xdg_directories/CHANGELOG.md index caad99371e95..bd23eb2d093a 100644 --- a/packages/xdg_directories/CHANGELOG.md +++ b/packages/xdg_directories/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 1.1.0 * Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. diff --git a/packages/xdg_directories/example/pubspec.yaml b/packages/xdg_directories/example/pubspec.yaml index 6371986d179c..1f0314a685e3 100644 --- a/packages/xdg_directories/example/pubspec.yaml +++ b/packages/xdg_directories/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the xdg_directories package. publish_to: 'none' environment: - sdk: ^3.3.0 - flutter: ">=3.19.0" + sdk: ^3.4.0 + flutter: ">=3.22.0" dependencies: flutter: diff --git a/packages/xdg_directories/pubspec.yaml b/packages/xdg_directories/pubspec.yaml index 732bf2cd3f44..0983195a0a37 100644 --- a/packages/xdg_directories/pubspec.yaml +++ b/packages/xdg_directories/pubspec.yaml @@ -5,7 +5,7 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 1.1.0 environment: - sdk: ^3.3.0 + sdk: ^3.4.0 platforms: linux: diff --git a/script/tool/lib/src/common/core.dart b/script/tool/lib/src/common/core.dart index 9fef751ab56d..57b48252241d 100644 --- a/script/tool/lib/src/common/core.dart +++ b/script/tool/lib/src/common/core.dart @@ -85,6 +85,8 @@ final Map _dartSdkForFlutterSdk = { Version(3, 22, 0): Version(3, 4, 0), Version(3, 22, 3): Version(3, 4, 4), Version(3, 24, 0): Version(3, 5, 0), + Version(3, 24, 5): Version(3, 5, 4), + Version(3, 27, 0): Version(3, 6, 0), }; /// Returns the version of the Dart SDK that shipped with the given Flutter diff --git a/third_party/packages/cupertino_icons/CHANGELOG.md b/third_party/packages/cupertino_icons/CHANGELOG.md index 447d622436e4..49e20a6a5f52 100644 --- a/third_party/packages/cupertino_icons/CHANGELOG.md +++ b/third_party/packages/cupertino_icons/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 1.0.8 diff --git a/third_party/packages/cupertino_icons/pubspec.yaml b/third_party/packages/cupertino_icons/pubspec.yaml index 76e5962fd4e1..9ad4317bdea0 100644 --- a/third_party/packages/cupertino_icons/pubspec.yaml +++ b/third_party/packages/cupertino_icons/pubspec.yaml @@ -6,7 +6,7 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 1.0.8 environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dev_dependencies: collection: ^1.18.0 diff --git a/third_party/packages/path_parsing/CHANGELOG.md b/third_party/packages/path_parsing/CHANGELOG.md index 976dbd012355..f543e817124b 100644 --- a/third_party/packages/path_parsing/CHANGELOG.md +++ b/third_party/packages/path_parsing/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + ## 1.1.0 * Deprecates top-level utility functions `blendPoints` and `reflectedPoint` and diff --git a/third_party/packages/path_parsing/example/pubspec.yaml b/third_party/packages/path_parsing/example/pubspec.yaml index dd9a6eef8dcb..02b1e094156e 100644 --- a/third_party/packages/path_parsing/example/pubspec.yaml +++ b/third_party/packages/path_parsing/example/pubspec.yaml @@ -2,7 +2,7 @@ name: path_parsing_example publish_to: none environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dependencies: path_parsing: diff --git a/third_party/packages/path_parsing/pubspec.yaml b/third_party/packages/path_parsing/pubspec.yaml index ae99c4dffc07..3c11104989f8 100644 --- a/third_party/packages/path_parsing/pubspec.yaml +++ b/third_party/packages/path_parsing/pubspec.yaml @@ -6,7 +6,7 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 1.1.0 environment: - sdk: ^3.3.0 + sdk: ^3.4.0 dependencies: meta: ^1.3.0 From 5e141f0708872bacf195d75950b9e397bc652446 Mon Sep 17 00:00:00 2001 From: Vitalii Date: Fri, 13 Dec 2024 01:34:56 +0200 Subject: [PATCH 14/24] [go_router] Fix a typo in a comment in the shell_route.dart (#8235) Fixed a typo in a comment in the shell_route.dart. --- packages/go_router/example/lib/shell_route.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/go_router/example/lib/shell_route.dart b/packages/go_router/example/lib/shell_route.dart index 1628151d9371..7ffc474b0fd3 100644 --- a/packages/go_router/example/lib/shell_route.dart +++ b/packages/go_router/example/lib/shell_route.dart @@ -87,7 +87,7 @@ class ShellRouteExampleApp extends StatelessWidget { }, routes: [ // The details screen to display stacked on the inner Navigator. - // This will cover screen A but not the application shell. + // This will cover screen C but not the application shell. GoRoute( path: 'details', builder: (BuildContext context, GoRouterState state) { From 4ce4a2119d3ed318606a4576b44df1713b56f875 Mon Sep 17 00:00:00 2001 From: Valentin Vignal <32538273+ValentinVignal@users.noreply.github.com> Date: Fri, 13 Dec 2024 12:07:17 +0800 Subject: [PATCH 15/24] [go_router_builder] Activate leak testing (#8059) --- packages/go_router_builder/pubspec.yaml | 1 + .../go_router_builder/test/flutter_test_config.dart | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 packages/go_router_builder/test/flutter_test_config.dart diff --git a/packages/go_router_builder/pubspec.yaml b/packages/go_router_builder/pubspec.yaml index 8de1e3cc10e8..ef914abf8690 100644 --- a/packages/go_router_builder/pubspec.yaml +++ b/packages/go_router_builder/pubspec.yaml @@ -27,6 +27,7 @@ dev_dependencies: flutter: sdk: flutter go_router: ^14.0.0 + leak_tracker_flutter_testing: ">=3.0.0" test: ^1.20.0 topics: diff --git a/packages/go_router_builder/test/flutter_test_config.dart b/packages/go_router_builder/test/flutter_test_config.dart new file mode 100644 index 000000000000..9907e578b84b --- /dev/null +++ b/packages/go_router_builder/test/flutter_test_config.dart @@ -0,0 +1,13 @@ +// 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. + +import 'dart:async'; + +import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; + +Future testExecutable(FutureOr Function() testMain) async { + LeakTesting.enable(); + LeakTracking.warnForUnsupportedPlatforms = false; + await testMain(); +} From 56886ffe11ad677729ffeabcba227c9ad4218635 Mon Sep 17 00:00:00 2001 From: Rutvik Sanghavi Date: Fri, 13 Dec 2024 07:31:54 -0700 Subject: [PATCH 16/24] [webview_flutter_android] Allow configuration of WebView file access through `setAllowFileAccess` (#8228) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This pull request updates the `webview_flutter_android` package to allow developers to configure file access permissions for WebViews on Android devices. A new method, `AndroidWebViewController.setAllowFileAccess`, has been introduced, providing developers the ability to explicitly enable or disable file access as needed. Previously, file access permissions were dependent on the platform defaults, which could potentially lead to implicit behavior or unexpected security implications. This change empowers developers to make deliberate decisions about file access based on their app’s needs and security requirements. Addresses Issue [159810](https://github.com/flutter/flutter/issues/159810) --- .../webview_flutter_android/CHANGELOG.md | 4 ++++ .../lib/src/android_webview_controller.dart | 7 +++++++ .../webview_flutter_android/pubspec.yaml | 2 +- .../test/android_webview_controller_test.dart | 16 ++++++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md index 16dcfd07e48c..24633e85bd86 100644 --- a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.2.0 + +* Adds support for configuring file access permissions. See `AndroidWebViewController.setAllowFileAccess`. + ## 4.1.0 * Updates internal API wrapper to use `ProxyApi`s. diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart index c250a87d36a9..3cde232ca9f9 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart @@ -353,6 +353,13 @@ class AndroidWebViewController extends PlatformWebViewController { void Function(ScrollPositionChange scrollPositionChange)? _onScrollPositionChangedCallback; + /// Sets the file access permission for the web view. + /// + /// The default value is true for apps targeting API 29 and below, and false + /// when targeting API 30 and above. + Future setAllowFileAccess(bool allow) => + _webView.settings.setAllowFileAccess(allow); + /// Whether to enable the platform's webview content debugging tools. /// /// Defaults to false. diff --git a/packages/webview_flutter/webview_flutter_android/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/pubspec.yaml index 4ff9b6166a6d..44f19b2af19c 100644 --- a/packages/webview_flutter/webview_flutter_android/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_android/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_android description: A Flutter plugin that provides a WebView widget on Android. repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 4.1.0 +version: 4.2.0 environment: sdk: ^3.5.0 diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.dart index 6879c33253e7..167b660aa53f 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.dart @@ -1495,6 +1495,22 @@ void main() { expect(await controller.getUserAgent(), userAgent); }); + + test('setAllowFileAccess', () async { + final MockWebView mockWebView = MockWebView(); + final MockWebSettings mockSettings = MockWebSettings(); + final AndroidWebViewController controller = createControllerWithMocks( + mockWebView: mockWebView, + mockSettings: mockSettings, + ); + + clearInteractions(mockWebView); + + await controller.setAllowFileAccess(true); + + verify(mockWebView.settings).called(1); + verify(mockSettings.setAllowFileAccess(true)).called(1); + }); }); test('setMediaPlaybackRequiresUserGesture', () async { From 563dd2ca2a05caf5233b26c367065314189703a0 Mon Sep 17 00:00:00 2001 From: Tarrin Neal Date: Fri, 13 Dec 2024 07:57:12 -0800 Subject: [PATCH 17/24] [shared_preferences] Adds Shared preferences as option in shared preferences async android (#7994) Adds the ability to select which Android preferences backend (SharedPreferences or DataStore Preferences) one would like to use. Also adds the ability to pick a file name for the shared preferences backend. fixes https://github.com/flutter/flutter/issues/153300 fixes https://github.com/flutter/flutter/issues/14337 --- .../shared_preferences_android/CHANGELOG.md | 4 + .../shared_preferences_android/README.md | 17 + .../android/build.gradle | 3 +- .../android/gradle.properties | 3 + .../sharedpreferences/MessagesAsync.g.kt | 260 +++++----- .../SharedPreferencesPlugin.kt | 232 +++++++-- .../SharedPreferencesTest.kt | 311 ++++++++---- .../example/android/.gitignore | 2 + .../example/android/app/build.gradle | 34 +- .../MainActivityTest.java | 6 +- .../android/app/src/debug/AndroidManifest.xml | 6 +- .../android/app/src/main/AndroidManifest.xml | 10 +- .../MainActivity.java | 26 + .../flutter/plugins/DartIntegrationTest.java | 0 .../app/src/profile/AndroidManifest.xml | 6 +- .../gradle/wrapper/gradle-wrapper.properties | 3 +- .../example/android/settings.gradle | 2 +- .../shared_preferences_test.dart | 443 +++++++++++------- .../example/lib/main.dart | 10 +- .../lib/src/messages_async.g.dart | 398 ++++++++-------- .../src/shared_preferences_async_android.dart | 141 ++++-- .../pigeons/messages_async.dart | 6 +- .../shared_preferences_android/pubspec.yaml | 4 +- .../test/shared_preferences_async_test.dart | 366 ++++++++------- .../CHANGELOG.md | 3 +- .../messages.g.swift | 18 +- .../pubspec.yaml | 2 +- 27 files changed, 1478 insertions(+), 838 deletions(-) create mode 100644 packages/shared_preferences/shared_preferences_android/android/gradle.properties rename packages/shared_preferences/shared_preferences_android/example/android/app/src/androidTest/java/{io/flutter/plugins/sharedpreferencesexample => dev/flutter/plugins/shared_preferences_example}/MainActivityTest.java (69%) create mode 100644 packages/shared_preferences/shared_preferences_android/example/android/app/src/main/java/dev/flutter/plugins/shared_preferences_example/MainActivity.java rename packages/shared_preferences/shared_preferences_android/example/android/app/src/{androidTest => main}/java/io/flutter/plugins/DartIntegrationTest.java (100%) diff --git a/packages/shared_preferences/shared_preferences_android/CHANGELOG.md b/packages/shared_preferences/shared_preferences_android/CHANGELOG.md index 958932eda0c3..e8abda3d2628 100644 --- a/packages/shared_preferences/shared_preferences_android/CHANGELOG.md +++ b/packages/shared_preferences/shared_preferences_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.4.0 + +* Adds `SharedPreferences` support within `SharedPreferencesAsyncAndroid` API. + ## 2.3.4 * Restrict types when decoding preferences. diff --git a/packages/shared_preferences/shared_preferences_android/README.md b/packages/shared_preferences/shared_preferences_android/README.md index d12b09c068a2..8d8a84e9f135 100644 --- a/packages/shared_preferences/shared_preferences_android/README.md +++ b/packages/shared_preferences/shared_preferences_android/README.md @@ -11,5 +11,22 @@ so you do not need to add it to your `pubspec.yaml`. However, if you `import` this package to use any of its APIs directly, you should add it to your `pubspec.yaml` as usual. +## Options + +The [SharedPreferencesAsync] and [SharedPreferencesWithCache] APIs can use [DataStore Preferences](https://developer.android.com/topic/libraries/architecture/datastore) or [Android SharedPreferences](https://developer.android.com/reference/android/content/SharedPreferences) to store data. + +To use the `Android SharedPreferences` backend, use the `SharedPreferencesAsyncAndroidOptions` when using [SharedPreferencesAsync]. + + +```dart +const SharedPreferencesAsyncAndroidOptions options = + SharedPreferencesAsyncAndroidOptions( + backend: SharedPreferencesAndroidBackendLibrary.SharedPreferences, + originalSharedPreferencesOptions: AndroidSharedPreferencesStoreOptions( + fileName: 'the_name_of_a_file')); +``` + +The [SharedPreferences] API uses the native [Android SharedPreferences](https://developer.android.com/reference/android/content/SharedPreferences) tool to store data. + [1]: https://pub.dev/packages/shared_preferences [2]: https://flutter.dev/to/endorsed-federated-plugin diff --git a/packages/shared_preferences/shared_preferences_android/android/build.gradle b/packages/shared_preferences/shared_preferences_android/android/build.gradle index 28dc9ef31dbe..9d165eaf3e43 100644 --- a/packages/shared_preferences/shared_preferences_android/android/build.gradle +++ b/packages/shared_preferences/shared_preferences_android/android/build.gradle @@ -60,7 +60,8 @@ android { } dependencies { implementation 'androidx.datastore:datastore:1.0.0' - implementation 'androidx.datastore:datastore-preferences:1.0.0' + implementation 'androidx.datastore:datastore-preferences:1.0.0' + implementation 'androidx.preference:preference:1.2.1' testImplementation 'junit:junit:4.13.2' testImplementation 'androidx.test:core-ktx:1.5.0' testImplementation 'androidx.test.ext:junit-ktx:1.2.1' diff --git a/packages/shared_preferences/shared_preferences_android/android/gradle.properties b/packages/shared_preferences/shared_preferences_android/android/gradle.properties new file mode 100644 index 000000000000..598d13fee446 --- /dev/null +++ b/packages/shared_preferences/shared_preferences_android/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx4G +android.useAndroidX=true +android.enableJetifier=true diff --git a/packages/shared_preferences/shared_preferences_android/android/src/main/kotlin/io/flutter/plugins/sharedpreferences/MessagesAsync.g.kt b/packages/shared_preferences/shared_preferences_android/android/src/main/kotlin/io/flutter/plugins/sharedpreferences/MessagesAsync.g.kt index 159253f4280e..6855bad260b9 100644 --- a/packages/shared_preferences/shared_preferences_android/android/src/main/kotlin/io/flutter/plugins/sharedpreferences/MessagesAsync.g.kt +++ b/packages/shared_preferences/shared_preferences_android/android/src/main/kotlin/io/flutter/plugins/sharedpreferences/MessagesAsync.g.kt @@ -1,8 +1,9 @@ // 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 (v16.0.5), do not edit directly. +// Autogenerated from Pigeon (v22.6.1), do not edit directly. // See also: https://pub.dev/packages/pigeon +@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") package io.flutter.plugins.sharedpreferences @@ -19,10 +20,10 @@ private fun wrapResult(result: Any?): List { } private fun wrapError(exception: Throwable): List { - if (exception is SharedPreferencesError) { - return listOf(exception.code, exception.message, exception.details) + return if (exception is SharedPreferencesError) { + listOf(exception.code, exception.message, exception.details) } else { - return listOf( + listOf( exception.javaClass.simpleName, exception.toString(), "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)) @@ -43,28 +44,27 @@ class SharedPreferencesError( ) : Throwable() /** Generated class from Pigeon that represents data sent in messages. */ -data class SharedPreferencesPigeonOptions(val fileKey: String? = null) { - +data class SharedPreferencesPigeonOptions(val fileName: String? = null, val useDataStore: Boolean) { companion object { - @Suppress("UNCHECKED_CAST") - fun fromList(list: List): SharedPreferencesPigeonOptions { - val fileKey = list[0] as String? - return SharedPreferencesPigeonOptions(fileKey) + fun fromList(pigeonVar_list: List): SharedPreferencesPigeonOptions { + val fileName = pigeonVar_list[0] as String? + val useDataStore = pigeonVar_list[1] as Boolean + return SharedPreferencesPigeonOptions(fileName, useDataStore) } } fun toList(): List { - return listOf( - fileKey, + return listOf( + fileName, + useDataStore, ) } } -@Suppress("UNCHECKED_CAST") -private object SharedPreferencesAsyncApiCodec : StandardMessageCodec() { +private open class MessagesAsyncPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return when (type) { - 128.toByte() -> { + 129.toByte() -> { return (readValue(buffer) as? List)?.let { SharedPreferencesPigeonOptions.fromList(it) } @@ -76,7 +76,7 @@ private object SharedPreferencesAsyncApiCodec : StandardMessageCodec() { override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { when (value) { is SharedPreferencesPigeonOptions -> { - stream.write(128) + stream.write(129) writeValue(stream, value.toList()) } else -> super.writeValue(stream, value) @@ -115,19 +115,25 @@ interface SharedPreferencesAsyncApi { companion object { /** The codec used by SharedPreferencesAsyncApi. */ - val codec: MessageCodec by lazy { SharedPreferencesAsyncApiCodec } + val codec: MessageCodec by lazy { MessagesAsyncPigeonCodec() } /** * Sets up an instance of `SharedPreferencesAsyncApi` to handle messages through the * `binaryMessenger`. */ - @Suppress("UNCHECKED_CAST") - fun setUp(binaryMessenger: BinaryMessenger, api: SharedPreferencesAsyncApi?) { + @JvmOverloads + fun setUp( + binaryMessenger: BinaryMessenger, + api: SharedPreferencesAsyncApi?, + messageChannelSuffix: String = "" + ) { + val separatedMessageChannelSuffix = + if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" run { val taskQueue = binaryMessenger.makeBackgroundTaskQueue() val channel = BasicMessageChannel( binaryMessenger, - "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setBool", + "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setBool$separatedMessageChannelSuffix", codec, taskQueue) if (api != null) { @@ -136,13 +142,13 @@ interface SharedPreferencesAsyncApi { val keyArg = args[0] as String val valueArg = args[1] as Boolean val optionsArg = args[2] as SharedPreferencesPigeonOptions - var wrapped: List - try { - api.setBool(keyArg, valueArg, optionsArg) - wrapped = listOf(null) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } + val wrapped: List = + try { + api.setBool(keyArg, valueArg, optionsArg) + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } reply.reply(wrapped) } } else { @@ -154,7 +160,7 @@ interface SharedPreferencesAsyncApi { val channel = BasicMessageChannel( binaryMessenger, - "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setString", + "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setString$separatedMessageChannelSuffix", codec, taskQueue) if (api != null) { @@ -163,13 +169,13 @@ interface SharedPreferencesAsyncApi { val keyArg = args[0] as String val valueArg = args[1] as String val optionsArg = args[2] as SharedPreferencesPigeonOptions - var wrapped: List - try { - api.setString(keyArg, valueArg, optionsArg) - wrapped = listOf(null) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } + val wrapped: List = + try { + api.setString(keyArg, valueArg, optionsArg) + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } reply.reply(wrapped) } } else { @@ -181,22 +187,22 @@ interface SharedPreferencesAsyncApi { val channel = BasicMessageChannel( binaryMessenger, - "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setInt", + "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setInt$separatedMessageChannelSuffix", codec, taskQueue) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val keyArg = args[0] as String - val valueArg = args[1].let { if (it is Int) it.toLong() else it as Long } + val valueArg = args[1] as Long val optionsArg = args[2] as SharedPreferencesPigeonOptions - var wrapped: List - try { - api.setInt(keyArg, valueArg, optionsArg) - wrapped = listOf(null) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } + val wrapped: List = + try { + api.setInt(keyArg, valueArg, optionsArg) + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } reply.reply(wrapped) } } else { @@ -208,7 +214,7 @@ interface SharedPreferencesAsyncApi { val channel = BasicMessageChannel( binaryMessenger, - "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setDouble", + "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setDouble$separatedMessageChannelSuffix", codec, taskQueue) if (api != null) { @@ -217,13 +223,13 @@ interface SharedPreferencesAsyncApi { val keyArg = args[0] as String val valueArg = args[1] as Double val optionsArg = args[2] as SharedPreferencesPigeonOptions - var wrapped: List - try { - api.setDouble(keyArg, valueArg, optionsArg) - wrapped = listOf(null) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } + val wrapped: List = + try { + api.setDouble(keyArg, valueArg, optionsArg) + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } reply.reply(wrapped) } } else { @@ -235,7 +241,7 @@ interface SharedPreferencesAsyncApi { val channel = BasicMessageChannel( binaryMessenger, - "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setStringList", + "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setStringList$separatedMessageChannelSuffix", codec, taskQueue) if (api != null) { @@ -244,13 +250,13 @@ interface SharedPreferencesAsyncApi { val keyArg = args[0] as String val valueArg = args[1] as List val optionsArg = args[2] as SharedPreferencesPigeonOptions - var wrapped: List - try { - api.setStringList(keyArg, valueArg, optionsArg) - wrapped = listOf(null) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } + val wrapped: List = + try { + api.setStringList(keyArg, valueArg, optionsArg) + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } reply.reply(wrapped) } } else { @@ -258,22 +264,24 @@ interface SharedPreferencesAsyncApi { } } run { + val taskQueue = binaryMessenger.makeBackgroundTaskQueue() val channel = BasicMessageChannel( binaryMessenger, - "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getString", - codec) + "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getString$separatedMessageChannelSuffix", + codec, + taskQueue) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val keyArg = args[0] as String val optionsArg = args[1] as SharedPreferencesPigeonOptions - var wrapped: List - try { - wrapped = listOf(api.getString(keyArg, optionsArg)) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } + val wrapped: List = + try { + listOf(api.getString(keyArg, optionsArg)) + } catch (exception: Throwable) { + wrapError(exception) + } reply.reply(wrapped) } } else { @@ -281,22 +289,24 @@ interface SharedPreferencesAsyncApi { } } run { + val taskQueue = binaryMessenger.makeBackgroundTaskQueue() val channel = BasicMessageChannel( binaryMessenger, - "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getBool", - codec) + "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getBool$separatedMessageChannelSuffix", + codec, + taskQueue) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val keyArg = args[0] as String val optionsArg = args[1] as SharedPreferencesPigeonOptions - var wrapped: List - try { - wrapped = listOf(api.getBool(keyArg, optionsArg)) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } + val wrapped: List = + try { + listOf(api.getBool(keyArg, optionsArg)) + } catch (exception: Throwable) { + wrapError(exception) + } reply.reply(wrapped) } } else { @@ -304,22 +314,24 @@ interface SharedPreferencesAsyncApi { } } run { + val taskQueue = binaryMessenger.makeBackgroundTaskQueue() val channel = BasicMessageChannel( binaryMessenger, - "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getDouble", - codec) + "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getDouble$separatedMessageChannelSuffix", + codec, + taskQueue) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val keyArg = args[0] as String val optionsArg = args[1] as SharedPreferencesPigeonOptions - var wrapped: List - try { - wrapped = listOf(api.getDouble(keyArg, optionsArg)) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } + val wrapped: List = + try { + listOf(api.getDouble(keyArg, optionsArg)) + } catch (exception: Throwable) { + wrapError(exception) + } reply.reply(wrapped) } } else { @@ -327,22 +339,24 @@ interface SharedPreferencesAsyncApi { } } run { + val taskQueue = binaryMessenger.makeBackgroundTaskQueue() val channel = BasicMessageChannel( binaryMessenger, - "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getInt", - codec) + "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getInt$separatedMessageChannelSuffix", + codec, + taskQueue) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val keyArg = args[0] as String val optionsArg = args[1] as SharedPreferencesPigeonOptions - var wrapped: List - try { - wrapped = listOf(api.getInt(keyArg, optionsArg)) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } + val wrapped: List = + try { + listOf(api.getInt(keyArg, optionsArg)) + } catch (exception: Throwable) { + wrapError(exception) + } reply.reply(wrapped) } } else { @@ -350,22 +364,24 @@ interface SharedPreferencesAsyncApi { } } run { + val taskQueue = binaryMessenger.makeBackgroundTaskQueue() val channel = BasicMessageChannel( binaryMessenger, - "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getStringList", - codec) + "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getStringList$separatedMessageChannelSuffix", + codec, + taskQueue) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val keyArg = args[0] as String val optionsArg = args[1] as SharedPreferencesPigeonOptions - var wrapped: List - try { - wrapped = listOf(api.getStringList(keyArg, optionsArg)) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } + val wrapped: List = + try { + listOf(api.getStringList(keyArg, optionsArg)) + } catch (exception: Throwable) { + wrapError(exception) + } reply.reply(wrapped) } } else { @@ -377,7 +393,7 @@ interface SharedPreferencesAsyncApi { val channel = BasicMessageChannel( binaryMessenger, - "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.clear", + "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.clear$separatedMessageChannelSuffix", codec, taskQueue) if (api != null) { @@ -385,13 +401,13 @@ interface SharedPreferencesAsyncApi { val args = message as List val allowListArg = args[0] as List? val optionsArg = args[1] as SharedPreferencesPigeonOptions - var wrapped: List - try { - api.clear(allowListArg, optionsArg) - wrapped = listOf(null) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } + val wrapped: List = + try { + api.clear(allowListArg, optionsArg) + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } reply.reply(wrapped) } } else { @@ -403,7 +419,7 @@ interface SharedPreferencesAsyncApi { val channel = BasicMessageChannel( binaryMessenger, - "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getAll", + "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getAll$separatedMessageChannelSuffix", codec, taskQueue) if (api != null) { @@ -411,12 +427,12 @@ interface SharedPreferencesAsyncApi { val args = message as List val allowListArg = args[0] as List? val optionsArg = args[1] as SharedPreferencesPigeonOptions - var wrapped: List - try { - wrapped = listOf(api.getAll(allowListArg, optionsArg)) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } + val wrapped: List = + try { + listOf(api.getAll(allowListArg, optionsArg)) + } catch (exception: Throwable) { + wrapError(exception) + } reply.reply(wrapped) } } else { @@ -428,7 +444,7 @@ interface SharedPreferencesAsyncApi { val channel = BasicMessageChannel( binaryMessenger, - "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getKeys", + "dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getKeys$separatedMessageChannelSuffix", codec, taskQueue) if (api != null) { @@ -436,12 +452,12 @@ interface SharedPreferencesAsyncApi { val args = message as List val allowListArg = args[0] as List? val optionsArg = args[1] as SharedPreferencesPigeonOptions - var wrapped: List - try { - wrapped = listOf(api.getKeys(allowListArg, optionsArg)) - } catch (exception: Throwable) { - wrapped = wrapError(exception) - } + val wrapped: List = + try { + listOf(api.getKeys(allowListArg, optionsArg)) + } catch (exception: Throwable) { + wrapError(exception) + } reply.reply(wrapped) } } else { diff --git a/packages/shared_preferences/shared_preferences_android/android/src/main/kotlin/io/flutter/plugins/sharedpreferences/SharedPreferencesPlugin.kt b/packages/shared_preferences/shared_preferences_android/android/src/main/kotlin/io/flutter/plugins/sharedpreferences/SharedPreferencesPlugin.kt index 84c38630b899..e0ca35b258cf 100644 --- a/packages/shared_preferences/shared_preferences_android/android/src/main/kotlin/io/flutter/plugins/sharedpreferences/SharedPreferencesPlugin.kt +++ b/packages/shared_preferences/shared_preferences_android/android/src/main/kotlin/io/flutter/plugins/sharedpreferences/SharedPreferencesPlugin.kt @@ -5,6 +5,7 @@ package io.flutter.plugins.sharedpreferences import android.content.Context +import android.content.SharedPreferences import android.util.Base64 import android.util.Log import androidx.annotation.VisibleForTesting @@ -16,6 +17,7 @@ import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.longPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore +import androidx.preference.PreferenceManager import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.plugin.common.BinaryMessenger import java.io.ByteArrayInputStream @@ -29,6 +31,7 @@ import kotlinx.coroutines.runBlocking const val TAG = "SharedPreferencesPlugin" const val SHARED_PREFERENCES_NAME = "FlutterSharedPreferences" const val LIST_PREFIX = "VGhpcyBpcyB0aGUgcHJlZml4IGZvciBhIGxpc3Qu" +const val DOUBLE_PREFIX = "VGhpcyBpcyB0aGUgcHJlZml4IGZvciBEb3VibGUu" private val Context.sharedPreferencesDataStore: DataStore by preferencesDataStore(SHARED_PREFERENCES_NAME) @@ -36,6 +39,7 @@ private val Context.sharedPreferencesDataStore: DataStore by /// SharedPreferencesPlugin class SharedPreferencesPlugin() : FlutterPlugin, SharedPreferencesAsyncApi { private lateinit var context: Context + private var backend: SharedPreferencesBackend? = null private var listEncoder = ListEncoder() as SharedPreferencesListEncoder @@ -47,7 +51,8 @@ class SharedPreferencesPlugin() : FlutterPlugin, SharedPreferencesAsyncApi { private fun setUp(messenger: BinaryMessenger, context: Context) { this.context = context try { - SharedPreferencesAsyncApi.setUp(messenger, this) + SharedPreferencesAsyncApi.setUp(messenger, this, "data_store") + backend = SharedPreferencesBackend(messenger, context, listEncoder) } catch (ex: Exception) { Log.e(TAG, "Received exception while setting up SharedPreferencesPlugin", ex) } @@ -59,7 +64,9 @@ class SharedPreferencesPlugin() : FlutterPlugin, SharedPreferencesAsyncApi { } override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { - SharedPreferencesAsyncApi.setUp(binding.binaryMessenger, null) + SharedPreferencesAsyncApi.setUp(binding.binaryMessenger, null, "data_store") + backend?.tearDown() + backend = null } /** Adds property to data store of type bool. */ @@ -135,7 +142,6 @@ class SharedPreferencesPlugin() : FlutterPlugin, SharedPreferencesAsyncApi { val preferencesKey = longPreferencesKey(key) val preferenceFlow: Flow = context.sharedPreferencesDataStore.data.map { preferences -> preferences[preferencesKey] } - value = preferenceFlow.firstOrNull() } return value @@ -144,6 +150,7 @@ class SharedPreferencesPlugin() : FlutterPlugin, SharedPreferencesAsyncApi { /** Gets bool at [key] from data store. */ override fun getBool(key: String, options: SharedPreferencesPigeonOptions): Boolean? { val value: Boolean? + runBlocking { val preferencesKey = booleanPreferencesKey(key) val preferenceFlow: Flow = @@ -160,7 +167,7 @@ class SharedPreferencesPlugin() : FlutterPlugin, SharedPreferencesAsyncApi { val preferencesKey = stringPreferencesKey(key) val preferenceFlow: Flow = context.sharedPreferencesDataStore.data.map { preferences -> - transformPref(preferences[preferencesKey] as Any?) as Double? + transformPref(preferences[preferencesKey] as Any?, listEncoder) as Double? } value = preferenceFlow.firstOrNull() @@ -183,7 +190,8 @@ class SharedPreferencesPlugin() : FlutterPlugin, SharedPreferencesAsyncApi { /** Gets StringList at [key] from data store. */ override fun getStringList(key: String, options: SharedPreferencesPigeonOptions): List? { - return (transformPref(getString(key, options) as Any?) as List<*>?)?.filterIsInstance() + val value: List<*>? = transformPref(getString(key, options) as Any?, listEncoder) as List<*>? + return value?.filterIsInstance() } /** Gets all properties from data store. */ @@ -200,10 +208,10 @@ class SharedPreferencesPlugin() : FlutterPlugin, SharedPreferencesAsyncApi { val filteredMap = mutableMapOf() val keys = readAllKeys() - keys?.forEach() { key -> + keys?.forEach { key -> val value = getValueByKey(key) if (preferencesFilter(key.toString(), value, allowSet)) { - val transformedValue = transformPref(value) + val transformedValue = transformPref(value, listEncoder) if (transformedValue != null) { filteredMap[key.toString()] = transformedValue } @@ -221,45 +229,199 @@ class SharedPreferencesPlugin() : FlutterPlugin, SharedPreferencesAsyncApi { val value = context.sharedPreferencesDataStore.data.map { it[key] } return value.firstOrNull() } +} + +class SharedPreferencesBackend( + private var messenger: BinaryMessenger, + private var context: Context, + private var listEncoder: SharedPreferencesListEncoder = ListEncoder() +) : SharedPreferencesAsyncApi { + + init { + try { + SharedPreferencesAsyncApi.setUp(messenger, this, "shared_preferences") + } catch (ex: Exception) { + Log.e(TAG, "Received exception while setting up SharedPreferencesBackend", ex) + } + } + + fun tearDown() { + SharedPreferencesAsyncApi.setUp(messenger, null, "shared_preferences") + } - /** - * Returns false for any preferences that are not included in [allowList]. - * - * If no [allowList] is provided, instead returns false for any preferences that are not supported - * by shared_preferences. - */ - private fun preferencesFilter(key: String, value: Any?, allowList: Set?): Boolean { - if (allowList == null) { - return value is Boolean || value is Long || value is String || value is Double + private fun createSharedPreferences(options: SharedPreferencesPigeonOptions): SharedPreferences { + return if (options.fileName == null) { + PreferenceManager.getDefaultSharedPreferences(context) + } else { + context.getSharedPreferences(options.fileName, Context.MODE_PRIVATE) } + } + + /** Adds property to data store of type bool. */ + override fun setBool(key: String, value: Boolean, options: SharedPreferencesPigeonOptions) { + return createSharedPreferences(options).edit().putBoolean(key, value).apply() + } + + /** Adds property to data store of type String. */ + override fun setString(key: String, value: String, options: SharedPreferencesPigeonOptions) { + return createSharedPreferences(options).edit().putString(key, value).apply() + } + + /** Adds property to data store of type int. Converted to Long by pigeon, and saved as such. */ + override fun setInt(key: String, value: Long, options: SharedPreferencesPigeonOptions) { + return createSharedPreferences(options).edit().putLong(key, value).apply() + } + + /** Adds property to data store of type double. */ + override fun setDouble(key: String, value: Double, options: SharedPreferencesPigeonOptions) { + return createSharedPreferences(options).edit().putString(key, DOUBLE_PREFIX + value).apply() + } - return allowList.contains(key) + /** Adds property to data store of type List. */ + override fun setStringList( + key: String, + value: List, + options: SharedPreferencesPigeonOptions + ) { + val valueString = LIST_PREFIX + listEncoder.encode(value) + return createSharedPreferences(options).edit().putString(key, valueString).apply() } - /** Transforms preferences that are stored as Strings back to original type. */ - private fun transformPref(value: Any?): Any? { - if (value is String) { - if (value.startsWith(LIST_PREFIX)) { - return listEncoder.decode(value.substring(LIST_PREFIX.length)) + /** Removes all properties from data store. */ + override fun clear(allowList: List?, options: SharedPreferencesPigeonOptions) { + val preferences = createSharedPreferences(options) + val clearEditor: SharedPreferences.Editor = preferences.edit() + val allPrefs: Map = preferences.all + val filteredPrefs = ArrayList() + for (key in allPrefs.keys) { + if (preferencesFilter(key, allPrefs[key], allowList = allowList?.toSet())) { + filteredPrefs.add(key) } } - return value + for (key in filteredPrefs) { + clearEditor.remove(key) + } + return clearEditor.apply() } - /** Class that provides tools for encoding and decoding List to String and back. */ - class ListEncoder : SharedPreferencesListEncoder { - override fun encode(list: List): String { - val byteStream = ByteArrayOutputStream() - val stream = ObjectOutputStream(byteStream) - stream.writeObject(list) - stream.flush() - return Base64.encodeToString(byteStream.toByteArray(), 0) + /** Gets all properties from data store. */ + override fun getAll( + allowList: List?, + options: SharedPreferencesPigeonOptions + ): Map { + val preferences = createSharedPreferences(options) + val allPrefs: Map = preferences.all + val filteredPrefs = HashMap() + for (entry in allPrefs.entries) { + if (preferencesFilter(entry.key, entry.value, allowList = allowList?.toSet())) { + entry.value?.let { filteredPrefs.put(entry.key, transformPref(it, listEncoder) as Any) } + } + } + return filteredPrefs + } + + /** Gets int (as long) at [key] from data store. */ + override fun getInt(key: String, options: SharedPreferencesPigeonOptions): Long? { + val preferences = createSharedPreferences(options) + return if (preferences.contains(key)) { + preferences.getLong(key, 0) + } else { + null + } + } + + /** Gets bool at [key] from data store. */ + override fun getBool(key: String, options: SharedPreferencesPigeonOptions): Boolean? { + val preferences = createSharedPreferences(options) + return if (preferences.contains(key)) { + preferences.getBoolean(key, true) + } else { + null } + } + /** Gets double at [key] from data store. */ + override fun getDouble(key: String, options: SharedPreferencesPigeonOptions): Double? { + val preferences = createSharedPreferences(options) + return if (preferences.contains(key)) { + transformPref(preferences.getString(key, ""), listEncoder) as Double + } else { + null + } + } - override fun decode(listString: String): List { - val byteArray = Base64.decode(listString, 0) - val stream = StringListObjectInputStream(ByteArrayInputStream(byteArray)) - return (stream.readObject() as List<*>).filterIsInstance() + /** Gets String at [key] from data store. */ + override fun getString(key: String, options: SharedPreferencesPigeonOptions): String? { + val preferences = createSharedPreferences(options) + return if (preferences.contains(key)) { + preferences.getString(key, "") + } else { + null } } + + /** Gets StringList at [key] from data store. */ + override fun getStringList(key: String, options: SharedPreferencesPigeonOptions): List? { + val preferences = createSharedPreferences(options) + return if (preferences.contains(key)) { + (transformPref(preferences.getString(key, ""), listEncoder) as List<*>?)?.filterIsInstance< + String>() + } else { + null + } + } + + /** Gets all properties from data store. */ + override fun getKeys( + allowList: List?, + options: SharedPreferencesPigeonOptions + ): List { + val preferences = createSharedPreferences(options) + return preferences.all + .filter { preferencesFilter(it.key, it.value, allowList?.toSet()) } + .keys + .toList() + } +} + +/** + * Returns false for any preferences that are not included in [allowList]. + * + * If no [allowList] is provided, instead returns false for any preferences that are not supported + * by shared_preferences. + */ +internal fun preferencesFilter(key: String, value: Any?, allowList: Set?): Boolean { + if (allowList == null) { + return value is Boolean || value is Long || value is String || value is Double + } + + return allowList.contains(key) +} + +/** Transforms preferences that are stored as Strings back to original type. */ +internal fun transformPref(value: Any?, listEncoder: SharedPreferencesListEncoder): Any? { + if (value is String) { + if (value.startsWith(LIST_PREFIX)) { + return listEncoder.decode(value.substring(LIST_PREFIX.length)) + } else if (value.startsWith(DOUBLE_PREFIX)) { + return value.substring(DOUBLE_PREFIX.length).toDouble() + } + } + return value +} + +/** Class that provides tools for encoding and decoding List to String and back. */ +class ListEncoder : SharedPreferencesListEncoder { + override fun encode(list: List): String { + val byteStream = ByteArrayOutputStream() + val stream = ObjectOutputStream(byteStream) + stream.writeObject(list) + stream.flush() + return Base64.encodeToString(byteStream.toByteArray(), 0) + } + + override fun decode(listString: String): List { + val byteArray = Base64.decode(listString, 0) + val stream = StringListObjectInputStream(ByteArrayInputStream(byteArray)) + return (stream.readObject() as List<*>).filterIsInstance() + } } diff --git a/packages/shared_preferences/shared_preferences_android/android/src/test/kotlin/io/flutter/plugins/sharedpreferences/SharedPreferencesTest.kt b/packages/shared_preferences/shared_preferences_android/android/src/test/kotlin/io/flutter/plugins/sharedpreferences/SharedPreferencesTest.kt index ad5d6420ccec..1803138bc123 100644 --- a/packages/shared_preferences/shared_preferences_android/android/src/test/kotlin/io/flutter/plugins/sharedpreferences/SharedPreferencesTest.kt +++ b/packages/shared_preferences/shared_preferences_android/android/src/test/kotlin/io/flutter/plugins/sharedpreferences/SharedPreferencesTest.kt @@ -5,7 +5,9 @@ package io.flutter.plugins.sharedpreferences import android.content.Context +import android.content.SharedPreferences import android.util.Base64 +import androidx.preference.PreferenceManager import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import io.flutter.embedding.engine.plugins.FlutterPlugin @@ -41,98 +43,104 @@ internal class SharedPreferencesTest { private val testList = listOf("foo", "bar") - private val emptyOptions = SharedPreferencesPigeonOptions() - - private fun pluginSetup(): SharedPreferencesPlugin { - val testContext: Context = ApplicationProvider.getApplicationContext() + private val dataStoreOptions = SharedPreferencesPigeonOptions(useDataStore = true) + private val sharedPreferencesOptions = SharedPreferencesPigeonOptions(useDataStore = false) + private val testContext: Context = ApplicationProvider.getApplicationContext() + private fun pluginSetup(options: SharedPreferencesPigeonOptions): SharedPreferencesAsyncApi { val plugin = SharedPreferencesPlugin() val binaryMessenger = mockk() val flutterPluginBinding = mockk() every { flutterPluginBinding.binaryMessenger } returns binaryMessenger every { flutterPluginBinding.applicationContext } returns testContext plugin.onAttachedToEngine(flutterPluginBinding) - plugin.clear(null, emptyOptions) - return plugin + val backend = + SharedPreferencesBackend( + flutterPluginBinding.binaryMessenger, flutterPluginBinding.applicationContext) + return if (options.useDataStore) { + plugin + } else { + backend + } } @Test - fun testSetAndGetBool() { - val plugin = pluginSetup() - plugin.setBool(boolKey, testBool, emptyOptions) - Assert.assertEquals(plugin.getBool(boolKey, emptyOptions), testBool) + fun testSetAndGetBoolWithDataStore() { + val plugin = pluginSetup(dataStoreOptions) + plugin.setBool(boolKey, testBool, dataStoreOptions) + Assert.assertEquals(plugin.getBool(boolKey, dataStoreOptions), testBool) } @Test - fun testSetAndGetString() { - val plugin = pluginSetup() - plugin.setString(stringKey, testString, emptyOptions) - Assert.assertEquals(plugin.getString(stringKey, emptyOptions), testString) + fun testSetAndGetStringWithDataStore() { + val plugin = pluginSetup(dataStoreOptions) + plugin.setString(stringKey, testString, dataStoreOptions) + Assert.assertEquals(plugin.getString(stringKey, dataStoreOptions), testString) } @Test - fun testSetAndGetInt() { - val plugin = pluginSetup() - plugin.setInt(intKey, testInt, emptyOptions) - Assert.assertEquals(plugin.getInt(intKey, emptyOptions), testInt) + fun testSetAndGetIntWithDataStore() { + val plugin = pluginSetup(dataStoreOptions) + plugin.setInt(intKey, testInt, dataStoreOptions) + Assert.assertEquals(plugin.getInt(intKey, dataStoreOptions), testInt) } @Test - fun testSetAndGetDouble() { - val plugin = pluginSetup() - plugin.setDouble(doubleKey, testDouble, emptyOptions) - Assert.assertEquals(plugin.getDouble(doubleKey, emptyOptions), testDouble) + fun testSetAndGetDoubleWithDataStore() { + val plugin = pluginSetup(dataStoreOptions) + plugin.setDouble(doubleKey, testDouble, dataStoreOptions) + Assert.assertEquals(plugin.getDouble(doubleKey, dataStoreOptions), testDouble) } @Test - fun testSetAndGetStringList() { - val plugin = pluginSetup() - plugin.setStringList(listKey, testList, emptyOptions) - Assert.assertEquals(plugin.getStringList(listKey, emptyOptions), testList) + fun testSetAndGetStringListWithDataStore() { + val plugin = pluginSetup(dataStoreOptions) + plugin.setStringList(listKey, testList, dataStoreOptions) + Assert.assertEquals(plugin.getStringList(listKey, dataStoreOptions), testList) } @Test - fun testGetKeys() { - val plugin = pluginSetup() - plugin.setBool(boolKey, testBool, emptyOptions) - plugin.setString(stringKey, testString, emptyOptions) - plugin.setInt(intKey, testInt, emptyOptions) - plugin.setDouble(doubleKey, testDouble, emptyOptions) - plugin.setStringList(listKey, testList, emptyOptions) - val keyList = plugin.getKeys(listOf(boolKey, stringKey), emptyOptions) + fun testGetKeysWithDataStore() { + val plugin = pluginSetup(dataStoreOptions) + plugin.setBool(boolKey, testBool, dataStoreOptions) + plugin.setString(stringKey, testString, dataStoreOptions) + plugin.setInt(intKey, testInt, dataStoreOptions) + plugin.setDouble(doubleKey, testDouble, dataStoreOptions) + plugin.setStringList(listKey, testList, dataStoreOptions) + val keyList = plugin.getKeys(listOf(boolKey, stringKey), dataStoreOptions) Assert.assertEquals(keyList.size, 2) Assert.assertTrue(keyList.contains(stringKey)) Assert.assertTrue(keyList.contains(boolKey)) } @Test - fun testClear() { - val plugin = pluginSetup() - plugin.setBool(boolKey, testBool, emptyOptions) - plugin.setString(stringKey, testString, emptyOptions) - plugin.setInt(intKey, testInt, emptyOptions) - plugin.setDouble(doubleKey, testDouble, emptyOptions) - plugin.setStringList(listKey, testList, emptyOptions) - - plugin.clear(null, emptyOptions) - - Assert.assertNull(plugin.getBool(boolKey, emptyOptions)) - Assert.assertNull(plugin.getBool(stringKey, emptyOptions)) - Assert.assertNull(plugin.getBool(intKey, emptyOptions)) - Assert.assertNull(plugin.getBool(doubleKey, emptyOptions)) - Assert.assertNull(plugin.getBool(listKey, emptyOptions)) + fun testClearWithDataStore() { + val plugin = pluginSetup(dataStoreOptions) + plugin.setBool(boolKey, testBool, dataStoreOptions) + plugin.setString(stringKey, testString, dataStoreOptions) + plugin.setInt(intKey, testInt, dataStoreOptions) + plugin.setDouble(doubleKey, testDouble, dataStoreOptions) + plugin.setStringList(listKey, testList, dataStoreOptions) + + plugin.clear(null, dataStoreOptions) + + Assert.assertNull(plugin.getBool(boolKey, dataStoreOptions)) + Assert.assertNull(plugin.getBool(stringKey, dataStoreOptions)) + Assert.assertNull(plugin.getBool(intKey, dataStoreOptions)) + Assert.assertNull(plugin.getBool(doubleKey, dataStoreOptions)) + Assert.assertNull(plugin.getBool(listKey, dataStoreOptions)) } @Test - fun testGetAll() { - val plugin = pluginSetup() - plugin.setBool(boolKey, testBool, emptyOptions) - plugin.setString(stringKey, testString, emptyOptions) - plugin.setInt(intKey, testInt, emptyOptions) - plugin.setDouble(doubleKey, testDouble, emptyOptions) - plugin.setStringList(listKey, testList, emptyOptions) + fun testGetAllWithDataStore() { + val plugin = pluginSetup(dataStoreOptions) + plugin.setBool(boolKey, testBool, dataStoreOptions) + plugin.setString(stringKey, testString, dataStoreOptions) + plugin.setInt(intKey, testInt, dataStoreOptions) + plugin.setDouble(doubleKey, testDouble, dataStoreOptions) + plugin.setStringList(listKey, testList, dataStoreOptions) - val all = plugin.getAll(null, emptyOptions) + val all = plugin.getAll(null, dataStoreOptions) Assert.assertEquals(all[boolKey], testBool) Assert.assertEquals(all[stringKey], testString) @@ -142,33 +150,154 @@ internal class SharedPreferencesTest { } @Test - fun testClearWithAllowList() { - val plugin = pluginSetup() - plugin.setBool(boolKey, testBool, emptyOptions) - plugin.setString(stringKey, testString, emptyOptions) - plugin.setInt(intKey, testInt, emptyOptions) - plugin.setDouble(doubleKey, testDouble, emptyOptions) - plugin.setStringList(listKey, testList, emptyOptions) + fun testClearWithAllowListWithDataStore() { + val plugin = pluginSetup(dataStoreOptions) + plugin.setBool(boolKey, testBool, dataStoreOptions) + plugin.setString(stringKey, testString, dataStoreOptions) + plugin.setInt(intKey, testInt, dataStoreOptions) + plugin.setDouble(doubleKey, testDouble, dataStoreOptions) + plugin.setStringList(listKey, testList, dataStoreOptions) + + plugin.clear(listOf(boolKey, stringKey), dataStoreOptions) + + Assert.assertNull(plugin.getBool(boolKey, dataStoreOptions)) + Assert.assertNull(plugin.getString(stringKey, dataStoreOptions)) + Assert.assertNotNull(plugin.getInt(intKey, dataStoreOptions)) + Assert.assertNotNull(plugin.getDouble(doubleKey, dataStoreOptions)) + Assert.assertNotNull(plugin.getStringList(listKey, dataStoreOptions)) + } + + @Test + fun testGetAllWithAllowListWithDataStore() { + val plugin = pluginSetup(dataStoreOptions) + plugin.setBool(boolKey, testBool, dataStoreOptions) + plugin.setString(stringKey, testString, dataStoreOptions) + plugin.setInt(intKey, testInt, dataStoreOptions) + plugin.setDouble(doubleKey, testDouble, dataStoreOptions) + plugin.setStringList(listKey, testList, dataStoreOptions) + + val all = plugin.getAll(listOf(boolKey, stringKey), dataStoreOptions) + + Assert.assertEquals(all[boolKey], testBool) + Assert.assertEquals(all[stringKey], testString) + Assert.assertNull(all[intKey]) + Assert.assertNull(all[doubleKey]) + Assert.assertNull(all[listKey]) + } + + @Test + fun testSetAndGetBoolWithSharedPreferences() { + val plugin = pluginSetup(sharedPreferencesOptions) + plugin.setBool(boolKey, testBool, sharedPreferencesOptions) + Assert.assertEquals(plugin.getBool(boolKey, sharedPreferencesOptions), testBool) + } - plugin.clear(listOf(boolKey, stringKey), emptyOptions) + @Test + fun testSetAndGetStringWithSharedPreferences() { + val plugin = pluginSetup(sharedPreferencesOptions) + plugin.setString(stringKey, testString, sharedPreferencesOptions) + Assert.assertEquals(plugin.getString(stringKey, sharedPreferencesOptions), testString) + } - Assert.assertNull(plugin.getBool(boolKey, emptyOptions)) - Assert.assertNull(plugin.getString(stringKey, emptyOptions)) - Assert.assertNotNull(plugin.getInt(intKey, emptyOptions)) - Assert.assertNotNull(plugin.getDouble(doubleKey, emptyOptions)) - Assert.assertNotNull(plugin.getStringList(listKey, emptyOptions)) + @Test + fun testSetAndGetIntWithSharedPreferences() { + val plugin = pluginSetup(sharedPreferencesOptions) + plugin.setInt(intKey, testInt, sharedPreferencesOptions) + Assert.assertEquals(plugin.getInt(intKey, sharedPreferencesOptions), testInt) } @Test - fun testGetAllWithAllowList() { - val plugin = pluginSetup() - plugin.setBool(boolKey, testBool, emptyOptions) - plugin.setString(stringKey, testString, emptyOptions) - plugin.setInt(intKey, testInt, emptyOptions) - plugin.setDouble(doubleKey, testDouble, emptyOptions) - plugin.setStringList(listKey, testList, emptyOptions) + fun testSetAndGetDoubleWithSharedPreferences() { + val plugin = pluginSetup(sharedPreferencesOptions) + plugin.setDouble(doubleKey, testDouble, sharedPreferencesOptions) + Assert.assertEquals(plugin.getDouble(doubleKey, sharedPreferencesOptions), testDouble) + } - val all = plugin.getAll(listOf(boolKey, stringKey), emptyOptions) + @Test + fun testSetAndGetStringListWithSharedPreferences() { + val plugin = pluginSetup(sharedPreferencesOptions) + plugin.setStringList(listKey, testList, sharedPreferencesOptions) + Assert.assertEquals(plugin.getStringList(listKey, sharedPreferencesOptions), testList) + } + + @Test + fun testGetKeysWithSharedPreferences() { + val plugin = pluginSetup(sharedPreferencesOptions) + plugin.setBool(boolKey, testBool, sharedPreferencesOptions) + plugin.setString(stringKey, testString, sharedPreferencesOptions) + plugin.setInt(intKey, testInt, sharedPreferencesOptions) + plugin.setDouble(doubleKey, testDouble, sharedPreferencesOptions) + plugin.setStringList(listKey, testList, sharedPreferencesOptions) + val keyList = plugin.getKeys(listOf(boolKey, stringKey), sharedPreferencesOptions) + Assert.assertEquals(keyList.size, 2) + Assert.assertTrue(keyList.contains(stringKey)) + Assert.assertTrue(keyList.contains(boolKey)) + } + + @Test + fun testClearWithSharedPreferences() { + val plugin = pluginSetup(sharedPreferencesOptions) + plugin.setBool(boolKey, testBool, sharedPreferencesOptions) + plugin.setString(stringKey, testString, sharedPreferencesOptions) + plugin.setInt(intKey, testInt, sharedPreferencesOptions) + plugin.setDouble(doubleKey, testDouble, sharedPreferencesOptions) + plugin.setStringList(listKey, testList, sharedPreferencesOptions) + + plugin.clear(null, sharedPreferencesOptions) + + Assert.assertNull(plugin.getBool(boolKey, sharedPreferencesOptions)) + Assert.assertNull(plugin.getBool(stringKey, sharedPreferencesOptions)) + Assert.assertNull(plugin.getBool(intKey, sharedPreferencesOptions)) + Assert.assertNull(plugin.getBool(doubleKey, sharedPreferencesOptions)) + Assert.assertNull(plugin.getBool(listKey, sharedPreferencesOptions)) + } + + @Test + fun testGetAllWithSharedPreferences() { + val plugin = pluginSetup(sharedPreferencesOptions) + plugin.setBool(boolKey, testBool, sharedPreferencesOptions) + plugin.setString(stringKey, testString, sharedPreferencesOptions) + plugin.setInt(intKey, testInt, sharedPreferencesOptions) + plugin.setDouble(doubleKey, testDouble, sharedPreferencesOptions) + plugin.setStringList(listKey, testList, sharedPreferencesOptions) + + val all = plugin.getAll(null, sharedPreferencesOptions) + + Assert.assertEquals(all[boolKey], testBool) + Assert.assertEquals(all[stringKey], testString) + Assert.assertEquals(all[intKey], testInt) + Assert.assertEquals(all[doubleKey], testDouble) + Assert.assertEquals(all[listKey], testList) + } + + @Test + fun testClearWithAllowListWithSharedPreferences() { + val plugin = pluginSetup(sharedPreferencesOptions) + plugin.setBool(boolKey, testBool, sharedPreferencesOptions) + plugin.setString(stringKey, testString, sharedPreferencesOptions) + plugin.setInt(intKey, testInt, sharedPreferencesOptions) + plugin.setDouble(doubleKey, testDouble, sharedPreferencesOptions) + plugin.setStringList(listKey, testList, sharedPreferencesOptions) + + plugin.clear(listOf(boolKey, stringKey), sharedPreferencesOptions) + + Assert.assertNull(plugin.getBool(boolKey, sharedPreferencesOptions)) + Assert.assertNull(plugin.getString(stringKey, sharedPreferencesOptions)) + Assert.assertNotNull(plugin.getInt(intKey, sharedPreferencesOptions)) + Assert.assertNotNull(plugin.getDouble(doubleKey, sharedPreferencesOptions)) + Assert.assertNotNull(plugin.getStringList(listKey, sharedPreferencesOptions)) + } + + @Test + fun testGetAllWithAllowListWithSharedPreferences() { + val plugin = pluginSetup(sharedPreferencesOptions) + plugin.setBool(boolKey, testBool, sharedPreferencesOptions) + plugin.setString(stringKey, testString, sharedPreferencesOptions) + plugin.setInt(intKey, testInt, sharedPreferencesOptions) + plugin.setDouble(doubleKey, testDouble, sharedPreferencesOptions) + plugin.setStringList(listKey, testList, sharedPreferencesOptions) + + val all = plugin.getAll(listOf(boolKey, stringKey), sharedPreferencesOptions) Assert.assertEquals(all[boolKey], testBool) Assert.assertEquals(all[stringKey], testString) @@ -177,6 +306,26 @@ internal class SharedPreferencesTest { Assert.assertNull(all[listKey]) } + @Test + fun testSharedPreferencesWithMultipleFiles() { + val plugin = pluginSetup(sharedPreferencesOptions) + val optionsWithNewFile = + SharedPreferencesPigeonOptions(useDataStore = false, fileName = "test_file") + plugin.setInt(intKey, 1, sharedPreferencesOptions) + plugin.setInt(intKey, 2, optionsWithNewFile) + Assert.assertEquals(plugin.getInt(intKey, sharedPreferencesOptions), 1L) + Assert.assertEquals(plugin.getInt(intKey, optionsWithNewFile), 2L) + } + + @Test + fun testSharedPreferencesDefaultFile() { + val defaultPreferences: SharedPreferences = + PreferenceManager.getDefaultSharedPreferences(testContext) + defaultPreferences.edit().putString(stringKey, testString).commit() + val plugin = pluginSetup(sharedPreferencesOptions) + Assert.assertEquals(plugin.getString(stringKey, sharedPreferencesOptions), testString) + } + @Test fun testUnexpectedClassDecodeThrows() { // Only String should be allowed in an encoded list. @@ -188,12 +337,12 @@ internal class SharedPreferencesTest { stream.flush() val badPref = LIST_PREFIX + Base64.encodeToString(byteStream.toByteArray(), 0) - val plugin = pluginSetup() + val plugin = pluginSetup(dataStoreOptions) val badListKey = "badList" // Inject the bad pref as a string, as that is how string lists are stored internally. - plugin.setString(badListKey, badPref, emptyOptions) + plugin.setString(badListKey, badPref, dataStoreOptions) assertThrows(ClassNotFoundException::class.java) { - plugin.getStringList(badListKey, emptyOptions) + plugin.getStringList(badListKey, dataStoreOptions) } } } diff --git a/packages/shared_preferences/shared_preferences_android/example/android/.gitignore b/packages/shared_preferences/shared_preferences_android/example/android/.gitignore index 8e599af9f211..55afd919c659 100644 --- a/packages/shared_preferences/shared_preferences_android/example/android/.gitignore +++ b/packages/shared_preferences/shared_preferences_android/example/android/.gitignore @@ -9,3 +9,5 @@ GeneratedPluginRegistrant.java # Remember to never publicly share your keystore. # See https://flutter.dev/to/reference-keystore key.properties +**/*.keystore +**/*.jks diff --git a/packages/shared_preferences/shared_preferences_android/example/android/app/build.gradle b/packages/shared_preferences/shared_preferences_android/example/android/app/build.gradle index b2379b24950b..f59008b9173b 100644 --- a/packages/shared_preferences/shared_preferences_android/example/android/app/build.gradle +++ b/packages/shared_preferences/shared_preferences_android/example/android/app/build.gradle @@ -1,3 +1,16 @@ +buildscript { + ext.kotlin_version = '1.7.10' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:8.5.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + plugins { id "com.android.application" id "org.jetbrains.kotlin.android" @@ -23,15 +36,25 @@ if (flutterVersionName == null) { } android { - namespace 'io.flutter.plugins.sharedpreferencesexample' + namespace "dev.flutter.plugins.shared_preferences_example" compileSdk flutter.compileSdkVersion + ndkVersion flutter.ndkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = '11' + } sourceSets { main.java.srcDirs += 'src/main/kotlin' } defaultConfig { - applicationId "io.flutter.plugins.sharedpreferencesexample" + applicationId "dev.flutter.plugins.shared_preferences_example" minSdkVersion flutter.minSdkVersion targetSdkVersion 34 versionCode flutterVersionCode.toInteger() @@ -54,4 +77,11 @@ flutter { dependencies { implementation "androidx.datastore:datastore-preferences:1.0.0" + implementation 'androidx.preference:preference:1.2.1' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.espresso:espresso-intents:3.2.0' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test:rules:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + api 'androidx.test:core:1.4.0' } diff --git a/packages/shared_preferences/shared_preferences_android/example/android/app/src/androidTest/java/io/flutter/plugins/sharedpreferencesexample/MainActivityTest.java b/packages/shared_preferences/shared_preferences_android/example/android/app/src/androidTest/java/dev/flutter/plugins/shared_preferences_example/MainActivityTest.java similarity index 69% rename from packages/shared_preferences/shared_preferences_android/example/android/app/src/androidTest/java/io/flutter/plugins/sharedpreferencesexample/MainActivityTest.java rename to packages/shared_preferences/shared_preferences_android/example/android/app/src/androidTest/java/dev/flutter/plugins/shared_preferences_example/MainActivityTest.java index 304ee4c33326..20e13ab4115a 100644 --- a/packages/shared_preferences/shared_preferences_android/example/android/app/src/androidTest/java/io/flutter/plugins/sharedpreferencesexample/MainActivityTest.java +++ b/packages/shared_preferences/shared_preferences_android/example/android/app/src/androidTest/java/dev/flutter/plugins/shared_preferences_example/MainActivityTest.java @@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package io.flutter.plugins.sharedpreferences; +package dev.flutter.plugins.shared_preferences_example; import androidx.test.rule.ActivityTestRule; import dev.flutter.plugins.integration_test.FlutterTestRunner; -import io.flutter.embedding.android.FlutterActivity; import io.flutter.plugins.DartIntegrationTest; import org.junit.Rule; import org.junit.runner.RunWith; @@ -14,6 +13,5 @@ @DartIntegrationTest @RunWith(FlutterTestRunner.class) public class MainActivityTest { - @Rule - public ActivityTestRule rule = new ActivityTestRule<>(FlutterActivity.class); + @Rule public ActivityTestRule rule = new ActivityTestRule<>(MainActivity.class); } diff --git a/packages/shared_preferences/shared_preferences_android/example/android/app/src/debug/AndroidManifest.xml b/packages/shared_preferences/shared_preferences_android/example/android/app/src/debug/AndroidManifest.xml index d60d6f69a862..399f6981d5d3 100644 --- a/packages/shared_preferences/shared_preferences_android/example/android/app/src/debug/AndroidManifest.xml +++ b/packages/shared_preferences/shared_preferences_android/example/android/app/src/debug/AndroidManifest.xml @@ -1,6 +1,6 @@ - - diff --git a/packages/shared_preferences/shared_preferences_android/example/android/app/src/main/AndroidManifest.xml b/packages/shared_preferences/shared_preferences_android/example/android/app/src/main/AndroidManifest.xml index 4288e93f875d..1300cc597640 100644 --- a/packages/shared_preferences/shared_preferences_android/example/android/app/src/main/AndroidManifest.xml +++ b/packages/shared_preferences/shared_preferences_android/example/android/app/src/main/AndroidManifest.xml @@ -1,10 +1,10 @@ - - + - diff --git a/packages/shared_preferences/shared_preferences_android/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/shared_preferences/shared_preferences_android/example/android/gradle/wrapper/gradle-wrapper.properties index b9150adbf128..3c85cfe057a1 100644 --- a/packages/shared_preferences/shared_preferences_android/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/shared_preferences/shared_preferences_android/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Wed Jan 17 19:21:34 PST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip diff --git a/packages/shared_preferences/shared_preferences_android/example/android/settings.gradle b/packages/shared_preferences/shared_preferences_android/example/android/settings.gradle index d056e4db3665..74d52ff12f4f 100644 --- a/packages/shared_preferences/shared_preferences_android/example/android/settings.gradle +++ b/packages/shared_preferences/shared_preferences_android/example/android/settings.gradle @@ -19,7 +19,7 @@ pluginManagement { // See https://github.com/flutter/flutter/blob/master/docs/ecosystem/Plugins-and-Packages-repository-structure.md#gradle-structure for more info. plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.5.1" apply false + id "com.android.application" version "8.5.2" apply false id "org.jetbrains.kotlin.android" version "1.9.0" apply false id "com.google.cloud.artifactregistry.gradle-plugin" version "2.2.1" } diff --git a/packages/shared_preferences/shared_preferences_android/example/integration_test/shared_preferences_test.dart b/packages/shared_preferences/shared_preferences_android/example/integration_test/shared_preferences_test.dart index 48f451d20a1f..0335b00968b8 100644 --- a/packages/shared_preferences/shared_preferences_android/example/integration_test/shared_preferences_test.dart +++ b/packages/shared_preferences/shared_preferences_android/example/integration_test/shared_preferences_test.dart @@ -495,208 +495,299 @@ void main() { }); }); - group('shared_preferences_async', () { - const SharedPreferencesAsyncAndroidOptions emptyOptions = - SharedPreferencesAsyncAndroidOptions(); - - const String stringKey = 'testString'; - const String boolKey = 'testBool'; - const String intKey = 'testInt'; - const String doubleKey = 'testDouble'; - const String listKey = 'testList'; - - const String testString = 'hello world'; - const bool testBool = true; - const int testInt = 42; - const double testDouble = 3.14159; - const List testList = ['foo', 'bar']; - - Future getPreferences() async { - final SharedPreferencesAsyncPlatform preferences = - SharedPreferencesAsyncPlatform.instance!; - await preferences.clear( - const ClearPreferencesParameters(filter: PreferencesFilters()), - emptyOptions); - return preferences; - } - - testWidgets('set and get String', (WidgetTester _) async { - final SharedPreferencesAsyncPlatform preferences = await getPreferences(); - - await preferences.setString(stringKey, testString, emptyOptions); - expect(await preferences.getString(stringKey, emptyOptions), testString); - }); + const String stringKey = 'testString'; + const String boolKey = 'testBool'; + const String intKey = 'testInt'; + const String doubleKey = 'testDouble'; + const String listKey = 'testList'; + + const String testString = 'hello world'; + const bool testBool = true; + const int testInt = 42; + const double testDouble = 3.14159; + const List testList = ['foo', 'bar']; + + SharedPreferencesAsyncAndroidOptions getOptions({ + required bool useDataStore, + String? fileName, + }) { + return SharedPreferencesAsyncAndroidOptions( + backend: useDataStore + ? SharedPreferencesAndroidBackendLibrary.DataStore + : SharedPreferencesAndroidBackendLibrary.SharedPreferences, + originalSharedPreferencesOptions: fileName == null + ? null + : AndroidSharedPreferencesStoreOptions(fileName: fileName), + ); + } + + Future clearPreferences( + SharedPreferencesAsyncPlatform preferences, + SharedPreferencesAsyncAndroidOptions options, + ) async { + await preferences.clear( + const ClearPreferencesParameters(filter: PreferencesFilters()), + options); + } + + SharedPreferencesAsyncPlatform getPreferences() { + final SharedPreferencesAsyncPlatform preferences = + SharedPreferencesAsyncPlatform.instance!; + return preferences; + } + + void runAsyncTests(bool useDataStore) { + group('shared_preferences_async', () { + final String backend = useDataStore ? 'DataStore' : 'SharedPreferences'; + + testWidgets('set and get String with $backend', (WidgetTester _) async { + final SharedPreferencesAsyncAndroidOptions options = + getOptions(useDataStore: useDataStore, fileName: 'notDefault'); + final SharedPreferencesAsyncPlatform preferences = getPreferences(); + await clearPreferences(preferences, options); + + await preferences.setString(stringKey, testString, options); + expect(await preferences.getString(stringKey, options), testString); + }); - testWidgets('set and get bool', (WidgetTester _) async { - final SharedPreferencesAsyncPlatform preferences = await getPreferences(); + testWidgets('set and get bool with $backend', (WidgetTester _) async { + final SharedPreferencesAsyncAndroidOptions options = + getOptions(useDataStore: useDataStore, fileName: 'notDefault'); + final SharedPreferencesAsyncPlatform preferences = getPreferences(); + await clearPreferences(preferences, options); - await preferences.setBool(boolKey, testBool, emptyOptions); - expect(await preferences.getBool(boolKey, emptyOptions), testBool); - }); + await preferences.setBool(boolKey, testBool, options); + expect(await preferences.getBool(boolKey, options), testBool); + }); - testWidgets('set and get int', (WidgetTester _) async { - final SharedPreferencesAsyncPlatform preferences = await getPreferences(); + testWidgets('set and get int with $backend', (WidgetTester _) async { + final SharedPreferencesAsyncAndroidOptions options = + getOptions(useDataStore: useDataStore, fileName: 'notDefault'); + final SharedPreferencesAsyncPlatform preferences = getPreferences(); + await clearPreferences(preferences, options); - await preferences.setInt(intKey, testInt, emptyOptions); - expect(await preferences.getInt(intKey, emptyOptions), testInt); - }); + await preferences.setInt(intKey, testInt, options); + expect(await preferences.getInt(intKey, options), testInt); + }); - testWidgets('set and get double', (WidgetTester _) async { - final SharedPreferencesAsyncPlatform preferences = await getPreferences(); + testWidgets('set and get double with $backend', (WidgetTester _) async { + final SharedPreferencesAsyncAndroidOptions options = + getOptions(useDataStore: useDataStore, fileName: 'notDefault'); + final SharedPreferencesAsyncPlatform preferences = getPreferences(); + await clearPreferences(preferences, options); - await preferences.setDouble(doubleKey, testDouble, emptyOptions); - expect(await preferences.getDouble(doubleKey, emptyOptions), testDouble); - }); + await preferences.setDouble(doubleKey, testDouble, options); + expect(await preferences.getDouble(doubleKey, options), testDouble); + }); - testWidgets('set and get StringList', (WidgetTester _) async { - final SharedPreferencesAsyncPlatform preferences = await getPreferences(); + testWidgets('set and get StringList with $backend', + (WidgetTester _) async { + final SharedPreferencesAsyncAndroidOptions options = + getOptions(useDataStore: useDataStore, fileName: 'notDefault'); + final SharedPreferencesAsyncPlatform preferences = getPreferences(); + await clearPreferences(preferences, options); - await preferences.setStringList(listKey, testList, emptyOptions); - expect(await preferences.getStringList(listKey, emptyOptions), testList); - }); + await preferences.setStringList(listKey, testList, options); + expect(await preferences.getStringList(listKey, options), testList); + }); - testWidgets('getStringList returns mutable list', (WidgetTester _) async { - final SharedPreferencesAsyncPlatform preferences = await getPreferences(); + testWidgets('getStringList returns mutable list with $backend', + (WidgetTester _) async { + final SharedPreferencesAsyncAndroidOptions options = + getOptions(useDataStore: useDataStore, fileName: 'notDefault'); + final SharedPreferencesAsyncPlatform preferences = getPreferences(); + await clearPreferences(preferences, options); + + await preferences.setStringList(listKey, testList, options); + final List? list = + await preferences.getStringList(listKey, options); + list?.add('value'); + expect(list?.length, testList.length + 1); + }); - await preferences.setStringList(listKey, testList, emptyOptions); - final List? list = - await preferences.getStringList(listKey, emptyOptions); - list?.add('value'); - expect(list?.length, testList.length + 1); - }); + testWidgets('getPreferences with $backend', (WidgetTester _) async { + final SharedPreferencesAsyncAndroidOptions options = + getOptions(useDataStore: useDataStore, fileName: 'notDefault'); + final SharedPreferencesAsyncPlatform preferences = getPreferences(); + await clearPreferences(preferences, options); + await Future.wait(>[ + preferences.setString(stringKey, testString, options), + preferences.setBool(boolKey, testBool, options), + preferences.setInt(intKey, testInt, options), + preferences.setDouble(doubleKey, testDouble, options), + preferences.setStringList(listKey, testList, options) + ]); - testWidgets('getPreferences', (WidgetTester _) async { - final SharedPreferencesAsyncPlatform preferences = await getPreferences(); - await Future.wait(>[ - preferences.setString(stringKey, testString, emptyOptions), - preferences.setBool(boolKey, testBool, emptyOptions), - preferences.setInt(intKey, testInt, emptyOptions), - preferences.setDouble(doubleKey, testDouble, emptyOptions), - preferences.setStringList(listKey, testList, emptyOptions) - ]); + final Map gotAll = await preferences.getPreferences( + const GetPreferencesParameters(filter: PreferencesFilters()), + options, + ); - final Map gotAll = await preferences.getPreferences( - const GetPreferencesParameters(filter: PreferencesFilters()), - emptyOptions, - ); + expect(gotAll.length, 5); + expect(gotAll[stringKey], testString); + expect(gotAll[boolKey], testBool); + expect(gotAll[intKey], testInt); + expect(gotAll[doubleKey], testDouble); + expect(gotAll[listKey], testList); + }); - expect(gotAll.length, 5); - expect(gotAll[stringKey], testString); - expect(gotAll[boolKey], testBool); - expect(gotAll[intKey], testInt); - expect(gotAll[doubleKey], testDouble); - expect(gotAll[listKey], testList); - }); + testWidgets('getPreferences with filter with $backend', + (WidgetTester _) async { + final SharedPreferencesAsyncAndroidOptions options = + getOptions(useDataStore: useDataStore, fileName: 'notDefault'); + final SharedPreferencesAsyncPlatform preferences = getPreferences(); + await clearPreferences(preferences, options); + await Future.wait(>[ + preferences.setString(stringKey, testString, options), + preferences.setBool(boolKey, testBool, options), + preferences.setInt(intKey, testInt, options), + preferences.setDouble(doubleKey, testDouble, options), + preferences.setStringList(listKey, testList, options) + ]); - testWidgets('getPreferences with filter', (WidgetTester _) async { - final SharedPreferencesAsyncPlatform preferences = await getPreferences(); - await Future.wait(>[ - preferences.setString(stringKey, testString, emptyOptions), - preferences.setBool(boolKey, testBool, emptyOptions), - preferences.setInt(intKey, testInt, emptyOptions), - preferences.setDouble(doubleKey, testDouble, emptyOptions), - preferences.setStringList(listKey, testList, emptyOptions) - ]); + final Map gotAll = await preferences.getPreferences( + const GetPreferencesParameters( + filter: PreferencesFilters(allowList: {stringKey, boolKey}), + ), + options, + ); - final Map gotAll = await preferences.getPreferences( - const GetPreferencesParameters( - filter: PreferencesFilters(allowList: {stringKey, boolKey}), - ), - emptyOptions, - ); + expect(gotAll.length, 2); + expect(gotAll[stringKey], testString); + expect(gotAll[boolKey], testBool); + }); - expect(gotAll.length, 2); - expect(gotAll[stringKey], testString); - expect(gotAll[boolKey], testBool); - }); + testWidgets('getKeys with $backend', (WidgetTester _) async { + final SharedPreferencesAsyncAndroidOptions options = + getOptions(useDataStore: useDataStore, fileName: 'notDefault'); + final SharedPreferencesAsyncPlatform preferences = getPreferences(); + await clearPreferences(preferences, options); + await Future.wait(>[ + preferences.setString(stringKey, testString, options), + preferences.setBool(boolKey, testBool, options), + preferences.setInt(intKey, testInt, options), + preferences.setDouble(doubleKey, testDouble, options), + preferences.setStringList(listKey, testList, options) + ]); - testWidgets('getKeys', (WidgetTester _) async { - final SharedPreferencesAsyncPlatform preferences = await getPreferences(); - await Future.wait(>[ - preferences.setString(stringKey, testString, emptyOptions), - preferences.setBool(boolKey, testBool, emptyOptions), - preferences.setInt(intKey, testInt, emptyOptions), - preferences.setDouble(doubleKey, testDouble, emptyOptions), - preferences.setStringList(listKey, testList, emptyOptions) - ]); + final Set keys = await preferences.getKeys( + const GetPreferencesParameters(filter: PreferencesFilters()), + options, + ); - final Set keys = await preferences.getKeys( - const GetPreferencesParameters(filter: PreferencesFilters()), - emptyOptions, - ); + expect(keys.length, 5); + expect(keys, contains(stringKey)); + expect(keys, contains(boolKey)); + expect(keys, contains(intKey)); + expect(keys, contains(doubleKey)); + expect(keys, contains(listKey)); + }); - expect(keys.length, 5); - expect(keys, contains(stringKey)); - expect(keys, contains(boolKey)); - expect(keys, contains(intKey)); - expect(keys, contains(doubleKey)); - expect(keys, contains(listKey)); - }); + testWidgets('getKeys with filter with $backend', (WidgetTester _) async { + final SharedPreferencesAsyncAndroidOptions options = + getOptions(useDataStore: useDataStore, fileName: 'notDefault'); + final SharedPreferencesAsyncPlatform preferences = getPreferences(); + await clearPreferences(preferences, options); + await Future.wait(>[ + preferences.setString(stringKey, testString, options), + preferences.setBool(boolKey, testBool, options), + preferences.setInt(intKey, testInt, options), + preferences.setDouble(doubleKey, testDouble, options), + preferences.setStringList(listKey, testList, options) + ]); - testWidgets('getKeys with filter', (WidgetTester _) async { - final SharedPreferencesAsyncPlatform preferences = await getPreferences(); - await Future.wait(>[ - preferences.setString(stringKey, testString, emptyOptions), - preferences.setBool(boolKey, testBool, emptyOptions), - preferences.setInt(intKey, testInt, emptyOptions), - preferences.setDouble(doubleKey, testDouble, emptyOptions), - preferences.setStringList(listKey, testList, emptyOptions) - ]); + final Set keys = await preferences.getKeys( + const GetPreferencesParameters( + filter: PreferencesFilters(allowList: {stringKey, boolKey}), + ), + options, + ); - final Set keys = await preferences.getKeys( - const GetPreferencesParameters( - filter: PreferencesFilters(allowList: {stringKey, boolKey}), - ), - emptyOptions, - ); + expect(keys.length, 2); + expect(keys, contains(stringKey)); + expect(keys, contains(boolKey)); + }); - expect(keys.length, 2); - expect(keys, contains(stringKey)); - expect(keys, contains(boolKey)); - }); + testWidgets('clear with $backend', (WidgetTester _) async { + final SharedPreferencesAsyncAndroidOptions options = + getOptions(useDataStore: useDataStore, fileName: 'notDefault'); + final SharedPreferencesAsyncPlatform preferences = getPreferences(); + await clearPreferences(preferences, options); + await Future.wait(>[ + preferences.setString(stringKey, testString, options), + preferences.setBool(boolKey, testBool, options), + preferences.setInt(intKey, testInt, options), + preferences.setDouble(doubleKey, testDouble, options), + preferences.setStringList(listKey, testList, options) + ]); - testWidgets('clear', (WidgetTester _) async { - final SharedPreferencesAsyncPlatform preferences = await getPreferences(); - await Future.wait(>[ - preferences.setString(stringKey, testString, emptyOptions), - preferences.setBool(boolKey, testBool, emptyOptions), - preferences.setInt(intKey, testInt, emptyOptions), - preferences.setDouble(doubleKey, testDouble, emptyOptions), - preferences.setStringList(listKey, testList, emptyOptions) - ]); + await preferences.clear( + const ClearPreferencesParameters(filter: PreferencesFilters()), + options, + ); - await preferences.clear( - const ClearPreferencesParameters(filter: PreferencesFilters()), - emptyOptions, - ); + expect(await preferences.getString(stringKey, options), null); + expect(await preferences.getBool(boolKey, options), null); + expect(await preferences.getInt(intKey, options), null); + expect(await preferences.getDouble(doubleKey, options), null); + expect(await preferences.getStringList(listKey, options), null); + }); - expect(await preferences.getString(stringKey, emptyOptions), null); - expect(await preferences.getBool(boolKey, emptyOptions), null); - expect(await preferences.getInt(intKey, emptyOptions), null); - expect(await preferences.getDouble(doubleKey, emptyOptions), null); - expect(await preferences.getStringList(listKey, emptyOptions), null); + testWidgets('clear with filter with $backend', (WidgetTester _) async { + final SharedPreferencesAsyncAndroidOptions options = + getOptions(useDataStore: useDataStore, fileName: 'notDefault'); + final SharedPreferencesAsyncPlatform preferences = getPreferences(); + await clearPreferences(preferences, options); + await Future.wait(>[ + preferences.setString(stringKey, testString, options), + preferences.setBool(boolKey, testBool, options), + preferences.setInt(intKey, testInt, options), + preferences.setDouble(doubleKey, testDouble, options), + preferences.setStringList(listKey, testList, options) + ]); + await preferences.clear( + const ClearPreferencesParameters( + filter: PreferencesFilters(allowList: {stringKey, boolKey}), + ), + options, + ); + expect(await preferences.getString(stringKey, options), null); + expect(await preferences.getBool(boolKey, options), null); + expect(await preferences.getInt(intKey, options), testInt); + expect(await preferences.getDouble(doubleKey, options), testDouble); + expect(await preferences.getStringList(listKey, options), testList); + }); }); + } + + runAsyncTests(true); + runAsyncTests(false); + + testWidgets('Shared Preferences works with multiple files', + (WidgetTester _) async { + final SharedPreferencesAsyncAndroidOptions options1 = + getOptions(useDataStore: false, fileName: 'file1'); + final SharedPreferencesAsyncAndroidOptions options2 = + getOptions(useDataStore: false, fileName: 'file2'); + final SharedPreferencesAsyncPlatform preferences = getPreferences(); + await clearPreferences(preferences, options1); + await clearPreferences(preferences, options2); + + await preferences.setInt(intKey, 1, options1); + await preferences.setInt(intKey, 2, options2); + expect(await preferences.getInt(intKey, options1), 1); + expect(await preferences.getInt(intKey, options2), 2); + }); - testWidgets('clear with filter', (WidgetTester _) async { - final SharedPreferencesAsyncPlatform preferences = await getPreferences(); - await Future.wait(>[ - preferences.setString(stringKey, testString, emptyOptions), - preferences.setBool(boolKey, testBool, emptyOptions), - preferences.setInt(intKey, testInt, emptyOptions), - preferences.setDouble(doubleKey, testDouble, emptyOptions), - preferences.setStringList(listKey, testList, emptyOptions) - ]); - await preferences.clear( - const ClearPreferencesParameters( - filter: PreferencesFilters(allowList: {stringKey, boolKey}), - ), - emptyOptions, - ); - expect(await preferences.getString(stringKey, emptyOptions), null); - expect(await preferences.getBool(boolKey, emptyOptions), null); - expect(await preferences.getInt(intKey, emptyOptions), testInt); - expect(await preferences.getDouble(doubleKey, emptyOptions), testDouble); - expect(await preferences.getStringList(listKey, emptyOptions), testList); - }); + testWidgets('Shared Preferences can read default sharedPreferences', + (WidgetTester _) async { + final SharedPreferencesAsyncAndroidOptions options = + getOptions(useDataStore: false); + final SharedPreferencesAsyncPlatform preferences = getPreferences(); + + expect( + await preferences.getString( + 'thisStringIsWrittenInTheExampleAppJavaCode', options), + 'testString'); }); } diff --git a/packages/shared_preferences/shared_preferences_android/example/lib/main.dart b/packages/shared_preferences/shared_preferences_android/example/lib/main.dart index 5bf8d0609204..e4a0e2121f23 100644 --- a/packages/shared_preferences/shared_preferences_android/example/lib/main.dart +++ b/packages/shared_preferences/shared_preferences_android/example/lib/main.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// ignore_for_file: public_member_api_docs +// ignore_for_file: public_member_api_docs, unreachable_from_main import 'package:flutter/material.dart'; import 'package:shared_preferences_android/shared_preferences_android.dart'; @@ -12,6 +12,14 @@ void main() { runApp(const MyApp()); } +// #docregion Android_Options +const SharedPreferencesAsyncAndroidOptions options = + SharedPreferencesAsyncAndroidOptions( + backend: SharedPreferencesAndroidBackendLibrary.SharedPreferences, + originalSharedPreferencesOptions: AndroidSharedPreferencesStoreOptions( + fileName: 'the_name_of_a_file')); +// #enddocregion Android_Options + class MyApp extends StatelessWidget { const MyApp({super.key}); diff --git a/packages/shared_preferences/shared_preferences_android/lib/src/messages_async.g.dart b/packages/shared_preferences/shared_preferences_android/lib/src/messages_async.g.dart index d355cfd916dd..c21b49cca96f 100644 --- a/packages/shared_preferences/shared_preferences_android/lib/src/messages_async.g.dart +++ b/packages/shared_preferences/shared_preferences_android/lib/src/messages_async.g.dart @@ -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 (v16.0.5), do not edit directly. +// Autogenerated from Pigeon (v22.6.1), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers @@ -20,31 +20,39 @@ PlatformException _createConnectionError(String channelName) { class SharedPreferencesPigeonOptions { SharedPreferencesPigeonOptions({ - this.fileKey, + this.fileName, + this.useDataStore = true, }); - String? fileKey; + String? fileName; + + bool useDataStore; Object encode() { return [ - fileKey, + fileName, + useDataStore, ]; } static SharedPreferencesPigeonOptions decode(Object result) { result as List; return SharedPreferencesPigeonOptions( - fileKey: result[0] as String?, + fileName: result[0] as String?, + useDataStore: result[1]! as bool, ); } } -class _SharedPreferencesAsyncApiCodec extends StandardMessageCodec { - const _SharedPreferencesAsyncApiCodec(); +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { - if (value is SharedPreferencesPigeonOptions) { - buffer.putUint8(128); + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else if (value is SharedPreferencesPigeonOptions) { + buffer.putUint8(129); writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); @@ -54,7 +62,7 @@ class _SharedPreferencesAsyncApiCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: + case 129: return SharedPreferencesPigeonOptions.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -66,33 +74,37 @@ class SharedPreferencesAsyncApi { /// Constructor for [SharedPreferencesAsyncApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - SharedPreferencesAsyncApi({BinaryMessenger? binaryMessenger}) - : __pigeon_binaryMessenger = binaryMessenger; - final BinaryMessenger? __pigeon_binaryMessenger; + SharedPreferencesAsyncApi( + {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + final BinaryMessenger? pigeonVar_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - static const MessageCodec pigeonChannelCodec = - _SharedPreferencesAsyncApiCodec(); + final String pigeonVar_messageChannelSuffix; /// Adds property to shared preferences data set of type bool. Future setBool( String key, bool value, SharedPreferencesPigeonOptions options) async { - const String __pigeon_channelName = - 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setBool'; - final BasicMessageChannel __pigeon_channel = + final String pigeonVar_channelName = + 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setBool$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - __pigeon_channelName, + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? __pigeon_replyList = await __pigeon_channel + final List? pigeonVar_replyList = await pigeonVar_channel .send([key, value, options]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], ); } else { return; @@ -102,23 +114,23 @@ class SharedPreferencesAsyncApi { /// Adds property to shared preferences data set of type String. Future setString( String key, String value, SharedPreferencesPigeonOptions options) async { - const String __pigeon_channelName = - 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setString'; - final BasicMessageChannel __pigeon_channel = + final String pigeonVar_channelName = + 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setString$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - __pigeon_channelName, + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? __pigeon_replyList = await __pigeon_channel + final List? pigeonVar_replyList = await pigeonVar_channel .send([key, value, options]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], ); } else { return; @@ -128,23 +140,23 @@ class SharedPreferencesAsyncApi { /// Adds property to shared preferences data set of type int. Future setInt( String key, int value, SharedPreferencesPigeonOptions options) async { - const String __pigeon_channelName = - 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setInt'; - final BasicMessageChannel __pigeon_channel = + final String pigeonVar_channelName = + 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setInt$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - __pigeon_channelName, + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? __pigeon_replyList = await __pigeon_channel + final List? pigeonVar_replyList = await pigeonVar_channel .send([key, value, options]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], ); } else { return; @@ -154,23 +166,23 @@ class SharedPreferencesAsyncApi { /// Adds property to shared preferences data set of type double. Future setDouble( String key, double value, SharedPreferencesPigeonOptions options) async { - const String __pigeon_channelName = - 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setDouble'; - final BasicMessageChannel __pigeon_channel = + final String pigeonVar_channelName = + 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setDouble$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - __pigeon_channelName, + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? __pigeon_replyList = await __pigeon_channel + final List? pigeonVar_replyList = await pigeonVar_channel .send([key, value, options]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], ); } else { return; @@ -178,25 +190,25 @@ class SharedPreferencesAsyncApi { } /// Adds property to shared preferences data set of type List. - Future setStringList(String key, List value, + Future setStringList(String key, List value, SharedPreferencesPigeonOptions options) async { - const String __pigeon_channelName = - 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setStringList'; - final BasicMessageChannel __pigeon_channel = + final String pigeonVar_channelName = + 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.setStringList$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - __pigeon_channelName, + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? __pigeon_replyList = await __pigeon_channel + final List? pigeonVar_replyList = await pigeonVar_channel .send([key, value, options]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], ); } else { return; @@ -206,153 +218,153 @@ class SharedPreferencesAsyncApi { /// Gets individual String value stored with [key], if any. Future getString( String key, SharedPreferencesPigeonOptions options) async { - const String __pigeon_channelName = - 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getString'; - final BasicMessageChannel __pigeon_channel = + final String pigeonVar_channelName = + 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getString$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - __pigeon_channelName, + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? __pigeon_replyList = - await __pigeon_channel.send([key, options]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { + final List? pigeonVar_replyList = + await pigeonVar_channel.send([key, options]) as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], ); } else { - return (__pigeon_replyList[0] as String?); + return (pigeonVar_replyList[0] as String?); } } /// Gets individual void value stored with [key], if any. Future getBool( String key, SharedPreferencesPigeonOptions options) async { - const String __pigeon_channelName = - 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getBool'; - final BasicMessageChannel __pigeon_channel = + final String pigeonVar_channelName = + 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getBool$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - __pigeon_channelName, + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? __pigeon_replyList = - await __pigeon_channel.send([key, options]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { + final List? pigeonVar_replyList = + await pigeonVar_channel.send([key, options]) as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], ); } else { - return (__pigeon_replyList[0] as bool?); + return (pigeonVar_replyList[0] as bool?); } } /// Gets individual double value stored with [key], if any. Future getDouble( String key, SharedPreferencesPigeonOptions options) async { - const String __pigeon_channelName = - 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getDouble'; - final BasicMessageChannel __pigeon_channel = + final String pigeonVar_channelName = + 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getDouble$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - __pigeon_channelName, + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? __pigeon_replyList = - await __pigeon_channel.send([key, options]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { + final List? pigeonVar_replyList = + await pigeonVar_channel.send([key, options]) as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], ); } else { - return (__pigeon_replyList[0] as double?); + return (pigeonVar_replyList[0] as double?); } } /// Gets individual int value stored with [key], if any. Future getInt( String key, SharedPreferencesPigeonOptions options) async { - const String __pigeon_channelName = - 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getInt'; - final BasicMessageChannel __pigeon_channel = + final String pigeonVar_channelName = + 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getInt$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - __pigeon_channelName, + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? __pigeon_replyList = - await __pigeon_channel.send([key, options]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { + final List? pigeonVar_replyList = + await pigeonVar_channel.send([key, options]) as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], ); } else { - return (__pigeon_replyList[0] as int?); + return (pigeonVar_replyList[0] as int?); } } /// Gets individual List value stored with [key], if any. - Future?> getStringList( + Future?> getStringList( String key, SharedPreferencesPigeonOptions options) async { - const String __pigeon_channelName = - 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getStringList'; - final BasicMessageChannel __pigeon_channel = + final String pigeonVar_channelName = + 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getStringList$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - __pigeon_channelName, + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? __pigeon_replyList = - await __pigeon_channel.send([key, options]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { + final List? pigeonVar_replyList = + await pigeonVar_channel.send([key, options]) as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], ); } else { - return (__pigeon_replyList[0] as List?)?.cast(); + return (pigeonVar_replyList[0] as List?)?.cast(); } } /// Removes all properties from shared preferences data set with matching prefix. Future clear( - List? allowList, SharedPreferencesPigeonOptions options) async { - const String __pigeon_channelName = - 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.clear'; - final BasicMessageChannel __pigeon_channel = + List? allowList, SharedPreferencesPigeonOptions options) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.clear$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - __pigeon_channelName, + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? __pigeon_replyList = await __pigeon_channel + final List? pigeonVar_replyList = await pigeonVar_channel .send([allowList, options]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], ); } else { return; @@ -360,65 +372,65 @@ class SharedPreferencesAsyncApi { } /// Gets all properties from shared preferences data set with matching prefix. - Future> getAll( - List? allowList, SharedPreferencesPigeonOptions options) async { - const String __pigeon_channelName = - 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getAll'; - final BasicMessageChannel __pigeon_channel = + Future> getAll( + List? allowList, SharedPreferencesPigeonOptions options) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getAll$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - __pigeon_channelName, + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? __pigeon_replyList = await __pigeon_channel + final List? pigeonVar_replyList = await pigeonVar_channel .send([allowList, options]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], ); - } else if (__pigeon_replyList[0] == null) { + } else if (pigeonVar_replyList[0] == null) { throw PlatformException( code: 'null-error', message: 'Host platform returned null value for non-null return value.', ); } else { - return (__pigeon_replyList[0] as Map?)! - .cast(); + return (pigeonVar_replyList[0] as Map?)! + .cast(); } } /// Gets all properties from shared preferences data set with matching prefix. - Future> getKeys( - List? allowList, SharedPreferencesPigeonOptions options) async { - const String __pigeon_channelName = - 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getKeys'; - final BasicMessageChannel __pigeon_channel = + Future> getKeys( + List? allowList, SharedPreferencesPigeonOptions options) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.shared_preferences_android.SharedPreferencesAsyncApi.getKeys$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - __pigeon_channelName, + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? __pigeon_replyList = await __pigeon_channel + final List? pigeonVar_replyList = await pigeonVar_channel .send([allowList, options]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], ); - } else if (__pigeon_replyList[0] == null) { + } else if (pigeonVar_replyList[0] == null) { throw PlatformException( code: 'null-error', message: 'Host platform returned null value for non-null return value.', ); } else { - return (__pigeon_replyList[0] as List?)!.cast(); + return (pigeonVar_replyList[0] as List?)!.cast(); } } } diff --git a/packages/shared_preferences/shared_preferences_android/lib/src/shared_preferences_async_android.dart b/packages/shared_preferences/shared_preferences_android/lib/src/shared_preferences_async_android.dart index 7b3f1cb7b352..2b6dcd5bcaa1 100644 --- a/packages/shared_preferences/shared_preferences_android/lib/src/shared_preferences_async_android.dart +++ b/packages/shared_preferences/shared_preferences_android/lib/src/shared_preferences_async_android.dart @@ -18,10 +18,16 @@ base class SharedPreferencesAsyncAndroid extends SharedPreferencesAsyncPlatform { /// Creates a new plugin implementation instance. SharedPreferencesAsyncAndroid({ - @visibleForTesting SharedPreferencesAsyncApi? api, - }) : _api = api ?? SharedPreferencesAsyncApi(); + @visibleForTesting SharedPreferencesAsyncApi? dataStoreApi, + @visibleForTesting SharedPreferencesAsyncApi? sharedPreferencesApi, + }) : _dataStoreApi = dataStoreApi ?? + SharedPreferencesAsyncApi(messageChannelSuffix: 'data_store'), + _sharedPreferencesApi = sharedPreferencesApi ?? + SharedPreferencesAsyncApi( + messageChannelSuffix: 'shared_preferences'); - final SharedPreferencesAsyncApi _api; + final SharedPreferencesAsyncApi _dataStoreApi; + final SharedPreferencesAsyncApi _sharedPreferencesApi; /// Registers this class as the default instance of [SharedPreferencesAsyncPlatform]. static void registerWith() { @@ -31,22 +37,34 @@ base class SharedPreferencesAsyncAndroid /// Returns a SharedPreferencesPigeonOptions for sending to platform. SharedPreferencesPigeonOptions _convertOptionsToPigeonOptions( SharedPreferencesOptions options) { + if (options is SharedPreferencesAsyncAndroidOptions) { + return SharedPreferencesPigeonOptions( + fileName: options.originalSharedPreferencesOptions?.fileName, + useDataStore: + options.backend == SharedPreferencesAndroidBackendLibrary.DataStore, + ); + } return SharedPreferencesPigeonOptions(); } + SharedPreferencesAsyncApi _getApiForBackend( + SharedPreferencesPigeonOptions options) { + return options.useDataStore ? _dataStoreApi : _sharedPreferencesApi; + } + @override Future> getKeys( GetPreferencesParameters parameters, SharedPreferencesOptions options, ) async { final PreferencesFilters filter = parameters.filter; - // TODO(tarrinneal): Remove cast once https://github.com/flutter/flutter/issues/97848 - // is fixed. In practice, the values will never be null, and the native implementation assumes that. - return (await _api.getKeys( + final SharedPreferencesPigeonOptions pigeonOptions = + _convertOptionsToPigeonOptions(options); + final SharedPreferencesAsyncApi api = _getApiForBackend(pigeonOptions); + return (await api.getKeys( filter.allowList?.toList(), - _convertOptionsToPigeonOptions(options), + pigeonOptions, )) - .cast() .toSet(); } @@ -60,8 +78,11 @@ base class SharedPreferencesAsyncAndroid throw ArgumentError( 'StorageError: This string cannot be stored as it clashes with special identifier prefixes'); } + final SharedPreferencesPigeonOptions pigeonOptions = + _convertOptionsToPigeonOptions(options); + final SharedPreferencesAsyncApi api = _getApiForBackend(pigeonOptions); - return _api.setString(key, value, _convertOptionsToPigeonOptions(options)); + return api.setString(key, value, pigeonOptions); } @override @@ -70,7 +91,10 @@ base class SharedPreferencesAsyncAndroid int value, SharedPreferencesOptions options, ) async { - return _api.setInt(key, value, _convertOptionsToPigeonOptions(options)); + final SharedPreferencesPigeonOptions pigeonOptions = + _convertOptionsToPigeonOptions(options); + final SharedPreferencesAsyncApi api = _getApiForBackend(pigeonOptions); + return api.setInt(key, value, pigeonOptions); } @override @@ -79,7 +103,10 @@ base class SharedPreferencesAsyncAndroid double value, SharedPreferencesOptions options, ) async { - return _api.setDouble(key, value, _convertOptionsToPigeonOptions(options)); + final SharedPreferencesPigeonOptions pigeonOptions = + _convertOptionsToPigeonOptions(options); + final SharedPreferencesAsyncApi api = _getApiForBackend(pigeonOptions); + return api.setDouble(key, value, pigeonOptions); } @override @@ -88,7 +115,10 @@ base class SharedPreferencesAsyncAndroid bool value, SharedPreferencesOptions options, ) async { - return _api.setBool(key, value, _convertOptionsToPigeonOptions(options)); + final SharedPreferencesPigeonOptions pigeonOptions = + _convertOptionsToPigeonOptions(options); + final SharedPreferencesAsyncApi api = _getApiForBackend(pigeonOptions); + return api.setBool(key, value, pigeonOptions); } @override @@ -97,8 +127,10 @@ base class SharedPreferencesAsyncAndroid List value, SharedPreferencesOptions options, ) async { - return _api.setStringList( - key, value, _convertOptionsToPigeonOptions(options)); + final SharedPreferencesPigeonOptions pigeonOptions = + _convertOptionsToPigeonOptions(options); + final SharedPreferencesAsyncApi api = _getApiForBackend(pigeonOptions); + return api.setStringList(key, value, pigeonOptions); } @override @@ -106,8 +138,11 @@ base class SharedPreferencesAsyncAndroid String key, SharedPreferencesOptions options, ) async { - return _convertKnownExceptions(() async => - _api.getString(key, _convertOptionsToPigeonOptions(options))); + final SharedPreferencesPigeonOptions pigeonOptions = + _convertOptionsToPigeonOptions(options); + final SharedPreferencesAsyncApi api = _getApiForBackend(pigeonOptions); + return _convertKnownExceptions( + () async => api.getString(key, pigeonOptions)); } @override @@ -115,8 +150,11 @@ base class SharedPreferencesAsyncAndroid String key, SharedPreferencesOptions options, ) async { + final SharedPreferencesPigeonOptions pigeonOptions = + _convertOptionsToPigeonOptions(options); + final SharedPreferencesAsyncApi api = _getApiForBackend(pigeonOptions); return _convertKnownExceptions( - () async => _api.getBool(key, _convertOptionsToPigeonOptions(options))); + () async => api.getBool(key, pigeonOptions)); } @override @@ -124,8 +162,11 @@ base class SharedPreferencesAsyncAndroid String key, SharedPreferencesOptions options, ) async { - return _convertKnownExceptions(() async => - _api.getDouble(key, _convertOptionsToPigeonOptions(options))); + final SharedPreferencesPigeonOptions pigeonOptions = + _convertOptionsToPigeonOptions(options); + final SharedPreferencesAsyncApi api = _getApiForBackend(pigeonOptions); + return _convertKnownExceptions( + () async => api.getDouble(key, pigeonOptions)); } @override @@ -133,8 +174,11 @@ base class SharedPreferencesAsyncAndroid String key, SharedPreferencesOptions options, ) async { + final SharedPreferencesPigeonOptions pigeonOptions = + _convertOptionsToPigeonOptions(options); + final SharedPreferencesAsyncApi api = _getApiForBackend(pigeonOptions); return _convertKnownExceptions( - () async => _api.getInt(key, _convertOptionsToPigeonOptions(options))); + () async => api.getInt(key, pigeonOptions)); } @override @@ -142,12 +186,13 @@ base class SharedPreferencesAsyncAndroid String key, SharedPreferencesOptions options, ) async { + final SharedPreferencesPigeonOptions pigeonOptions = + _convertOptionsToPigeonOptions(options); + final SharedPreferencesAsyncApi api = _getApiForBackend(pigeonOptions); // TODO(tarrinneal): Remove cast once https://github.com/flutter/flutter/issues/97848 // is fixed. In practice, the values will never be null, and the native implementation assumes that. return _convertKnownExceptions>(() async => - (await _api.getStringList(key, _convertOptionsToPigeonOptions(options))) - ?.cast() - .toList()); + (await api.getStringList(key, pigeonOptions))?.cast().toList()); } Future _convertKnownExceptions(Future Function() method) async { @@ -169,9 +214,12 @@ base class SharedPreferencesAsyncAndroid SharedPreferencesOptions options, ) async { final PreferencesFilters filter = parameters.filter; - return _api.clear( + final SharedPreferencesPigeonOptions pigeonOptions = + _convertOptionsToPigeonOptions(options); + final SharedPreferencesAsyncApi api = _getApiForBackend(pigeonOptions); + return api.clear( filter.allowList?.toList(), - _convertOptionsToPigeonOptions(options), + pigeonOptions, ); } @@ -181,16 +229,53 @@ base class SharedPreferencesAsyncAndroid SharedPreferencesOptions options, ) async { final PreferencesFilters filter = parameters.filter; - final Map data = await _api.getAll( + final SharedPreferencesPigeonOptions pigeonOptions = + _convertOptionsToPigeonOptions(options); + final SharedPreferencesAsyncApi api = _getApiForBackend(pigeonOptions); + final Map data = await api.getAll( filter.allowList?.toList(), - _convertOptionsToPigeonOptions(options), + pigeonOptions, ); return data.cast(); } } +/// Used to identify which Android library should be used on the backend of this call. +enum SharedPreferencesAndroidBackendLibrary { + /// Represents the newer DataStore Preferences library. + DataStore, + + /// Represents the older SharedPreferences library. + SharedPreferences, +} + /// Options for the Android specific SharedPreferences plugin. class SharedPreferencesAsyncAndroidOptions extends SharedPreferencesOptions { /// Constructor for SharedPreferencesAsyncAndroidOptions. - const SharedPreferencesAsyncAndroidOptions(); + const SharedPreferencesAsyncAndroidOptions({ + this.backend = SharedPreferencesAndroidBackendLibrary.DataStore, + this.originalSharedPreferencesOptions, + }); + + /// Which backend should be used for this method call. + final SharedPreferencesAndroidBackendLibrary backend; + + /// These options define how the `SharedPreferences` backend should behave. + /// + /// Any options in this field will be ignored unless the backend that is selected + /// is `SharedPreferences`. + final AndroidSharedPreferencesStoreOptions? originalSharedPreferencesOptions; +} + +/// Options necessary for defining the use of the original `SharedPreferences` +/// library. +/// +/// These options are only ever used with the original `SharedPreferences` and +/// have no purpose when using the default DataStore Preferences. +class AndroidSharedPreferencesStoreOptions { + /// Constructor for AndroidSharedPreferencesStoreOptions. + const AndroidSharedPreferencesStoreOptions({this.fileName}); + + /// The name of the file in which the preferences are stored. + final String? fileName; } diff --git a/packages/shared_preferences/shared_preferences_android/pigeons/messages_async.dart b/packages/shared_preferences/shared_preferences_android/pigeons/messages_async.dart index 5334cc042f5f..9334123482b5 100644 --- a/packages/shared_preferences/shared_preferences_android/pigeons/messages_async.dart +++ b/packages/shared_preferences/shared_preferences_android/pigeons/messages_async.dart @@ -17,9 +17,11 @@ import 'package:pigeon/pigeon.dart'; )) class SharedPreferencesPigeonOptions { SharedPreferencesPigeonOptions({ - this.fileKey, + this.fileName, + this.useDataStore = true, }); - String? fileKey; + String? fileName; + bool useDataStore; } @HostApi(dartHostTestHandler: 'TestSharedPreferencesAsyncApi') diff --git a/packages/shared_preferences/shared_preferences_android/pubspec.yaml b/packages/shared_preferences/shared_preferences_android/pubspec.yaml index c161df41512f..594d763c6f8a 100644 --- a/packages/shared_preferences/shared_preferences_android/pubspec.yaml +++ b/packages/shared_preferences/shared_preferences_android/pubspec.yaml @@ -2,7 +2,7 @@ name: shared_preferences_android description: Android implementation of the shared_preferences plugin repository: https://github.com/flutter/packages/tree/main/packages/shared_preferences/shared_preferences_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+shared_preferences%22 -version: 2.3.4 +version: 2.4.0 environment: sdk: ^3.5.0 @@ -25,7 +25,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - pigeon: ^16.0.4 + pigeon: ^22.6.0 topics: - persistence diff --git a/packages/shared_preferences/shared_preferences_android/test/shared_preferences_async_test.dart b/packages/shared_preferences/shared_preferences_android/test/shared_preferences_async_test.dart index 45ee340a7cfe..fd2907e164b1 100755 --- a/packages/shared_preferences/shared_preferences_android/test/shared_preferences_async_test.dart +++ b/packages/shared_preferences/shared_preferences_android/test/shared_preferences_async_test.dart @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// ignore_for_file: non_constant_identifier_names + +import 'package:flutter/src/services/binary_messenger.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:shared_preferences_android/shared_preferences_android.dart'; import 'package:shared_preferences_android/src/messages_async.g.dart'; @@ -22,185 +25,216 @@ void main() { const double testDouble = 3.14159; const List testList = ['foo', 'bar']; - const SharedPreferencesAsyncAndroidOptions emptyOptions = - SharedPreferencesAsyncAndroidOptions(); - - SharedPreferencesAsyncAndroid getPreferences() { + SharedPreferencesAsyncAndroid getPreferences(bool useDataStore) { final _FakeSharedPreferencesApi api = _FakeSharedPreferencesApi(); final SharedPreferencesAsyncAndroid preferences = - SharedPreferencesAsyncAndroid(api: api); + SharedPreferencesAsyncAndroid( + dataStoreApi: api, + sharedPreferencesApi: api, + ); return preferences; } - test('set and get String', () async { - final SharedPreferencesAsyncAndroid preferences = getPreferences(); - - await preferences.setString(stringKey, testString, emptyOptions); - expect(await preferences.getString(stringKey, emptyOptions), testString); - }); - - test('set and get bool', () async { - final SharedPreferencesAsyncAndroid preferences = getPreferences(); - - await preferences.setBool(boolKey, testBool, emptyOptions); - expect(await preferences.getBool(boolKey, emptyOptions), testBool); - }); - - test('set and get int', () async { - final SharedPreferencesAsyncAndroid preferences = getPreferences(); - - await preferences.setInt(intKey, testInt, emptyOptions); - expect(await preferences.getInt(intKey, emptyOptions), testInt); - }); - - test('set and get double', () async { - final SharedPreferencesAsyncAndroid preferences = getPreferences(); - - await preferences.setDouble(doubleKey, testDouble, emptyOptions); - expect(await preferences.getDouble(doubleKey, emptyOptions), testDouble); - }); - - test('set and get StringList', () async { - final SharedPreferencesAsyncAndroid preferences = getPreferences(); + void runTests(bool useDataStore) { + final String backend = useDataStore ? 'DataStore' : 'SharedPreferences'; - await preferences.setStringList(listKey, testList, emptyOptions); - expect(await preferences.getStringList(listKey, emptyOptions), testList); - }); - - test('getPreferences', () async { - final SharedPreferencesAsyncAndroid preferences = getPreferences(); - await Future.wait(>[ - preferences.setString(stringKey, testString, emptyOptions), - preferences.setBool(boolKey, testBool, emptyOptions), - preferences.setInt(intKey, testInt, emptyOptions), - preferences.setDouble(doubleKey, testDouble, emptyOptions), - preferences.setStringList(listKey, testList, emptyOptions) - ]); + final SharedPreferencesAsyncAndroidOptions emptyOptions = + SharedPreferencesAsyncAndroidOptions( + backend: useDataStore + ? SharedPreferencesAndroidBackendLibrary.DataStore + : SharedPreferencesAndroidBackendLibrary.SharedPreferences, + ); - final Map gotAll = await preferences.getPreferences( + test('set and get String with $backend', () async { + final SharedPreferencesAsyncAndroid preferences = + getPreferences(useDataStore); + + await preferences.setString(stringKey, testString, emptyOptions); + expect(await preferences.getString(stringKey, emptyOptions), testString); + }); + + test('set and get bool with $backend', () async { + final SharedPreferencesAsyncAndroid preferences = + getPreferences(useDataStore); + + await preferences.setBool(boolKey, testBool, emptyOptions); + expect(await preferences.getBool(boolKey, emptyOptions), testBool); + }); + + test('set and get int with $backend', () async { + final SharedPreferencesAsyncAndroid preferences = + getPreferences(useDataStore); + + await preferences.setInt(intKey, testInt, emptyOptions); + expect(await preferences.getInt(intKey, emptyOptions), testInt); + }); + + test('set and get double with $backend', () async { + final SharedPreferencesAsyncAndroid preferences = + getPreferences(useDataStore); + + await preferences.setDouble(doubleKey, testDouble, emptyOptions); + expect(await preferences.getDouble(doubleKey, emptyOptions), testDouble); + }); + + test('set and get StringList with $backend', () async { + final SharedPreferencesAsyncAndroid preferences = + getPreferences(useDataStore); + + await preferences.setStringList(listKey, testList, emptyOptions); + expect(await preferences.getStringList(listKey, emptyOptions), testList); + }); + + test('getPreferences with $backend', () async { + final SharedPreferencesAsyncAndroid preferences = + getPreferences(useDataStore); + await Future.wait(>[ + preferences.setString(stringKey, testString, emptyOptions), + preferences.setBool(boolKey, testBool, emptyOptions), + preferences.setInt(intKey, testInt, emptyOptions), + preferences.setDouble(doubleKey, testDouble, emptyOptions), + preferences.setStringList(listKey, testList, emptyOptions) + ]); + + final Map gotAll = await preferences.getPreferences( + const GetPreferencesParameters(filter: PreferencesFilters()), + emptyOptions); + + expect(gotAll.length, 5); + expect(gotAll[stringKey], testString); + expect(gotAll[boolKey], testBool); + expect(gotAll[intKey], testInt); + expect(gotAll[doubleKey], testDouble); + expect(gotAll[listKey], testList); + }); + + test('getPreferences with filter with $backend', () async { + final SharedPreferencesAsyncAndroid preferences = + getPreferences(useDataStore); + await Future.wait(>[ + preferences.setString(stringKey, testString, emptyOptions), + preferences.setBool(boolKey, testBool, emptyOptions), + preferences.setInt(intKey, testInt, emptyOptions), + preferences.setDouble(doubleKey, testDouble, emptyOptions), + preferences.setStringList(listKey, testList, emptyOptions) + ]); + + final Map gotAll = await preferences.getPreferences( + const GetPreferencesParameters( + filter: + PreferencesFilters(allowList: {stringKey, boolKey})), + emptyOptions); + + expect(gotAll.length, 2); + expect(gotAll[stringKey], testString); + expect(gotAll[boolKey], testBool); + }); + + test('getKeys with $backend', () async { + final SharedPreferencesAsyncAndroid preferences = + getPreferences(useDataStore); + await Future.wait(>[ + preferences.setString(stringKey, testString, emptyOptions), + preferences.setBool(boolKey, testBool, emptyOptions), + preferences.setInt(intKey, testInt, emptyOptions), + preferences.setDouble(doubleKey, testDouble, emptyOptions), + preferences.setStringList(listKey, testList, emptyOptions) + ]); + + final Set keys = await preferences.getKeys( const GetPreferencesParameters(filter: PreferencesFilters()), - emptyOptions); - - expect(gotAll.length, 5); - expect(gotAll[stringKey], testString); - expect(gotAll[boolKey], testBool); - expect(gotAll[intKey], testInt); - expect(gotAll[doubleKey], testDouble); - expect(gotAll[listKey], testList); - }); - - test('getPreferences with filter', () async { - final SharedPreferencesAsyncAndroid preferences = getPreferences(); - await Future.wait(>[ - preferences.setString(stringKey, testString, emptyOptions), - preferences.setBool(boolKey, testBool, emptyOptions), - preferences.setInt(intKey, testInt, emptyOptions), - preferences.setDouble(doubleKey, testDouble, emptyOptions), - preferences.setStringList(listKey, testList, emptyOptions) - ]); - - final Map gotAll = await preferences.getPreferences( + emptyOptions, + ); + + expect(keys.length, 5); + expect(keys, contains(stringKey)); + expect(keys, contains(boolKey)); + expect(keys, contains(intKey)); + expect(keys, contains(doubleKey)); + expect(keys, contains(listKey)); + }); + + test('getKeys with filter with $backend', () async { + final SharedPreferencesAsyncAndroid preferences = + getPreferences(useDataStore); + await Future.wait(>[ + preferences.setString(stringKey, testString, emptyOptions), + preferences.setBool(boolKey, testBool, emptyOptions), + preferences.setInt(intKey, testInt, emptyOptions), + preferences.setDouble(doubleKey, testDouble, emptyOptions), + preferences.setStringList(listKey, testList, emptyOptions) + ]); + + final Set keys = await preferences.getKeys( const GetPreferencesParameters( - filter: - PreferencesFilters(allowList: {stringKey, boolKey})), - emptyOptions); - - expect(gotAll.length, 2); - expect(gotAll[stringKey], testString); - expect(gotAll[boolKey], testBool); - }); - - test('getKeys', () async { - final SharedPreferencesAsyncAndroid preferences = getPreferences(); - await Future.wait(>[ - preferences.setString(stringKey, testString, emptyOptions), - preferences.setBool(boolKey, testBool, emptyOptions), - preferences.setInt(intKey, testInt, emptyOptions), - preferences.setDouble(doubleKey, testDouble, emptyOptions), - preferences.setStringList(listKey, testList, emptyOptions) - ]); - - final Set keys = await preferences.getKeys( - const GetPreferencesParameters(filter: PreferencesFilters()), - emptyOptions, - ); - - expect(keys.length, 5); - expect(keys, contains(stringKey)); - expect(keys, contains(boolKey)); - expect(keys, contains(intKey)); - expect(keys, contains(doubleKey)); - expect(keys, contains(listKey)); - }); - - test('getKeys with filter', () async { - final SharedPreferencesAsyncAndroid preferences = getPreferences(); - await Future.wait(>[ - preferences.setString(stringKey, testString, emptyOptions), - preferences.setBool(boolKey, testBool, emptyOptions), - preferences.setInt(intKey, testInt, emptyOptions), - preferences.setDouble(doubleKey, testDouble, emptyOptions), - preferences.setStringList(listKey, testList, emptyOptions) - ]); - - final Set keys = await preferences.getKeys( - const GetPreferencesParameters( - filter: PreferencesFilters(allowList: {stringKey, boolKey}), - ), - emptyOptions, - ); + filter: PreferencesFilters(allowList: {stringKey, boolKey}), + ), + emptyOptions, + ); + + expect(keys.length, 2); + expect(keys, contains(stringKey)); + expect(keys, contains(boolKey)); + }); + + test('clear with $backend', () async { + final SharedPreferencesAsyncAndroid preferences = + getPreferences(useDataStore); + await Future.wait(>[ + preferences.setString(stringKey, testString, emptyOptions), + preferences.setBool(boolKey, testBool, emptyOptions), + preferences.setInt(intKey, testInt, emptyOptions), + preferences.setDouble(doubleKey, testDouble, emptyOptions), + preferences.setStringList(listKey, testList, emptyOptions) + ]); + await preferences.clear( + const ClearPreferencesParameters(filter: PreferencesFilters()), + emptyOptions); + expect(await preferences.getString(stringKey, emptyOptions), null); + expect(await preferences.getBool(boolKey, emptyOptions), null); + expect(await preferences.getInt(intKey, emptyOptions), null); + expect(await preferences.getDouble(doubleKey, emptyOptions), null); + expect(await preferences.getStringList(listKey, emptyOptions), null); + }); + + test('clear with filter with $backend', () async { + final SharedPreferencesAsyncAndroid preferences = + getPreferences(useDataStore); + await Future.wait(>[ + preferences.setString(stringKey, testString, emptyOptions), + preferences.setBool(boolKey, testBool, emptyOptions), + preferences.setInt(intKey, testInt, emptyOptions), + preferences.setDouble(doubleKey, testDouble, emptyOptions), + preferences.setStringList(listKey, testList, emptyOptions) + ]); + await preferences.clear( + const ClearPreferencesParameters( + filter: PreferencesFilters(allowList: {stringKey, boolKey}), + ), + emptyOptions, + ); + expect(await preferences.getString(stringKey, emptyOptions), null); + expect(await preferences.getBool(boolKey, emptyOptions), null); + expect(await preferences.getInt(intKey, emptyOptions), testInt); + expect(await preferences.getDouble(doubleKey, emptyOptions), testDouble); + expect(await preferences.getStringList(listKey, emptyOptions), testList); + }); + } - expect(keys.length, 2); - expect(keys, contains(stringKey)); - expect(keys, contains(boolKey)); - }); - - test('clear', () async { - final SharedPreferencesAsyncAndroid preferences = getPreferences(); - await Future.wait(>[ - preferences.setString(stringKey, testString, emptyOptions), - preferences.setBool(boolKey, testBool, emptyOptions), - preferences.setInt(intKey, testInt, emptyOptions), - preferences.setDouble(doubleKey, testDouble, emptyOptions), - preferences.setStringList(listKey, testList, emptyOptions) - ]); - await preferences.clear( - const ClearPreferencesParameters(filter: PreferencesFilters()), - emptyOptions); - expect(await preferences.getString(stringKey, emptyOptions), null); - expect(await preferences.getBool(boolKey, emptyOptions), null); - expect(await preferences.getInt(intKey, emptyOptions), null); - expect(await preferences.getDouble(doubleKey, emptyOptions), null); - expect(await preferences.getStringList(listKey, emptyOptions), null); - }); - - test('clear with filter', () async { - final SharedPreferencesAsyncAndroid preferences = getPreferences(); - await Future.wait(>[ - preferences.setString(stringKey, testString, emptyOptions), - preferences.setBool(boolKey, testBool, emptyOptions), - preferences.setInt(intKey, testInt, emptyOptions), - preferences.setDouble(doubleKey, testDouble, emptyOptions), - preferences.setStringList(listKey, testList, emptyOptions) - ]); - await preferences.clear( - const ClearPreferencesParameters( - filter: PreferencesFilters(allowList: {stringKey, boolKey}), - ), - emptyOptions, - ); - expect(await preferences.getString(stringKey, emptyOptions), null); - expect(await preferences.getBool(boolKey, emptyOptions), null); - expect(await preferences.getInt(intKey, emptyOptions), testInt); - expect(await preferences.getDouble(doubleKey, emptyOptions), testDouble); - expect(await preferences.getStringList(listKey, emptyOptions), testList); - }); + runTests(true); + runTests(false); } class _FakeSharedPreferencesApi implements SharedPreferencesAsyncApi { final Map items = {}; + @override + BinaryMessenger? get pigeonVar_binaryMessenger => throw UnimplementedError(); + + @override + String get pigeonVar_messageChannelSuffix => throw UnimplementedError(); + @override Future clear( List? allowList, SharedPreferencesPigeonOptions options) async { @@ -214,7 +248,7 @@ class _FakeSharedPreferencesApi implements SharedPreferencesAsyncApi { } @override - Future> getAll( + Future> getAll( List? allowList, SharedPreferencesPigeonOptions options) async { final Map filteredItems = {...items}; if (allowList != null) { @@ -242,7 +276,7 @@ class _FakeSharedPreferencesApi implements SharedPreferencesAsyncApi { } @override - Future> getKeys( + Future> getKeys( List? allowList, SharedPreferencesPigeonOptions options) async { final List filteredItems = items.keys.toList(); if (allowList != null) { @@ -258,7 +292,7 @@ class _FakeSharedPreferencesApi implements SharedPreferencesAsyncApi { } @override - Future?> getStringList( + Future?> getStringList( String key, SharedPreferencesPigeonOptions options) async { return items[key] as List?; } diff --git a/packages/shared_preferences/shared_preferences_foundation/CHANGELOG.md b/packages/shared_preferences/shared_preferences_foundation/CHANGELOG.md index 6d2bdd8ab8a3..6af9743b2e0a 100644 --- a/packages/shared_preferences/shared_preferences_foundation/CHANGELOG.md +++ b/packages/shared_preferences/shared_preferences_foundation/CHANGELOG.md @@ -1,5 +1,6 @@ -## NEXT +## 2.5.4 +* Updates Pigeon to fix lint error. * Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 2.5.3 diff --git a/packages/shared_preferences/shared_preferences_foundation/darwin/shared_preferences_foundation/Sources/shared_preferences_foundation/messages.g.swift b/packages/shared_preferences/shared_preferences_foundation/darwin/shared_preferences_foundation/Sources/shared_preferences_foundation/messages.g.swift index 275de0921d50..665ea2e5ed6b 100644 --- a/packages/shared_preferences/shared_preferences_foundation/darwin/shared_preferences_foundation/Sources/shared_preferences_foundation/messages.g.swift +++ b/packages/shared_preferences/shared_preferences_foundation/darwin/shared_preferences_foundation/Sources/shared_preferences_foundation/messages.g.swift @@ -86,7 +86,7 @@ struct SharedPreferencesPigeonOptions { } } -private class messagesPigeonCodecReader: FlutterStandardReader { +private class MessagesPigeonCodecReader: FlutterStandardReader { override func readValue(ofType type: UInt8) -> Any? { switch type { case 129: @@ -97,7 +97,7 @@ private class messagesPigeonCodecReader: FlutterStandardReader { } } -private class messagesPigeonCodecWriter: FlutterStandardWriter { +private class MessagesPigeonCodecWriter: FlutterStandardWriter { override func writeValue(_ value: Any) { if let value = value as? SharedPreferencesPigeonOptions { super.writeByte(129) @@ -108,18 +108,18 @@ private class messagesPigeonCodecWriter: FlutterStandardWriter { } } -private class messagesPigeonCodecReaderWriter: FlutterStandardReaderWriter { +private class MessagesPigeonCodecReaderWriter: FlutterStandardReaderWriter { override func reader(with data: Data) -> FlutterStandardReader { - return messagesPigeonCodecReader(data: data) + return MessagesPigeonCodecReader(data: data) } override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return messagesPigeonCodecWriter(data: data) + return MessagesPigeonCodecWriter(data: data) } } -class messagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = messagesPigeonCodec(readerWriter: messagesPigeonCodecReaderWriter()) +class MessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { + static let shared = MessagesPigeonCodec(readerWriter: MessagesPigeonCodecReaderWriter()) } /// Generated protocol from Pigeon that represents a handler of messages from Flutter. @@ -134,7 +134,7 @@ protocol LegacyUserDefaultsApi { /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. class LegacyUserDefaultsApiSetup { - static var codec: FlutterStandardMessageCodec { messagesPigeonCodec.shared } + static var codec: FlutterStandardMessageCodec { MessagesPigeonCodec.shared } /// Sets up an instance of `LegacyUserDefaultsApi` to handle messages through the `binaryMessenger`. static func setUp( binaryMessenger: FlutterBinaryMessenger, api: LegacyUserDefaultsApi?, @@ -272,7 +272,7 @@ protocol UserDefaultsApi { /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. class UserDefaultsApiSetup { - static var codec: FlutterStandardMessageCodec { messagesPigeonCodec.shared } + static var codec: FlutterStandardMessageCodec { MessagesPigeonCodec.shared } /// Sets up an instance of `UserDefaultsApi` to handle messages through the `binaryMessenger`. static func setUp( binaryMessenger: FlutterBinaryMessenger, api: UserDefaultsApi?, diff --git a/packages/shared_preferences/shared_preferences_foundation/pubspec.yaml b/packages/shared_preferences/shared_preferences_foundation/pubspec.yaml index 300fc87fe3b8..915f1c5707a8 100644 --- a/packages/shared_preferences/shared_preferences_foundation/pubspec.yaml +++ b/packages/shared_preferences/shared_preferences_foundation/pubspec.yaml @@ -2,7 +2,7 @@ name: shared_preferences_foundation description: iOS and macOS implementation of the shared_preferences plugin. repository: https://github.com/flutter/packages/tree/main/packages/shared_preferences/shared_preferences_foundation issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+shared_preferences%22 -version: 2.5.3 +version: 2.5.4 environment: sdk: ^3.4.0 From c3787ff14b6f7c3291cd64fb7bca3607ea2cb60b Mon Sep 17 00:00:00 2001 From: Christian Padilla Date: Fri, 13 Dec 2024 13:22:20 -0500 Subject: [PATCH 18/24] [camera_android_camerax] Remove nonnull annotation from getDefaultPointSize (#8292) The primitive float type cannot be null, so the annotation is meaningless. - [NA] I [linked to at least one issue that this PR fixes] in the description above. - [NA] I added new tests to check the change I am making, or this PR is [test-exempt]. --- packages/camera/camera_android_camerax/CHANGELOG.md | 4 ++++ .../io/flutter/plugins/camerax/MeteringPointHostApiImpl.java | 1 - packages/camera/camera_android_camerax/pubspec.yaml | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/camera/camera_android_camerax/CHANGELOG.md b/packages/camera/camera_android_camerax/CHANGELOG.md index 18218256feea..68c5b4218c7c 100644 --- a/packages/camera/camera_android_camerax/CHANGELOG.md +++ b/packages/camera/camera_android_camerax/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.10+1 + +* Removes nonnull annotation from MeteringPointHostApiImpl#getDefaultPointSize. + ## 0.6.10 * Removes logic that explicitly removes `READ_EXTERNAL_STORAGE` permission that may be implied diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/MeteringPointHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/MeteringPointHostApiImpl.java index 36306253ed13..a8775ebb2278 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/MeteringPointHostApiImpl.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/MeteringPointHostApiImpl.java @@ -83,7 +83,6 @@ public DisplayOrientedMeteringPointFactory getDisplayOrientedMeteringPointFactor * Returns the default point size of the {@link MeteringPoint} width and height, which is a * normalized percentage of the sensor width/height. */ - @NonNull public float getDefaultPointSize() { return MeteringPointFactory.getDefaultPointSize(); } diff --git a/packages/camera/camera_android_camerax/pubspec.yaml b/packages/camera/camera_android_camerax/pubspec.yaml index 51d18c6aaa07..2402232a02c5 100644 --- a/packages/camera/camera_android_camerax/pubspec.yaml +++ b/packages/camera/camera_android_camerax/pubspec.yaml @@ -2,7 +2,7 @@ name: camera_android_camerax description: Android implementation of the camera plugin using the CameraX library. repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_android_camerax issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.6.10 +version: 0.6.10+1 environment: sdk: ^3.5.0 From cb9ab429e7eeaa42fa443c3f2d33ce28e38138d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Stivi?= Date: Fri, 13 Dec 2024 15:48:57 -0500 Subject: [PATCH 19/24] [google_adsense] Adds H5 Games Ads support to package. (#7747) This PR adds support for the H5 Games Ads (Ad Placement API) product to `package:google_adsense` through a new `h5.dart` library. Product page: * https://adsense.google.com/start/h5-games-ads JS API reference: * https://developers.google.com/ad-placement/apis ## Issues * Continuation of: https://github.com/flutter/packages/pull/6871 * Continuation of: https://github.com/flutter/packages/pull/8233 * Part of: https://github.com/flutter/flutter/issues/40376 --- packages/google_adsense/CHANGELOG.md | 4 + packages/google_adsense/README.md | 158 ++------- packages/google_adsense/dartdoc_options.yaml | 13 + packages/google_adsense/doc/ad_unit_widget.md | 140 ++++++++ packages/google_adsense/doc/h5.md | 158 +++++++++ packages/google_adsense/doc/initialization.md | 33 ++ .../example/integration_test/core_test.dart | 4 +- .../experimental_ad_unit_widget_test.dart | 2 +- .../example/integration_test/h5_test.dart | 130 +++++++ .../adsbygoogle_js_interop.dart | 34 ++ .../adsense_test_js_interop.dart | 30 +- .../js_interop_mocks/h5_test_js_interop.dart | 58 +++ .../example/lib/ad_unit_widget.dart | 116 ++++++ packages/google_adsense/example/lib/h5.dart | 228 ++++++++++++ packages/google_adsense/example/lib/main.dart | 59 +--- .../google_adsense/example/web/index.html | 3 +- .../lib/experimental/ad_unit_widget.dart | 3 + .../google_adsense/lib/google_adsense.dart | 3 + packages/google_adsense/lib/h5.dart | 8 + .../lib/src/adsense/ad_unit_widget.dart | 2 +- .../lib/src/adsense/adsense_js_interop.dart | 4 +- .../lib/src/core/google_adsense.dart | 57 +-- .../{ => core}/js_interop/adsbygoogle.dart | 0 .../lib/src/core/js_interop/js_loader.dart | 64 ++++ .../js_interop/package_web_tweaks.dart | 0 packages/google_adsense/lib/src/h5/enums.dart | 114 ++++++ packages/google_adsense/lib/src/h5/h5.dart | 39 +++ .../lib/src/h5/h5_js_interop.dart | 330 ++++++++++++++++++ packages/google_adsense/pubspec.yaml | 2 +- 29 files changed, 1526 insertions(+), 270 deletions(-) create mode 100644 packages/google_adsense/dartdoc_options.yaml create mode 100644 packages/google_adsense/doc/ad_unit_widget.md create mode 100644 packages/google_adsense/doc/h5.md create mode 100644 packages/google_adsense/doc/initialization.md create mode 100644 packages/google_adsense/example/integration_test/h5_test.dart create mode 100644 packages/google_adsense/example/integration_test/js_interop_mocks/adsbygoogle_js_interop.dart rename packages/google_adsense/example/integration_test/{ => js_interop_mocks}/adsense_test_js_interop.dart (75%) create mode 100644 packages/google_adsense/example/integration_test/js_interop_mocks/h5_test_js_interop.dart create mode 100644 packages/google_adsense/example/lib/ad_unit_widget.dart create mode 100644 packages/google_adsense/example/lib/h5.dart create mode 100644 packages/google_adsense/lib/h5.dart rename packages/google_adsense/lib/src/{ => core}/js_interop/adsbygoogle.dart (100%) create mode 100644 packages/google_adsense/lib/src/core/js_interop/js_loader.dart rename packages/google_adsense/lib/src/{ => core}/js_interop/package_web_tweaks.dart (100%) create mode 100644 packages/google_adsense/lib/src/h5/enums.dart create mode 100644 packages/google_adsense/lib/src/h5/h5.dart create mode 100644 packages/google_adsense/lib/src/h5/h5_js_interop.dart diff --git a/packages/google_adsense/CHANGELOG.md b/packages/google_adsense/CHANGELOG.md index a8f06137621f..91f12194eb37 100644 --- a/packages/google_adsense/CHANGELOG.md +++ b/packages/google_adsense/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.0 + +* Adds H5 Games Ads API as `h5` library. + ## 0.0.2 * **Breaking changes**: Reshuffles API exports: diff --git a/packages/google_adsense/README.md b/packages/google_adsense/README.md index c82209d480af..e34f60c90b9f 100644 --- a/packages/google_adsense/README.md +++ b/packages/google_adsense/README.md @@ -1,150 +1,34 @@ -# google_adsense -[Google AdSense](https://adsense.google.com/intl/en_us/start/) plugin for Flutter Web - -This package initializes AdSense on your website and provides an ad unit `Widget` that can be configured and placed in the desired location in your Flutter web app UI, without having to directly modify the HTML markup of the app directly. - -## Disclaimer: Early Access ⚠️ -This package is currently in early access and is provided as-is. While it's open source and publicly available, it's likely that you'll need to make additional customizations and configurations to fully integrate it with your Flutter Web App. -Please express interest joining Early Access program using [this form](https://docs.google.com/forms/d/e/1FAIpQLSdN6aOwVkaxGdxbVQFVZ_N4_UCBkuWYa-cS4_rbU_f1jK10Tw/viewform) - -## Usage - -### Setup your AdSense account -1. [Make sure your site's pages are ready for AdSense](https://support.google.com/adsense/answer/7299563) -2. [Create your AdSense account](https://support.google.com/adsense/answer/10162) - -### Initialize AdSense -To start displaying ads, initialize AdSense with your [Publisher ID](https://support.google.com/adsense/answer/105516) (only use numbers). - - -```dart -import 'package:google_adsense/experimental/ad_unit_widget.dart'; -import 'package:google_adsense/google_adsense.dart'; - -void main() async { - // Call `initialize` with your Publisher ID (pub-0123456789012345) - // (See: https://support.google.com/adsense/answer/105516) - await adSense.initialize('0123456789012345'); - - runApp(const MyApp()); -} -``` - -### Displaying Auto Ads -In order to start displaying [Auto ads](https://support.google.com/adsense/answer/9261805): - -1. Configure this feature in your AdSense Console. +# Before you start -Auto ads should start showing just with the call to `initialize`, when available. +This package is only intended for use by web **games**. -If you want to display ad units within your app content, continue to the next step +Please apply to the beta using [this form]( https://adsense.google.com/start/h5-beta/?src=flutter). Once approved, you may use the package. -### Display ad units (`AdUnitWidget`) +Without approval, your code may not behave as expected, and your AdSense account may face policy issues. -To display an Ad unit in your Flutter application: - -1. Create [ad units](https://support.google.com/adsense/answer/9183549) in your AdSense account. - This will provide an HTML snippet, which you need to translate to Dart. -2. Pick the `AdUnitConfiguration` for your ad type: - -| Ad Unit Type | `AdUnitConfiguration` constructor method | -|----------------|--------------------------------------------| -| Display Ads | `AdUnitConfiguration.displayAdUnit(...)` | -| In-feed Ads | `AdUnitConfiguration.inFeedAdUnit(...)` | -| In-article Ads | `AdUnitConfiguration.inArticleAdUnit(...)` | -| Multiplex Ads | `AdUnitConfiguration.multiplexAdUnit(...)` | - -3. The data-attributes from the generated snippet are available through the `AdUnitConfiguration` object. -Their Dart name is created as follows: - -- The `data-` prefix is **removed**. -- `kebab-case` becomes `camelCase` - -The only exception to this is `data-ad-client`, that is passed to `adSense.initialize`, -instead of through an `AdUnitConfiguration` object. - -For example snippet below: - -```html - - -``` -translates into: - - -```dart -// Call `initialize` with your Publisher ID (pub-0123456789012345) -// (See: https://support.google.com/adsense/answer/105516) -await adSense.initialize('0123456789012345'); - -``` - -and: +# google_adsense - -```dart - AdUnitWidget( - configuration: AdUnitConfiguration.displayAdUnit( - // TODO: Replace with your Ad Unit ID - adSlot: '1234567890', - // Remove AdFormat to make ads limited by height - adFormat: AdFormat.AUTO, - ), -), -``` +[Google AdSense](https://adsense.google.com/start/) plugin for Flutter Web. -#### `AdUnitWidget` customizations +This package provides a way to initialize and use AdSense on your Flutter Web app. +It includes libraries for the following products: -To [modify your responsive ad code](https://support.google.com/adsense/answer/9183363?hl=en&ref_topic=9183242&sjid=11551379421978541034-EU): -1. Make sure to follow [AdSense policies](https://support.google.com/adsense/answer/1346295?hl=en&sjid=18331098933308334645-EU&visit_id=638689380593964621-4184295127&ref_topic=1271508&rd=1) -2. Use Flutter instruments for [adaptive and responsive design](https://docs.flutter.dev/ui/adaptive-responsive) +* [H5 Games Ads](https://adsense.google.com/start/h5-games-ads/) (beta) +* (Experimental) [AdSense Ad Unit](https://support.google.com/adsense/answer/9183549) Widget -For example, when not using responsive `AdFormat` it is recommended to wrap adUnit widget in the `Container` with width and/or height constraints. -Note some [policies and restrictions](https://support.google.com/adsense/answer/9185043?hl=en#:~:text=Policies%20and%20restrictions) related to ad unit sizing: +## Documentation - -```dart -Container( - constraints: - const BoxConstraints(maxHeight: 100, maxWidth: 1200), - padding: const EdgeInsets.only(bottom: 10), - child: AdUnitWidget( - configuration: AdUnitConfiguration.displayAdUnit( - // TODO: Replace with your Ad Unit ID - adSlot: '1234567890', - // Do not use adFormat to make ad unit respect height constraint - // adFormat: AdFormat.AUTO, - ), - ), -), -``` -## Testing and common errors +Check the [Flutter API docs](https://pub.dev/documentation/google_adsense/latest/) +to learn how to: -### Failed to load resource: the server responded with a status of 400 -Make sure to set correct values to adSlot and adClient arguments +* [Initialize AdSense](https://pub.dev/documentation/google_adsense/latest/topics/Initialization-topic.html) +* [Use H5 Games Ads](https://pub.dev/documentation/google_adsense/latest/topics/H5%20Games%20Ads-topic.html) (beta) +* [Display Ad Units](https://pub.dev/documentation/google_adsense/latest/topics/Ad%20Units-topic.html) (experimental) -### Failed to load resource: the server responded with a status of 403 -1. When happening in **testing/staging** environment it is likely related to the fact that ads are only filled when requested from an authorized domain. If you are testing locally and running your web app on `localhost`, you need to: - 1. Set custom domain name on localhost by creating a local DNS record that would point `127.0.0.1` and/or `localhost` to `your-domain.com`. On mac/linux machines this can be achieved by adding the following records to you /etc/hosts file: - `127.0.0.1 your-domain.com` - `localhost your-domain.com` - 2. Specify additional run arguments in IDE by editing `Run/Debug Configuration` or by passing them directly to `flutter run` command: - `--web-port=8080` - `--web-hostname=your-domain.com` -2. When happening in **production** it might be that your domain was not yet approved or was disapproved. Login to your AdSense account to check your domain approval status +## Support -### Ad unfilled +For technical problems with the code of this package, please +[create a Github issue](https://github.com/flutter/flutter/issues/new?assignees=&labels=&projects=&template=9_first_party_packages.yml). -There is no deterministic way to make sure your ads are 100% filled even when testing. Some of the way to increase the fill rate: -- Ensure your ad units are correctly configured in AdSense -- Try setting `adTest` parameter to `true` -- Try setting AD_FORMAT to `auto` (default setting) -- Try setting FULL_WIDTH_RESPONSIVE to `true` (default setting) -- Try resizing the window or making sure that ad unit Widget width is less than ~1200px +For any questions or support, please reach out to your Google representative or +leverage the [AdSense Help Center](https://support.google.com/adsense#topic=3373519). diff --git a/packages/google_adsense/dartdoc_options.yaml b/packages/google_adsense/dartdoc_options.yaml new file mode 100644 index 000000000000..121c548b0607 --- /dev/null +++ b/packages/google_adsense/dartdoc_options.yaml @@ -0,0 +1,13 @@ +dartdoc: + categories: + "Initialization": + markdown: doc/initialization.md + "H5 Games Ads": + markdown: doc/h5.md + "Ad Units": + markdown: doc/ad_unit_widget.md + categoryOrder: + - "Initialization" + - "H5 Games Ads" + - "Ad Units" + showUndocumentedCategories: true diff --git a/packages/google_adsense/doc/ad_unit_widget.md b/packages/google_adsense/doc/ad_unit_widget.md new file mode 100644 index 000000000000..bec5aa1a5c49 --- /dev/null +++ b/packages/google_adsense/doc/ad_unit_widget.md @@ -0,0 +1,140 @@ +# Before you start + +This library is in a closed early access, and the list is closed for now. + +Stay tuned for expanded availability of the Ad Unit Widget for Flutter web. + +# `AdUnitWidget` + +The `experimental/ad_unit_widget.dart` library provides an `AdUnitWidget` that +can be configured and placed in the widget tree of your Flutter web app. + +## Usage + +First, initialize AdSense (see the +[Initialization](https://pub.dev/documentation/google_adsense/latest/topics/Initialization-topic.html) +topic). + +### Displaying Auto Ads + +In order to start displaying [Auto ads](https://support.google.com/adsense/answer/9261805): + +1. Configure this feature in your AdSense Console. + +Auto ads should start showing just with the call to `initialize`, when available. + +If you want to display ad units within your app content, continue to the next steps: + +### Import the widget + +Import the **experimental** `AdUnitWidget` from the package: + + +```dart +import 'package:google_adsense/experimental/ad_unit_widget.dart'; +``` + +### Displaying Ad Units + +To display AdSense Ad Units in your Flutter application layout: + +1. Create [ad units](https://support.google.com/adsense/answer/9183549) + in your AdSense account. This will provide an HTML snippet, which you need to + _translate_ to Dart. +2. The data-attributes from the generated snippet can be translated to Dart with the `AdUnitConfiguration` object. +Their Dart name is created as follows: + - The `data-` prefix is removed. + - `kebab-case` becomes `camelCase` + +The only exception to this is `data-ad-client`, that is passed to `adSense.initialize`, +instead of through an `AdUnitConfiguration` object. + +For example, the snippet below: + +```html + + +``` + +translates into: + + +```dart + AdUnitWidget( + configuration: AdUnitConfiguration.displayAdUnit( + // TODO: Replace with your Ad Unit ID + adSlot: '1234567890', + // Remove AdFormat to make ads limited by height + adFormat: AdFormat.AUTO, + ), +), +``` + +#### **`AdUnitConfiguration` constructors** + +In addition to `displayAdUnit`, there's specific constructors for each supported +Ad Unit type. See the table below: + +| Ad Unit Type | `AdUnitConfiguration` constructor method | +|----------------|--------------------------------------------| +| Display Ads | `AdUnitConfiguration.displayAdUnit(...)` | +| In-feed Ads | `AdUnitConfiguration.inFeedAdUnit(...)` | +| In-article Ads | `AdUnitConfiguration.inArticleAdUnit(...)` | +| Multiplex Ads | `AdUnitConfiguration.multiplexAdUnit(...)` | + + +#### **`AdUnitWidget` customizations** + +To [modify your responsive ad code](https://support.google.com/adsense/answer/9183363?hl=en&ref_topic=9183242&sjid=11551379421978541034-EU): +1. Make sure to follow [AdSense policies](https://support.google.com/adsense/answer/1346295?hl=en&sjid=18331098933308334645-EU&visit_id=638689380593964621-4184295127&ref_topic=1271508&rd=1) +2. Use Flutter instruments for [adaptive and responsive design](https://docs.flutter.dev/ui/adaptive-responsive) + +For example, when not using responsive `AdFormat` it is recommended to wrap adUnit widget in the `Container` with width and/or height constraints. +Note some [policies and restrictions](https://support.google.com/adsense/answer/9185043?hl=en#:~:text=Policies%20and%20restrictions) related to ad unit sizing: + + +```dart +Container( + constraints: + const BoxConstraints(maxHeight: 100, maxWidth: 1200), + padding: const EdgeInsets.only(bottom: 10), + child: AdUnitWidget( + configuration: AdUnitConfiguration.displayAdUnit( + // TODO: Replace with your Ad Unit ID + adSlot: '1234567890', + // Do not use adFormat to make ad unit respect height constraint + // adFormat: AdFormat.AUTO, + ), + ), +), +``` +## Testing and common errors + +### Failed to load resource: the server responded with a status of 400 +Make sure to set correct values to adSlot and adClient arguments + +### Failed to load resource: the server responded with a status of 403 +1. When happening in **testing/staging** environment it is likely related to the fact that ads are only filled when requested from an authorized domain. If you are testing locally and running your web app on `localhost`, you need to: + 1. Set custom domain name on localhost by creating a local DNS record that would point `127.0.0.1` and/or `localhost` to `your-domain.com`. On mac/linux machines this can be achieved by adding the following records to you /etc/hosts file: + `127.0.0.1 your-domain.com` + `localhost your-domain.com` + 2. Specify additional run arguments in IDE by editing `Run/Debug Configuration` or by passing them directly to `flutter run` command: + `--web-port=8080` + `--web-hostname=your-domain.com` +2. When happening in **production** it might be that your domain was not yet approved or was disapproved. Login to your AdSense account to check your domain approval status + +### Ad unfilled + +There is no deterministic way to make sure your ads are 100% filled even when testing. Some of the way to increase the fill rate: +- Ensure your ad units are correctly configured in AdSense +- Try setting `adTest` parameter to `true` +- Try setting AD_FORMAT to `auto` (default setting) +- Try setting FULL_WIDTH_RESPONSIVE to `true` (default setting) +- Try resizing the window or making sure that ad unit Widget width is less than ~1200px diff --git a/packages/google_adsense/doc/h5.md b/packages/google_adsense/doc/h5.md new file mode 100644 index 000000000000..93295ac21c1e --- /dev/null +++ b/packages/google_adsense/doc/h5.md @@ -0,0 +1,158 @@ +# Before you start + +This package is only intended for use by web **games**. + +Please apply to the beta using +[this form](https://adsense.google.com/start/h5-beta/?src=flutter). +Once approved, you may use the package. + +Without approval, your code may not behave as expected, and your AdSense account +may face policy issues. + +# H5 Games Ads + +The `h5.dart` library provides a way to use the +[AdSense Ad Placement API](https://developers.google.com/ad-placement) +to display ads in games on the web. + +[H5 Games Ads](https://adsense.google.com/start/h5-games-ads/) +offers high-performing formats: + +* [Interstitials](https://developers.google.com/ad-placement/apis#interstitials): + Full-screen ads that are displayed at natural breaks in your game, + such as between levels. Users can choose to either click these ads or return + to your game. +* [Rewarded ads](https://developers.google.com/ad-placement/apis#rewarded_ads): + Ads that users can choose to interact with in exchange for in-game rewards. + +H5 Games Ads formats support display ads, TrueView and Bumper video ads. + +_Review the +[Policy for ad units that offer rewards](https://support.google.com/adsense/answer/9121589) +before using Rewarded Ads._ + +## Usage + +First, initialize AdSense (see the +[Initialization](https://pub.dev/documentation/google_adsense/latest/topics/Initialization-topic.html) +topic). + +### Import the H5 Games Ads client + + +```dart +import 'package:google_adsense/h5.dart'; +``` + +This provides an `h5GamesAds` object with two methods: `adBreak` to request ads, +and `adConfig` to configure the ads that are going to be served. + +### Displaying an Interstitial Ad + +To display an Interstitial Ad, call the `adBreak` method with an +`AdBreakPlacement.interstitial`: + + +```dart +h5GamesAds.adBreak( + AdBreakPlacement.interstitial( + type: BreakType.browse, + name: 'test-interstitial-ad', + adBreakDone: _interstitialBreakDone, + ), +); +``` + +#### **Ad break types** + +The following break types are available for `interstitial` ads: + + +| `BreakType` | Description | +|-------------|-------------| +| `start` | Before the app flow starts (after UI has rendered) | +| `pause` | Shown while the app is paused (games) | +| `next` | Ad shown when user is navigating to the next screen | +| `browse` | Shown while the user explores options | + +See the Ad Placement API reference on +[Interstitials](https://developers.google.com/ad-placement/apis#interstitials) +for a full explanation of all the available parameters. + +### Displaying a Rewarded Ad + +_Review the +[Policy for ad units that offer rewards](https://support.google.com/adsense/answer/9121589) +before using Rewarded Ads._ + +To display a Rewarded Ad, call the `adBreak` method with an +`AdBreakPlacement.rewarded`: + + +```dart +h5GamesAds.adBreak( + AdBreakPlacement.rewarded( + name: 'test-rewarded-ad', + beforeReward: _beforeReward, + adViewed: _adViewed, + adDismissed: _adDismissed, + afterAd: _afterAd, + adBreakDone: _rewardedBreakDone, + ), +); +``` + +If a Rewarded ad is available, the `beforeReward` callback will be called with a +`showAdFn` function that you can call to show the Ad when the player wants to +claim a reward. + +When the user fully watches the ad, the `adViewed` callback will be called, and +the reward should be granted. + +If the user dismisses the ad before they're eligible for a reward, the +`adDismissed` callback will be called instead. + +See the Ad Placement API reference on +[Rewarded ads](https://developers.google.com/ad-placement/apis#rewarded_ads) +for a full explanation of all the available parameters, and the +[call sequence for a rewarded ad](https://developers.google.com/ad-placement/apis#call_sequence_for_a_rewarded_ad). + +### The `adBreakDone` callback + +Note that a call to `adBreak` might not show an ad at all. It simply declares a +place where an ad **could** be shown. + +If the API does not have an ad to show it will not call the various before/after +callbacks that are configured. However, if you provide an `adBreakDone` callback, +this will **always** be called, even if an ad is not shown. This allows you to +perform any additional work needed for the placement, such as logging analytics. + +The `adBreakDone` function takes as argument an `AdBreakDonePlacementInfo` object, +which contains a `breakStatus` property. See the `BreakStatus` enum docs for +more information about the possible values. + +### Configuring Ads + +The `adConfig` function communicates the game's current configuration to the Ad +Placement API. It is used to tune the way it preloads ads and to filter the kinds +of ads it requests so they're suitable. + +You can call `adConfig` with an `AdConfigParameters` object at any time, like +this: + + +```dart +h5GamesAds.adConfig( + AdConfigParameters( + // Configure whether or not your game is playing sounds or muted. + sound: SoundEnabled.on, + // Set to `on` so there's an Ad immediately preloaded. + preloadAdBreaks: PreloadAdBreaks.on, + onReady: _onH5Ready, + ), +); +``` + +See the Ad Placement API reference on +[adConfig](https://developers.google.com/ad-placement/apis/adconfig) +for a full explanation of all the available parameters. diff --git a/packages/google_adsense/doc/initialization.md b/packages/google_adsense/doc/initialization.md new file mode 100644 index 000000000000..9851e8a2441f --- /dev/null +++ b/packages/google_adsense/doc/initialization.md @@ -0,0 +1,33 @@ +# AdSense initialization + +AdSense initialization is the same both for H5 Games Ads and the Ad Unit Widget. + +To initialize AdSense: + +## Setup your AdSense account + +1. [Make sure your site's pages are ready for AdSense](https://support.google.com/adsense/answer/7299563) +2. [Sign up for AdSense](https://support.google.com/adsense/answer/10162) +3. Adhere to the + [AdSense program policies](https://support.google.com/adsense/answer/48182) + while using ads from AdSense, and any specific policies for the ad formats + that you use (for example, there's a specific + [Policy for ad units that offer rewards](https://support.google.com/adsense/answer/9121589).) + +## Configure your Publisher ID + +To start displaying ads, initialize AdSense with your +[Publisher ID](https://support.google.com/adsense/answer/105516) (only use numbers). + + +```dart +import 'package:google_adsense/google_adsense.dart'; + +void main() async { + // Call `initialize` with your Publisher ID (pub-0123456789012345) + // (See: https://support.google.com/adsense/answer/105516) + await adSense.initialize('0123456789012345'); + + runApp(const MyApp()); +} +``` diff --git a/packages/google_adsense/example/integration_test/core_test.dart b/packages/google_adsense/example/integration_test/core_test.dart index e55f735e2714..abc4fc18f6c3 100644 --- a/packages/google_adsense/example/integration_test/core_test.dart +++ b/packages/google_adsense/example/integration_test/core_test.dart @@ -11,7 +11,7 @@ import 'package:google_adsense/google_adsense.dart'; import 'package:integration_test/integration_test.dart'; import 'package:web/web.dart' as web; -import 'adsense_test_js_interop.dart'; +import 'js_interop_mocks/adsense_test_js_interop.dart'; const String testClient = 'test_client'; const String testScriptUrl = @@ -64,7 +64,7 @@ void main() async { final web.HTMLElement target = web.HTMLDivElement(); // Write an empty noop object - mockAdsByGoogle(() {}); + mockAdsByGoogle((_) {}); await adSense.initialize(testClient, jsLoaderTarget: target); diff --git a/packages/google_adsense/example/integration_test/experimental_ad_unit_widget_test.dart b/packages/google_adsense/example/integration_test/experimental_ad_unit_widget_test.dart index 12a1231b269a..0127622dd7f6 100644 --- a/packages/google_adsense/example/integration_test/experimental_ad_unit_widget_test.dart +++ b/packages/google_adsense/example/integration_test/experimental_ad_unit_widget_test.dart @@ -14,7 +14,7 @@ import 'package:google_adsense/google_adsense.dart' hide adSense; import 'package:google_adsense/src/adsense/ad_unit_params.dart'; import 'package:integration_test/integration_test.dart'; -import 'adsense_test_js_interop.dart'; +import 'js_interop_mocks/adsense_test_js_interop.dart'; const String testClient = 'test_client'; const String testSlot = 'test_slot'; diff --git a/packages/google_adsense/example/integration_test/h5_test.dart b/packages/google_adsense/example/integration_test/h5_test.dart new file mode 100644 index 000000000000..0ca816239a2e --- /dev/null +++ b/packages/google_adsense/example/integration_test/h5_test.dart @@ -0,0 +1,130 @@ +// 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. + +import 'dart:js_interop'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:google_adsense/google_adsense.dart'; +import 'package:google_adsense/h5.dart'; +import 'package:integration_test/integration_test.dart'; +import 'js_interop_mocks/h5_test_js_interop.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + late AdSense adSense; + + setUp(() async { + adSense = AdSense(); + }); + + tearDown(() { + clearAdsByGoogleMock(); + }); + + group('h5GamesAds.adBreak', () { + testWidgets('can do ad breaks', (WidgetTester tester) async { + mockAdsByGoogle( + mockAdBreak(), + ); + await adSense.initialize('_'); + + final AdBreakPlacement adBreakPlacement = AdBreakPlacement( + type: BreakType.reward, + ); + + h5GamesAds.adBreak(adBreakPlacement); + + // Pump frames so we can see what happened with adBreak + await tester.pump(); + await tester.pump(); + + expect(lastAdBreakPlacement, isNotNull); + expect(lastAdBreakPlacement!.type?.toDart, 'reward'); + }); + + testWidgets('can call the adBreakDone callback', + (WidgetTester tester) async { + AdBreakDonePlacementInfo? lastPlacementInfo; + + void adBreakDoneCallback(AdBreakDonePlacementInfo placementInfo) { + lastPlacementInfo = placementInfo; + } + + mockAdsByGoogle( + mockAdBreak( + adBreakDonePlacementInfo: AdBreakDonePlacementInfo( + breakName: 'ok-for-tests'.toJS, + ), + ), + ); + await adSense.initialize('_'); + + final AdBreakPlacement adBreakPlacement = AdBreakPlacement( + type: BreakType.reward, + adBreakDone: adBreakDoneCallback, + ); + + h5GamesAds.adBreak(adBreakPlacement); + + // Pump frames so we can see what happened with adBreak + await tester.pump(); + await tester.pump(); + + expect(lastPlacementInfo, isNotNull); + expect(lastPlacementInfo!.breakName, 'ok-for-tests'); + }); + + testWidgets('prefixes adBreak name', (WidgetTester tester) async { + mockAdsByGoogle( + mockAdBreak(), + ); + await adSense.initialize('_'); + + final AdBreakPlacement adBreakPlacement = AdBreakPlacement( + type: BreakType.reward, + name: 'my-test-break', + ); + + h5GamesAds.adBreak(adBreakPlacement); + + // Pump frames so we can see what happened with adBreak + await tester.pump(); + await tester.pump(); + + expect(lastAdBreakPlacement!.name!.toDart, 'APFlutter-my-test-break'); + }); + }); + + group('h5GamesAds.adConfig', () { + testWidgets('can set up configuration', (WidgetTester tester) async { + bool called = false; + void onReadyCallback() { + called = true; + } + + mockAdsByGoogle( + mockAdConfig(), + ); + await adSense.initialize('_'); + + h5GamesAds.adConfig( + AdConfigParameters( + preloadAdBreaks: PreloadAdBreaks.on, + sound: SoundEnabled.off, + onReady: onReadyCallback, + ), + ); + + // Pump frames so we can see what happened with adConfig + await tester.pump(); + await tester.pump(); + + expect(lastAdConfigParameters, isNotNull); + expect(lastAdConfigParameters!.sound!.toDart, 'off'); + expect(lastAdConfigParameters!.preloadAdBreaks!.toDart, 'on'); + expect(called, isTrue); + }); + }); +} diff --git a/packages/google_adsense/example/integration_test/js_interop_mocks/adsbygoogle_js_interop.dart b/packages/google_adsense/example/integration_test/js_interop_mocks/adsbygoogle_js_interop.dart new file mode 100644 index 000000000000..a48c22ecc845 --- /dev/null +++ b/packages/google_adsense/example/integration_test/js_interop_mocks/adsbygoogle_js_interop.dart @@ -0,0 +1,34 @@ +// 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. + +@JS() +library; + +import 'dart:async'; +import 'dart:js_interop'; + +/// A function that looks like `adsbygoogle.push` to our JS-interop. +typedef PushFn = void Function(JSAny? params); + +// window.adsbygoogle uses "duck typing", so let us set anything to it. +@JS('adsbygoogle') +external set _adsbygoogle(JSAny? value); + +/// Mocks `adsbygoogle` [push] function. +/// +/// `push` will run in the next tick (`Timer.run`) to ensure async behavior. +void mockAdsByGoogle(PushFn push) { + _adsbygoogle = { + 'push': (JSAny? params) { + Timer.run(() { + push(params); + }); + }.toJS, + }.jsify(); +} + +/// Sets `adsbygoogle` to null. +void clearAdsByGoogleMock() { + _adsbygoogle = null; +} diff --git a/packages/google_adsense/example/integration_test/adsense_test_js_interop.dart b/packages/google_adsense/example/integration_test/js_interop_mocks/adsense_test_js_interop.dart similarity index 75% rename from packages/google_adsense/example/integration_test/adsense_test_js_interop.dart rename to packages/google_adsense/example/integration_test/js_interop_mocks/adsense_test_js_interop.dart index aff8a4f4a55d..811f7eca9101 100644 --- a/packages/google_adsense/example/integration_test/adsense_test_js_interop.dart +++ b/packages/google_adsense/example/integration_test/js_interop_mocks/adsense_test_js_interop.dart @@ -5,39 +5,19 @@ @JS() library; -import 'dart:async'; import 'dart:js_interop'; import 'dart:ui'; import 'package:google_adsense/src/adsense/ad_unit_params.dart'; import 'package:web/web.dart' as web; +import 'adsbygoogle_js_interop.dart'; -typedef VoidFn = void Function(); - -// window.adsbygoogle uses "duck typing", so let us set anything to it. -@JS('adsbygoogle') -external set _adsbygoogle(JSAny? value); - -/// Mocks `adsbygoogle` [push] function. -/// -/// `push` will run in the next tick (`Timer.run`) to ensure async behavior. -void mockAdsByGoogle(VoidFn push) { - _adsbygoogle = { - 'push': () { - Timer.run(push); - }.toJS, - }.jsify(); -} - -/// Sets `adsbygoogle` to null. -void clearAdsByGoogleMock() { - _adsbygoogle = null; -} +export 'adsbygoogle_js_interop.dart'; typedef MockAdConfig = ({Size size, String adStatus}); /// Returns a function that generates a "push" function for [mockAdsByGoogle]. -VoidFn mockAd({ +PushFn mockAd({ Size size = Size.zero, String adStatus = AdStatus.FILLED, }) { @@ -47,8 +27,8 @@ VoidFn mockAd({ } /// Returns a function that handles a bunch of ad units at once. Can be used with [mockAdsByGoogle]. -VoidFn mockAds(List adConfigs) { - return () { +PushFn mockAds(List adConfigs) { + return (JSAny? _) { final List foundTargets = web.document.querySelectorAll('div[id^=adUnit] ins').toList; diff --git a/packages/google_adsense/example/integration_test/js_interop_mocks/h5_test_js_interop.dart b/packages/google_adsense/example/integration_test/js_interop_mocks/h5_test_js_interop.dart new file mode 100644 index 000000000000..f28498fa68a5 --- /dev/null +++ b/packages/google_adsense/example/integration_test/js_interop_mocks/h5_test_js_interop.dart @@ -0,0 +1,58 @@ +// 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. + +@JS() +library; + +import 'dart:js_interop'; + +import 'package:google_adsense/src/h5/h5.dart'; +import 'adsbygoogle_js_interop.dart'; + +export 'adsbygoogle_js_interop.dart'; + +/// Returns a push implementation that handles calls to `adBreak`. +AdBreakPlacement? lastAdBreakPlacement; +PushFn mockAdBreak({ + AdBreakDonePlacementInfo? adBreakDonePlacementInfo, +}) { + lastAdBreakPlacement = null; + return (JSAny? adBreakPlacement) { + adBreakPlacement as AdBreakPlacement?; + // Leak the adBreakPlacement. + lastAdBreakPlacement = adBreakPlacement; + // Call `adBreakDone` if set, with `adBreakDonePlacementInfo`. + if (adBreakPlacement?.adBreakDone != null) { + assert(adBreakDonePlacementInfo != null); + adBreakPlacement!.adBreakDone! + .callAsFunction(null, adBreakDonePlacementInfo); + } + }; +} + +AdConfigParameters? lastAdConfigParameters; +PushFn mockAdConfig() { + lastAdConfigParameters = null; + return (JSAny? adConfigParameters) { + adConfigParameters as AdConfigParameters?; + // Leak the adConfigParameters. + lastAdConfigParameters = adConfigParameters; + // Call `onReady` if set. + if (adConfigParameters?.onReady != null) { + adConfigParameters!.onReady!.callAsFunction(); + } + }; +} + +extension AdBreakPlacementGettersExtension on AdBreakPlacement { + external JSString? type; + external JSString? name; + external JSFunction? adBreakDone; +} + +extension AdConfigParametersGettersExtension on AdConfigParameters { + external JSString? preloadAdBreaks; + external JSString? sound; + external JSFunction? onReady; +} diff --git a/packages/google_adsense/example/lib/ad_unit_widget.dart b/packages/google_adsense/example/lib/ad_unit_widget.dart new file mode 100644 index 000000000000..7ab1f3801824 --- /dev/null +++ b/packages/google_adsense/example/lib/ad_unit_widget.dart @@ -0,0 +1,116 @@ +// 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. + +// ignore_for_file: flutter_style_todos + +import 'package:flutter/material.dart'; + +// #docregion import-widget +import 'package:google_adsense/experimental/ad_unit_widget.dart'; +// #enddocregion import-widget +import 'package:google_adsense/google_adsense.dart'; + +void main() async { + await adSense.initialize('0123456789012345'); + runApp(const MyApp()); +} + +/// The main app. +class MyApp extends StatelessWidget { + /// Constructs a [MyApp] + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), + useMaterial3: true, + ), + home: const MyHomePage(), + ); + } +} + +/// The home screen +class MyHomePage extends StatefulWidget { + /// Constructs a [HomeScreen] + const MyHomePage({super.key}); + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + title: const Text('AdSense for Flutter demo app'), + ), + body: SingleChildScrollView( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'Responsive Ad Constrained by width of 150px:', + ), + Container( + constraints: const BoxConstraints(maxWidth: 150), + padding: const EdgeInsets.only(bottom: 10), + child: + // #docregion adUnit + AdUnitWidget( + configuration: AdUnitConfiguration.displayAdUnit( + // TODO: Replace with your Ad Unit ID + adSlot: '1234567890', + // Remove AdFormat to make ads limited by height + adFormat: AdFormat.AUTO, + ), + ), + // #enddocregion adUnit + ), + const Text( + 'Responsive Ad Constrained by height of 100px and width of 1200px (to keep ad centered):', + ), + // #docregion constraints + Container( + constraints: + const BoxConstraints(maxHeight: 100, maxWidth: 1200), + padding: const EdgeInsets.only(bottom: 10), + child: AdUnitWidget( + configuration: AdUnitConfiguration.displayAdUnit( + // TODO: Replace with your Ad Unit ID + adSlot: '1234567890', + // Do not use adFormat to make ad unit respect height constraint + // adFormat: AdFormat.AUTO, + ), + ), + ), + // #enddocregion constraints + const Text( + 'Fixed 125x125 size Ad:', + ), + Container( + height: 125, + width: 125, + padding: const EdgeInsets.only(bottom: 10), + child: AdUnitWidget( + configuration: AdUnitConfiguration.displayAdUnit( + // TODO: Replace with your Ad Unit ID + adSlot: '1234567890', + isFullWidthResponsive: false, + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/packages/google_adsense/example/lib/h5.dart b/packages/google_adsense/example/lib/h5.dart new file mode 100644 index 000000000000..0ddbd6478cee --- /dev/null +++ b/packages/google_adsense/example/lib/h5.dart @@ -0,0 +1,228 @@ +// 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. + +// ignore_for_file: flutter_style_todos + +import 'package:flutter/material.dart'; + +import 'package:google_adsense/google_adsense.dart'; +// #docregion import-h5 +import 'package:google_adsense/h5.dart'; +// #enddocregion import-h5 + +void main() async { + await adSense.initialize('0123456789012345'); + runApp(const MyApp()); +} + +/// The main app. +class MyApp extends StatelessWidget { + /// Constructs a [MyApp] + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), + useMaterial3: true, + ), + home: const MyHomePage(), + ); + } +} + +/// The home screen +class MyHomePage extends StatefulWidget { + /// Constructs a [HomeScreen] + const MyHomePage({super.key}); + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + bool _h5Ready = false; + bool _adBreakRequested = false; + int _coins = 0; // The counter of rewards + H5ShowAdFn? _showAdFn; + AdBreakDonePlacementInfo? _lastInterstitialInfo; + AdBreakDonePlacementInfo? _lastRewardedInfo; + + @override + void initState() { + super.initState(); + // #docregion adConfig + h5GamesAds.adConfig( + AdConfigParameters( + // Configure whether or not your game is playing sounds or muted. + sound: SoundEnabled.on, + // Set to `on` so there's an Ad immediately preloaded. + preloadAdBreaks: PreloadAdBreaks.on, + onReady: _onH5Ready, + ), + ); + // #enddocregion adConfig + } + + void _onH5Ready() { + setState(() { + _h5Ready = true; + }); + } + + void _requestInterstitialAd() { + // #docregion interstitial + h5GamesAds.adBreak( + AdBreakPlacement.interstitial( + type: BreakType.browse, + name: 'test-interstitial-ad', + adBreakDone: _interstitialBreakDone, + ), + ); + // #enddocregion interstitial + } + + void _interstitialBreakDone(AdBreakDonePlacementInfo info) { + setState(() { + _lastInterstitialInfo = info; + }); + } + + void _requestRewardedAd() { + // #docregion rewarded + h5GamesAds.adBreak( + AdBreakPlacement.rewarded( + name: 'test-rewarded-ad', + beforeReward: _beforeReward, + adViewed: _adViewed, + adDismissed: _adDismissed, + afterAd: _afterAd, + adBreakDone: _rewardedBreakDone, + ), + ); + // #enddocregion rewarded + setState(() { + _adBreakRequested = true; + }); + } + + void _beforeReward(H5ShowAdFn showAdFn) { + setState(() { + _showAdFn = showAdFn; + }); + } + + void _adViewed() { + setState(() { + _showAdFn = null; + _coins++; + }); + } + + void _adDismissed() { + setState(() { + _showAdFn = null; + }); + } + + void _afterAd() { + setState(() { + _showAdFn = null; + _adBreakRequested = false; + }); + } + + void _rewardedBreakDone(AdBreakDonePlacementInfo info) { + setState(() { + _lastRewardedInfo = info; + }); + } + + @override + Widget build(BuildContext context) { + final bool adBreakAvailable = _showAdFn != null; + return Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + title: const Text('H5 Games for Flutter demo app'), + ), + body: Padding( + padding: const EdgeInsets.all(16), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TextButton.icon( + onPressed: _h5Ready ? _requestInterstitialAd : null, + label: const Text('Show Interstitial Ad'), + icon: const Icon(Icons.play_circle_outline_rounded), + ), + Text( + 'Interstitial Ad Status:', + style: Theme.of(context).textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + Text('Last Status: ${_lastInterstitialInfo?.breakStatus}'), + const Divider(), + PaddedCard( + children: [ + const Text( + '🪙 Available coins:', + ), + Text( + '$_coins', + style: Theme.of(context).textTheme.displayLarge, + ), + TextButton.icon( + onPressed: + _h5Ready && !adBreakAvailable ? _requestRewardedAd : null, + label: const Text('Prepare Reward'), + icon: const Icon(Icons.download_rounded), + ), + TextButton.icon( + onPressed: _showAdFn, + label: const Text('Watch Ad For 1 Coin'), + icon: const Text('🪙'), + ), + ], + ), + Text( + 'Rewarded Ad Status:', + style: Theme.of(context).textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + Text('Requested? $_adBreakRequested'), + Text('Available? $adBreakAvailable'), + Text('Last Status: ${_lastRewardedInfo?.breakStatus}'), + ], + ), + ), + ); + } +} + +/// A Card with some margin and padding pre-set. +class PaddedCard extends StatelessWidget { + /// Builds a `PaddedCard` with [children]. + const PaddedCard({super.key, required this.children}); + + /// The children for this card. They'll be rendered inside a [Column]. + final List children; + + @override + Widget build(BuildContext context) { + return Card( + margin: const EdgeInsets.only(bottom: 16), + child: Padding( + padding: const EdgeInsets.fromLTRB(16, 16, 16, 8), + child: Column( + children: children, + ), + ), + ); + } +} diff --git a/packages/google_adsense/example/lib/main.dart b/packages/google_adsense/example/lib/main.dart index 88d6f83424ec..f689ee7809eb 100644 --- a/packages/google_adsense/example/lib/main.dart +++ b/packages/google_adsense/example/lib/main.dart @@ -6,17 +6,15 @@ import 'package:flutter/material.dart'; -// #docregion init import 'package:google_adsense/experimental/ad_unit_widget.dart'; +// #docregion init import 'package:google_adsense/google_adsense.dart'; void main() async { -// #docregion init-min // Call `initialize` with your Publisher ID (pub-0123456789012345) // (See: https://support.google.com/adsense/answer/105516) await adSense.initialize('0123456789012345'); - // #enddocregion init-min runApp(const MyApp()); } // #enddocregion init @@ -61,55 +59,12 @@ class _MyHomePageState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - const Text( - 'Responsive Ad Constrained by width of 150px:', - ), - Container( - constraints: const BoxConstraints(maxWidth: 150), - padding: const EdgeInsets.only(bottom: 10), - child: - // #docregion adUnit - AdUnitWidget( - configuration: AdUnitConfiguration.displayAdUnit( - // TODO: Replace with your Ad Unit ID - adSlot: '1234567890', - // Remove AdFormat to make ads limited by height - adFormat: AdFormat.AUTO, - ), - ), - // #enddocregion adUnit - ), - const Text( - 'Responsive Ad Constrained by height of 100px and width of 1200px (to keep ad centered):', - ), - // #docregion constraints - Container( - constraints: - const BoxConstraints(maxHeight: 100, maxWidth: 1200), - padding: const EdgeInsets.only(bottom: 10), - child: AdUnitWidget( - configuration: AdUnitConfiguration.displayAdUnit( - // TODO: Replace with your Ad Unit ID - adSlot: '1234567890', - // Do not use adFormat to make ad unit respect height constraint - // adFormat: AdFormat.AUTO, - ), - ), - ), - // #enddocregion constraints - const Text( - 'Fixed 125x125 size Ad:', - ), - Container( - height: 125, - width: 125, - padding: const EdgeInsets.only(bottom: 10), - child: AdUnitWidget( - configuration: AdUnitConfiguration.displayAdUnit( - // TODO: Replace with your Ad Unit ID - adSlot: '1234567890', - isFullWidthResponsive: false, - ), + AdUnitWidget( + configuration: AdUnitConfiguration.displayAdUnit( + // TODO: Replace with your Ad Unit ID + adSlot: '1234567890', + // Remove AdFormat to make ads limited by height + adFormat: AdFormat.AUTO, ), ), ], diff --git a/packages/google_adsense/example/web/index.html b/packages/google_adsense/example/web/index.html index e1611098ded7..ae0f4a223d26 100644 --- a/packages/google_adsense/example/web/index.html +++ b/packages/google_adsense/example/web/index.html @@ -1,8 +1,7 @@ + - - diff --git a/packages/google_adsense/lib/experimental/ad_unit_widget.dart b/packages/google_adsense/lib/experimental/ad_unit_widget.dart index 9d165298d40d..ca933eb5a38f 100644 --- a/packages/google_adsense/lib/experimental/ad_unit_widget.dart +++ b/packages/google_adsense/lib/experimental/ad_unit_widget.dart @@ -2,4 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +/// {@category Ad Units} +library; + export '../src/adsense/adsense.dart'; diff --git a/packages/google_adsense/lib/google_adsense.dart b/packages/google_adsense/lib/google_adsense.dart index ac0e7ae01c56..4706a7027c3f 100644 --- a/packages/google_adsense/lib/google_adsense.dart +++ b/packages/google_adsense/lib/google_adsense.dart @@ -2,4 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +/// {@category Initialization} +library; + export 'src/core/google_adsense.dart'; diff --git a/packages/google_adsense/lib/h5.dart b/packages/google_adsense/lib/h5.dart new file mode 100644 index 000000000000..553ad2d4d0d9 --- /dev/null +++ b/packages/google_adsense/lib/h5.dart @@ -0,0 +1,8 @@ +// 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. + +/// {@category H5 Games Ads} +library; + +export 'src/h5/h5.dart'; diff --git a/packages/google_adsense/lib/src/adsense/ad_unit_widget.dart b/packages/google_adsense/lib/src/adsense/ad_unit_widget.dart index 6771c468cc1c..5e25dda6d76b 100644 --- a/packages/google_adsense/lib/src/adsense/ad_unit_widget.dart +++ b/packages/google_adsense/lib/src/adsense/ad_unit_widget.dart @@ -9,7 +9,7 @@ import 'package:flutter/widgets.dart'; import 'package:web/web.dart' as web; import '../core/google_adsense.dart'; -import '../js_interop/adsbygoogle.dart'; +import '../core/js_interop/adsbygoogle.dart'; import '../utils/logging.dart'; import 'ad_unit_configuration.dart'; import 'ad_unit_params.dart'; diff --git a/packages/google_adsense/lib/src/adsense/adsense_js_interop.dart b/packages/google_adsense/lib/src/adsense/adsense_js_interop.dart index d3b6fa53bb21..2f3d96d0711a 100644 --- a/packages/google_adsense/lib/src/adsense/adsense_js_interop.dart +++ b/packages/google_adsense/lib/src/adsense/adsense_js_interop.dart @@ -4,12 +4,14 @@ import 'dart:js_interop'; -import '../js_interop/adsbygoogle.dart'; +import '../core/js_interop/adsbygoogle.dart'; /// Adds a `requestAd` method to request an AdSense ad. extension AdsByGoogleExtension on AdsByGoogle { /// Convenience method for invoking push() with an empty object void requestAd() { + // This can't be defined as a named external, because we *must* call push + // with an empty JSObject push(JSObject()); } } diff --git a/packages/google_adsense/lib/src/core/google_adsense.dart b/packages/google_adsense/lib/src/core/google_adsense.dart index 3a56b5af92dc..527ac38347e6 100644 --- a/packages/google_adsense/lib/src/core/google_adsense.dart +++ b/packages/google_adsense/lib/src/core/google_adsense.dart @@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:js_interop'; - import 'package:flutter/widgets.dart'; import 'package:web/web.dart' as web; -import '../js_interop/adsbygoogle.dart' show adsbygooglePresent; -import '../js_interop/package_web_tweaks.dart'; - import '../utils/logging.dart'; +import 'js_interop/js_loader.dart'; /// The web implementation of the AdSense API. class AdSense { @@ -18,68 +14,33 @@ class AdSense { /// The [Publisher ID](https://support.google.com/adsense/answer/2923881). late String adClient; - static const String _url = - 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-'; /// Initializes the AdSense SDK with your [adClient]. /// /// The [adClient] parameter is your AdSense [Publisher ID](https://support.google.com/adsense/answer/2923881). /// /// Should be called ASAP, ideally in the `main` method. + // + // TODO(dit): Add the "optional AdSense code parameters", and render them + // in the right location (the script tag for h5 + the ins for display ads). + // See: https://support.google.com/adsense/answer/9955214?hl=en#adsense_code_parameter_descriptions Future initialize( String adClient, { @visibleForTesting bool skipJsLoader = false, @visibleForTesting web.HTMLElement? jsLoaderTarget, }) async { if (_isInitialized) { - debugLog('adSense.initialize called multiple times. Skipping init.'); + debugLog('initialize already called. Skipping.'); return; } this.adClient = adClient; - if (!(skipJsLoader || _sdkAlreadyLoaded(testingTarget: jsLoaderTarget))) { - _loadJsSdk(adClient, jsLoaderTarget); + if (!skipJsLoader) { + await loadJsSdk(adClient, jsLoaderTarget); } else { - debugLog('SDK already on page. Skipping init.'); + debugLog('initialize called with skipJsLoader. Skipping loadJsSdk.'); } _isInitialized = true; } - - bool _sdkAlreadyLoaded({ - web.HTMLElement? testingTarget, - }) { - final String selector = 'script[src*=ca-pub-$adClient]'; - return adsbygooglePresent || - web.document.querySelector(selector) != null || - testingTarget?.querySelector(selector) != null; - } - - void _loadJsSdk(String adClient, web.HTMLElement? testingTarget) { - final String finalUrl = _url + adClient; - - final web.HTMLScriptElement script = web.HTMLScriptElement() - ..async = true - ..crossOrigin = 'anonymous'; - - if (web.window.nullableTrustedTypes != null) { - final String trustedTypePolicyName = 'adsense-dart-$adClient'; - try { - final web.TrustedTypePolicy policy = - web.window.trustedTypes.createPolicy( - trustedTypePolicyName, - web.TrustedTypePolicyOptions( - createScriptURL: ((JSString url) => url).toJS, - )); - script.trustedSrc = policy.createScriptURLNoArgs(finalUrl); - } catch (e) { - throw TrustedTypesException(e.toString()); - } - } else { - debugLog('TrustedTypes not available.'); - script.src = finalUrl; - } - - (testingTarget ?? web.document.head)!.appendChild(script); - } } /// The singleton instance of the AdSense SDK. diff --git a/packages/google_adsense/lib/src/js_interop/adsbygoogle.dart b/packages/google_adsense/lib/src/core/js_interop/adsbygoogle.dart similarity index 100% rename from packages/google_adsense/lib/src/js_interop/adsbygoogle.dart rename to packages/google_adsense/lib/src/core/js_interop/adsbygoogle.dart diff --git a/packages/google_adsense/lib/src/core/js_interop/js_loader.dart b/packages/google_adsense/lib/src/core/js_interop/js_loader.dart new file mode 100644 index 000000000000..6c124ef5a5f7 --- /dev/null +++ b/packages/google_adsense/lib/src/core/js_interop/js_loader.dart @@ -0,0 +1,64 @@ +// 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. + +import 'dart:js_interop'; +import 'package:web/web.dart' as web; + +import '../../utils/logging.dart'; +import 'adsbygoogle.dart' show adsbygooglePresent; +import 'package_web_tweaks.dart'; + +// The URL of the ads by google client. +const String _URL = + 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js'; + +/// Loads the JS SDK for [adClient]. +/// +/// [target] can be used to specify a different injection target than +/// `window.document.head`, and is normally used for tests. +Future loadJsSdk(String adClient, web.HTMLElement? target) async { + if (_sdkAlreadyLoaded(adClient, target)) { + debugLog('adsbygoogle.js already injected. Skipping call to loadJsSdk.'); + return; + } + + final String scriptUrl = '$_URL?client=ca-pub-$adClient'; + + final web.HTMLScriptElement script = web.HTMLScriptElement() + ..async = true + ..crossOrigin = 'anonymous'; + + if (web.window.nullableTrustedTypes != null) { + final String trustedTypePolicyName = 'adsense-dart-$adClient'; + try { + final web.TrustedTypePolicy policy = web.window.trustedTypes.createPolicy( + trustedTypePolicyName, + web.TrustedTypePolicyOptions( + createScriptURL: ((JSString url) => url).toJS, + )); + script.trustedSrc = policy.createScriptURLNoArgs(scriptUrl); + } catch (e) { + throw TrustedTypesException(e.toString()); + } + } else { + debugLog('TrustedTypes not available.'); + script.src = scriptUrl; + } + + (target ?? web.document.head)!.appendChild(script); +} + +// Whether the script for [adClient] is already injected. +// +// [target] can be used to specify a different injection target than +// `window.document.head`, and is normally used for tests. +bool _sdkAlreadyLoaded( + String adClient, + web.HTMLElement? target, +) { + final String selector = 'script[src*=ca-pub-$adClient]'; + return adsbygooglePresent || + web.document.querySelector(selector) != null || + target?.querySelector(selector) != null; +} diff --git a/packages/google_adsense/lib/src/js_interop/package_web_tweaks.dart b/packages/google_adsense/lib/src/core/js_interop/package_web_tweaks.dart similarity index 100% rename from packages/google_adsense/lib/src/js_interop/package_web_tweaks.dart rename to packages/google_adsense/lib/src/core/js_interop/package_web_tweaks.dart diff --git a/packages/google_adsense/lib/src/h5/enums.dart b/packages/google_adsense/lib/src/h5/enums.dart new file mode 100644 index 000000000000..318078bdff74 --- /dev/null +++ b/packages/google_adsense/lib/src/h5/enums.dart @@ -0,0 +1,114 @@ +// 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. + +/// Adds a `maybe` method to Enum.values to retrieve them by their name +/// without throwing. +extension MaybeEnum on List { + /// Attempts to retrieve an enum of type T by its [name]. + T? maybe(String? name) { + for (final T value in this) { + if (value.name == name) { + return value; + } + } + return null; + } +} + +/// Available types of Ad Breaks. +enum BreakType { + /// Before the app loads (before UI has rendered). + preroll, + + /// Before the app flow starts (after UI has rendered). + start, + + /// When the user pauses the app. + pause, + + /// When the user navigates to the next screen. + next, + + /// When the user explores options. + browse, + + /// Rewarded ad. + reward, +} + +/// The set of [BreakType]s that can be used in [AdBreakPlacement.interstitial]. +const Set interstitialBreakType = { + BreakType.start, + BreakType.pause, + BreakType.next, + BreakType.browse, +}; + +/// Available formats of Ad Breaks. +enum BreakFormat { + /// Used in the middle of content + interstitial, + + /// User gets rewarded for watching the entire ad + reward, +} + +/// Response from AdSense, provided as param of the adBreakDone callback +enum BreakStatus { + /// The Ad Placement API had not initialized. + notReady, + + /// A placement timed out because the Ad Placement API took too long to respond. + timeout, + + /// There was a JavaScript error in a callback. + error, + + /// An ad had not been preloaded yet so this placement was skipped. + noAdPreloaded, + + /// An ad wasn't shown because the frequency cap was applied to this placement. + frequencyCapped, + + /// The user didn't click on a reward prompt before they reached the next placement. + /// + /// That is showAdFn() wasn't called before the next adBreak(). + ignored, + + /// The ad was not shown for another reason. + /// + /// (e.g., The ad was still being fetched, or a previously cached ad was + /// disposed because the screen was resized/rotated.) + other, + + /// The user dismissed a rewarded ad before viewing it to completion. + dismissed, + + /// The ad was viewed by the user. + viewed, + + /// The placement was invalid and was ignored. + /// + /// For instance there should only be one preroll placement per page load, + /// subsequent prerolls are failed with this status. + invalid, +} + +/// Whether ads should always be preloaded before the first call to `adBreak`. +enum PreloadAdBreaks { + /// Always preload. + on, + + /// Leaves the decision up to the Ad Placement API. + auto, +} + +/// Whether the app is plays sounds during normal operations. +enum SoundEnabled { + /// Sound is played. + on, + + /// Sound is never played. + off, +} diff --git a/packages/google_adsense/lib/src/h5/h5.dart b/packages/google_adsense/lib/src/h5/h5.dart new file mode 100644 index 000000000000..272ed387e23c --- /dev/null +++ b/packages/google_adsense/lib/src/h5/h5.dart @@ -0,0 +1,39 @@ +// 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. + +import '../core/js_interop/adsbygoogle.dart'; +import 'h5_js_interop.dart'; + +export 'enums.dart' hide MaybeEnum, interstitialBreakType; +export 'h5_js_interop.dart' hide H5JsInteropExtension; + +/// A client to request H5 Games Ads (Ad Placement API). +class H5GamesAdsClient { + /// Requests an ad placement to the Ad Placement API. + /// + /// The [placementConfig] defines the configuration of the ad. + void adBreak( + AdBreakPlacement placementConfig, + ) { + adsbygoogle.adBreak(placementConfig); + } + + /// Communicates the app's current configuration to the Ad Placement API. + /// + /// The Ad Placement API can use this to tune the way it preloads ads and to + /// filter the kinds of ads it requests so they're suitable (eg. video ads + /// that require sound). + /// + /// Call this function as soon as the sound state of your game changes, as the + /// Ad Placement API may have to request new creatives, and this gives it the + /// maximum amount of time to do so. See `sound` in [AdConfigParameters]. + void adConfig( + AdConfigParameters parameters, + ) { + adsbygoogle.adConfig(parameters); + } +} + +/// The singleton instance of the H5 Games Ads client. +final H5GamesAdsClient h5GamesAds = H5GamesAdsClient(); diff --git a/packages/google_adsense/lib/src/h5/h5_js_interop.dart b/packages/google_adsense/lib/src/h5/h5_js_interop.dart new file mode 100644 index 000000000000..4b645a78188c --- /dev/null +++ b/packages/google_adsense/lib/src/h5/h5_js_interop.dart @@ -0,0 +1,330 @@ +// 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. + +import 'dart:js_interop'; + +import 'package:flutter/widgets.dart' show visibleForTesting; + +import '../core/js_interop/adsbygoogle.dart'; +import 'enums.dart'; + +// Used to prefix all the "name"s of the ad placements. +const String _namePrefix = 'APFlutter-'; + +/// Adds H5's `adBreak` and `adConfig` methods to `adSense` to request H5 ads. +extension H5JsInteropExtension on AdsByGoogle { + /// Defines an ad placement configured by [params]. + @JS('push') + external void adBreak(AdBreakPlacement params); + + /// Communicates the app's current [configuration] to the Ad Placement API. + /// + /// The Ad Placement API can use this to tune the way it preloads ads and to + /// filter the kinds of ads it requests so they're suitable (eg. video ads + /// that require sound). + @JS('push') + external void adConfig(AdConfigParameters configuration); +} + +/// Placement configuration object. +/// +/// Used to configure the ad request through the `h5GamesAds.adBreak` method. +/// +/// In addition to a general constructor that takes all possible parameters, this +/// class contains named constructors for the following placement types: +/// +/// * Interstitial (see: [AdBreakPlacement.interstitial]) +/// * Preroll (see: [AdBreakPlacement.preroll]) +/// * Rewarded (see: [AdBreakPlacement.rewarded]) +/// +/// Each constructor will use one or more of the following arguments: +/// +/// {@template pkg_google_adsense_parameter_h5_type} +/// * [type]: The type of the placement. See [BreakType]. +/// {@endtemplate} +/// {@template pkg_google_adsense_parameter_h5_name} +/// * [name]: A name for this particular ad placement within your game. It is an +/// internal identifier, and is not shown to the player. Recommended. +/// {@endtemplate} +/// {@template pkg_google_adsense_parameter_h5_beforeAd} +/// * [beforeAd]: Called before the ad is displayed. The game should pause and +/// mute the sound. These actions must be done synchronously. The ad will be +/// displayed immediately after this callback finishes.. +/// {@endtemplate} +/// {@template pkg_google_adsense_parameter_h5_afterAd} +/// * [afterAd]: Called after the ad is finished (for any reason). For rewarded +/// ads, it is called after either adDismissed or adViewed, depending on +/// player actions +/// {@endtemplate} +/// {@template pkg_google_adsense_parameter_h5_adBreakDone} +/// * [adBreakDone]: Always called as the last step in an `adBreak`, even if +/// there was no ad shown. Takes as argument a `placementInfo` object. +/// See [AdBreakDonePlacementInfo], and: https://developers.google.com/ad-placement/apis/adbreak#adbreakdone_and_placementinfo +/// {@endtemplate} +/// +/// For rewarded placements, the following parameters are also available: +/// +/// {@template pkg_google_adsense_parameter_h5_beforeReward} +/// * [beforeReward]: Called if a rewarded ad is available. The function should +/// take a single argument `showAdFn` which **must** be called to display the +/// rewarded ad. +/// {@endtemplate} +/// {@template pkg_google_adsense_parameter_h5_adDismissed} +/// * [adDismissed]: Called if the player dismisses the ad before it completes. +/// In this case the reward should not be granted. +/// {@endtemplate} +/// {@template pkg_google_adsense_parameter_h5_adViewed} +/// * [adViewed]: Called when the player completes the ad and should be granted +/// the reward. +/// {@endtemplate} +/// +/// For more information about ad units, check +/// [Placement Types](https://developers.google.com/ad-placement/docs/placement-types) +/// documentation and +/// [adBreak parameters](https://developers.google.com/ad-placement/apis/adbreak#adbreak_parameters) +/// in the Ad Placement API docs. +extension type AdBreakPlacement._(JSObject _) implements JSObject { + /// Creates an ad placement configuration that can be passed to `adBreak`. + /// + /// The following parameters are available: + /// + /// {@macro pkg_google_adsense_parameter_h5_type} + /// {@macro pkg_google_adsense_parameter_h5_name} + /// {@macro pkg_google_adsense_parameter_h5_beforeAd} + /// {@macro pkg_google_adsense_parameter_h5_afterAd} + /// {@macro pkg_google_adsense_parameter_h5_beforeReward} + /// {@macro pkg_google_adsense_parameter_h5_adDismissed} + /// {@macro pkg_google_adsense_parameter_h5_adViewed} + /// {@macro pkg_google_adsense_parameter_h5_adBreakDone} + /// + /// This factory can create any type of placement configuration. Read the + /// [Placement Types](https://developers.google.com/ad-placement/docs/placement-types) + /// documentation for more information. + factory AdBreakPlacement({ + required BreakType type, + String? name, + H5BeforeAdCallback? beforeAd, + H5AfterAdCallback? afterAd, + H5BeforeRewardCallback? beforeReward, + H5AdDismissedCallback? adDismissed, + H5AdViewedCallback? adViewed, + H5AdBreakDoneCallback? adBreakDone, + }) { + return AdBreakPlacement._toJS( + type: type.name.toJS, + name: '$_namePrefix${name ?? ''}'.toJS, + beforeAd: beforeAd?.toJS, + afterAd: afterAd?.toJS, + beforeReward: beforeReward != null + ? (JSFunction fn) { + beforeReward(() { + fn.callAsFunction(); + }); + }.toJS + : null, + adDismissed: adDismissed?.toJS, + adViewed: adViewed?.toJS, + adBreakDone: adBreakDone?.toJS, + ); + } + + /// Convenience factory to create a rewarded ad placement configuration. + /// + /// The following parameters are available: + /// + /// {@macro pkg_google_adsense_parameter_h5_name} + /// {@macro pkg_google_adsense_parameter_h5_beforeAd} + /// {@macro pkg_google_adsense_parameter_h5_afterAd} + /// {@macro pkg_google_adsense_parameter_h5_beforeReward} + /// {@macro pkg_google_adsense_parameter_h5_adDismissed} + /// {@macro pkg_google_adsense_parameter_h5_adViewed} + /// {@macro pkg_google_adsense_parameter_h5_adBreakDone} + /// + /// See: https://developers.google.com/ad-placement/apis#rewarded_ads + factory AdBreakPlacement.rewarded({ + String? name, + H5BeforeAdCallback? beforeAd, + H5AfterAdCallback? afterAd, + required H5BeforeRewardCallback? beforeReward, + required H5AdDismissedCallback? adDismissed, + required H5AdViewedCallback? adViewed, + H5AdBreakDoneCallback? adBreakDone, + }) { + return AdBreakPlacement( + type: BreakType.reward, + name: name, + beforeAd: beforeAd, + afterAd: afterAd, + beforeReward: beforeReward, + adDismissed: adDismissed, + adViewed: adViewed, + adBreakDone: adBreakDone, + ); + } + + /// Convenience factory to create a preroll ad configuration. + /// + /// The following parameters are available: + /// + /// {@macro pkg_google_adsense_parameter_h5_adBreakDone} + /// + /// See: https://developers.google.com/ad-placement/apis#prerolls + factory AdBreakPlacement.preroll({ + required H5AdBreakDoneCallback? adBreakDone, + }) { + return AdBreakPlacement( + type: BreakType.preroll, + adBreakDone: adBreakDone, + ); + } + + /// Convenience factory to create an interstitial ad configuration. + /// + /// The following parameters are available: + /// + /// {@macro pkg_google_adsense_parameter_h5_name} + /// {@macro pkg_google_adsense_parameter_h5_beforeAd} + /// {@macro pkg_google_adsense_parameter_h5_afterAd} + /// {@macro pkg_google_adsense_parameter_h5_adBreakDone} + /// + /// See: https://developers.google.com/ad-placement/apis#interstitials + factory AdBreakPlacement.interstitial({ + required BreakType type, + String? name, + H5BeforeAdCallback? beforeAd, + H5AfterAdCallback? afterAd, + H5AdBreakDoneCallback? adBreakDone, + }) { + assert(interstitialBreakType.contains(type), + '$type is not a valid interstitial placement type.'); + return AdBreakPlacement( + type: type, + name: name, + beforeAd: beforeAd, + afterAd: afterAd, + adBreakDone: adBreakDone, + ); + } + + factory AdBreakPlacement._toJS({ + JSString? type, + JSString? name, + JSFunction? beforeAd, + JSFunction? afterAd, + JSFunction? beforeReward, + JSFunction? adDismissed, + JSFunction? adViewed, + JSFunction? adBreakDone, + }) { + return { + if (type != null) 'type': type, + if (name != null) 'name': name, + if (beforeAd != null) 'beforeAd': beforeAd, + if (afterAd != null) 'afterAd': afterAd, + if (beforeReward != null) 'beforeReward': beforeReward, + if (adDismissed != null) 'adDismissed': adDismissed, + if (adViewed != null) 'adViewed': adViewed, + if (adBreakDone != null) 'adBreakDone': adBreakDone, + }.jsify()! as AdBreakPlacement; + } +} + +/// Parameters for the `adConfig` method call. +extension type AdConfigParameters._(JSObject _) implements JSObject { + /// Parameters for the `adConfig` method call. + /// + /// The following parameters are available: + /// + /// * [sound]: Whether the game is currently playing sound. + /// * [preloadAdBreaks]: Whether ads should always be preloaded before the + /// first call to `adBreak`. See: https://developers.google.com/ad-placement/docs/preload-ads + /// * [onReady]: Called when the API has initialized and has finished preloading + /// ads (if you requested preloading using `preloadAdBreaks`). + /// + /// For more information, see: https://developers.google.com/ad-placement/apis/adconfig#adconfig_parameters + factory AdConfigParameters({ + required SoundEnabled? sound, // required because: cl/704928576 + PreloadAdBreaks? preloadAdBreaks, + H5OnReadyCallback? onReady, + }) { + return AdConfigParameters._toJS( + sound: sound?.name.toJS, + preloadAdBreaks: preloadAdBreaks?.name.toJS, + onReady: onReady?.toJS, + ); + } + + factory AdConfigParameters._toJS({ + JSString? sound, + JSString? preloadAdBreaks, + JSFunction? onReady, + }) { + return { + if (sound != null) 'sound': sound, + if (preloadAdBreaks != null) 'preloadAdBreaks': preloadAdBreaks, + if (onReady != null) 'onReady': onReady, + }.jsify()! as AdConfigParameters; + } +} + +/// The parameter passed from the Ad Placement API to the `adBreakDone` callback. +extension type AdBreakDonePlacementInfo._(JSObject _) implements JSObject { + /// Builds an AdBreakDonePlacementInfo object (for tests). + @visibleForTesting + external factory AdBreakDonePlacementInfo({ + JSString? breakType, + JSString? breakName, + JSString? breakFormat, + JSString? breakStatus, + }); + + /// The `type` argument passed to `adBreak`. + BreakType? get breakType => BreakType.values.maybe(_breakType?.toDart); + @JS('breakType') + external JSString? _breakType; + + /// The `name` argument passed to `adBreak`. + String? get breakName => _breakName?.toDart; + @JS('breakName') + external JSString? _breakName; + + /// The format of the break. See [BreakFormat]. + BreakFormat? get breakFormat => + BreakFormat.values.maybe(_breakFormat?.toDart); + @JS('breakFormat') + external JSString? _breakFormat; + + /// The status of this placement. See [BreakStatus]. + BreakStatus? get breakStatus => + BreakStatus.values.maybe(_breakStatus?.toDart); + @JS('breakStatus') + external JSString? _breakStatus; +} + +/// The type of the `showAdFn` function passed to the `beforeReward` callback. +/// +/// This is actually a JSFunction. Do not call outside of the browser. +typedef H5ShowAdFn = void Function(); + +/// The type of the `beforeAd` callback. +typedef H5BeforeAdCallback = void Function(); + +/// The type of the `afterAd` callback. +typedef H5AfterAdCallback = void Function(); + +/// The type of the `adBreakDone` callback. +typedef H5AdBreakDoneCallback = void Function( + AdBreakDonePlacementInfo placementInfo); + +/// The type of the `beforeReward` callback. +typedef H5BeforeRewardCallback = void Function(H5ShowAdFn showAdFn); + +/// The type of the `adDismissed` callback. +typedef H5AdDismissedCallback = void Function(); + +/// The type of the `adViewed` callback. +typedef H5AdViewedCallback = void Function(); + +/// The type of the `onReady` callback. +typedef H5OnReadyCallback = void Function(); diff --git a/packages/google_adsense/pubspec.yaml b/packages/google_adsense/pubspec.yaml index 5739583d2689..efc767669770 100644 --- a/packages/google_adsense/pubspec.yaml +++ b/packages/google_adsense/pubspec.yaml @@ -2,7 +2,7 @@ name: google_adsense description: A wrapper plugin with convenience APIs allowing easier inserting Google Adsense HTML snippets withing a Flutter UI Web application repository: https://github.com/flutter/packages/tree/main/packages/google_adsense issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_adsense%22 -version: 0.0.2 +version: 0.1.0 environment: sdk: ^3.4.0 From 2f78047265ee1e7a669f9f1e23b76d4918d7ea0e Mon Sep 17 00:00:00 2001 From: jesswrd Date: Fri, 13 Dec 2024 12:51:06 -0800 Subject: [PATCH 20/24] Bump Camera Example Plugin Apps Targetsdk Versions (#8193) Bumped targetsdk versions of example app plugins for `camera`, `camera_android`, and `camera_android_camerax`. Deleted `Capture specific image resolutions` integration. The Android CameraX team confirmed the result coming from the CameraX side is correct and works as they expect. This means the supported output sizes cannot fulfill our test case assumptions. For 'camera_android_camerax', we use the automatic selection described [here](https://developer.android.com/media/camera/camerax/configuration#resolution), and it willl automatically choose, so we can't control the outcome. Even if we specify, the resolution is not gauranteed. `camera` would have the same behavior as `camera_android_camerax` because `camera`'s android implementation defaults to `camera_android_camerax` behavior. For `camera_android` we cannot choose the aspect ratio [here](https://developer.android.com/reference/android/media/CamcorderProfile#getAll%28java.lang.String,%20int%29). If there's an unsupported size, it "falls through" to the next smallest size, which means we cannot choose the final resolution. Example high quality aspect ratio [here](https://developer.android.com/reference/android/media/CamcorderProfile#QUALITY_HIGH), and logic for final resolution [here](https://github.com/flutter/packages/blob/a02deb49c1f6bcb8bb895dd67fbf36ac2c9738bd/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/features/resolution/ResolutionFeature.java#L172). Fixes https://github.com/flutter/flutter/issues/154682 --- .../camera/example/android/app/build.gradle | 2 +- .../android/app/src/main/AndroidManifest.xml | 1 + .../example/integration_test/camera_test.dart | 43 --------------- .../example/android/app/build.gradle | 2 +- .../android/app/src/main/AndroidManifest.xml | 1 + .../example/integration_test/camera_test.dart | 46 ---------------- .../example/android/app/build.gradle | 2 +- .../android/app/src/main/AndroidManifest.xml | 2 +- .../integration_test/integration_test.dart | 52 ------------------- 9 files changed, 6 insertions(+), 145 deletions(-) diff --git a/packages/camera/camera/example/android/app/build.gradle b/packages/camera/camera/example/android/app/build.gradle index 9e2d6373e872..1a4c7c76659c 100644 --- a/packages/camera/camera/example/android/app/build.gradle +++ b/packages/camera/camera/example/android/app/build.gradle @@ -32,7 +32,7 @@ android { defaultConfig { applicationId "io.flutter.plugins.cameraexample" minSdkVersion flutter.minSdkVersion - targetSdkVersion 28 + targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/packages/camera/camera/example/android/app/src/main/AndroidManifest.xml b/packages/camera/camera/example/android/app/src/main/AndroidManifest.xml index cef23162ddb6..a6879cf032d5 100644 --- a/packages/camera/camera/example/android/app/src/main/AndroidManifest.xml +++ b/packages/camera/camera/example/android/app/src/main/AndroidManifest.xml @@ -7,6 +7,7 @@ testCaptureImageResolution( - CameraController controller, ResolutionPreset preset) async { - final Size expectedSize = presetExpectedSizes[preset]!; - - // Take Picture - final XFile file = await controller.takePicture(); - - // Load picture - final File fileImage = File(file.path); - final Image image = await decodeImageFromList(fileImage.readAsBytesSync()); - - // Verify image dimensions are as expected - expect(image, isNotNull); - return assertExpectedDimensions( - expectedSize, Size(image.height.toDouble(), image.width.toDouble())); - } - - testWidgets('Capture specific image resolutions', - (WidgetTester tester) async { - final List cameras = await availableCameras(); - if (cameras.isEmpty) { - return; - } - for (final CameraDescription cameraDescription in cameras) { - bool previousPresetExactlySupported = true; - for (final MapEntry preset - in presetExpectedSizes.entries) { - final CameraController controller = - CameraController(cameraDescription, preset.key); - await controller.initialize(); - final bool presetExactlySupported = - await testCaptureImageResolution(controller, preset.key); - assert(!(!previousPresetExactlySupported && presetExactlySupported), - 'The camera took higher resolution pictures at a lower resolution.'); - previousPresetExactlySupported = presetExactlySupported; - await controller.dispose(); - } - } - }); - // This tests that the capture is no bigger than the preset, since we have // automatic code to fall back to smaller sizes when we need to. Returns // whether the image is exactly the desired resolution. diff --git a/packages/camera/camera_android/example/android/app/build.gradle b/packages/camera/camera_android/example/android/app/build.gradle index 9e2d6373e872..1a4c7c76659c 100644 --- a/packages/camera/camera_android/example/android/app/build.gradle +++ b/packages/camera/camera_android/example/android/app/build.gradle @@ -32,7 +32,7 @@ android { defaultConfig { applicationId "io.flutter.plugins.cameraexample" minSdkVersion flutter.minSdkVersion - targetSdkVersion 28 + targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/packages/camera/camera_android/example/android/app/src/main/AndroidManifest.xml b/packages/camera/camera_android/example/android/app/src/main/AndroidManifest.xml index cef23162ddb6..a6879cf032d5 100644 --- a/packages/camera/camera_android/example/android/app/src/main/AndroidManifest.xml +++ b/packages/camera/camera_android/example/android/app/src/main/AndroidManifest.xml @@ -7,6 +7,7 @@ testCaptureImageResolution( - CameraController controller, ResolutionPreset preset) async { - final Size expectedSize = presetExpectedSizes[preset]!; - - // Take Picture - final XFile file = await controller.takePicture(); - - // Load picture - final File fileImage = File(file.path); - final Image image = await decodeImageFromList(fileImage.readAsBytesSync()); - - // Verify image dimensions are as expected - expect(image, isNotNull); - return assertExpectedDimensions( - expectedSize, Size(image.height.toDouble(), image.width.toDouble())); - } - - testWidgets('Capture specific image resolutions', - (WidgetTester tester) async { - final List cameras = - await CameraPlatform.instance.availableCameras(); - if (cameras.isEmpty) { - return; - } - for (final CameraDescription cameraDescription in cameras) { - bool previousPresetExactlySupported = true; - for (final MapEntry preset - in presetExpectedSizes.entries) { - final CameraController controller = CameraController(cameraDescription, - mediaSettings: MediaSettings(resolutionPreset: preset.key)); - await controller.initialize(); - final bool presetExactlySupported = - await testCaptureImageResolution(controller, preset.key); - assert(!(!previousPresetExactlySupported && presetExactlySupported), - 'The camera took higher resolution pictures at a lower resolution.'); - previousPresetExactlySupported = presetExactlySupported; - await controller.dispose(); - } - } - }); - // This tests that the capture is no bigger than the preset, since we have // automatic code to fall back to smaller sizes when we need to. Returns // whether the image is exactly the desired resolution. diff --git a/packages/camera/camera_android_camerax/example/android/app/build.gradle b/packages/camera/camera_android_camerax/example/android/app/build.gradle index 2094aa796f4c..0b0ba5d6442e 100644 --- a/packages/camera/camera_android_camerax/example/android/app/build.gradle +++ b/packages/camera/camera_android_camerax/example/android/app/build.gradle @@ -38,7 +38,7 @@ android { defaultConfig { applicationId "io.flutter.plugins.cameraxexample" minSdkVersion flutter.minSdkVersion - targetSdkVersion 30 + targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/packages/camera/camera_android_camerax/example/android/app/src/main/AndroidManifest.xml b/packages/camera/camera_android_camerax/example/android/app/src/main/AndroidManifest.xml index 1a0da4432332..27ccaae60760 100644 --- a/packages/camera/camera_android_camerax/example/android/app/src/main/AndroidManifest.xml +++ b/packages/camera/camera_android_camerax/example/android/app/src/main/AndroidManifest.xml @@ -6,11 +6,11 @@ android:icon="@mipmap/ic_launcher"> + + + + + + + + + + + + + + + shared_preferences_tool + + + + + + + + + + diff --git a/packages/shared_preferences/shared_preferences_tool/web/manifest.json b/packages/shared_preferences/shared_preferences_tool/web/manifest.json new file mode 100644 index 000000000000..f2fa39ab9af2 --- /dev/null +++ b/packages/shared_preferences/shared_preferences_tool/web/manifest.json @@ -0,0 +1,11 @@ +{ + "name": "shared_preferences_tool", + "short_name": "shared_preferences_tool", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false +} diff --git a/script/configs/allowed_unpinned_deps.yaml b/script/configs/allowed_unpinned_deps.yaml index 9aa33fd59f8e..2ac8f4740033 100644 --- a/script/configs/allowed_unpinned_deps.yaml +++ b/script/configs/allowed_unpinned_deps.yaml @@ -35,6 +35,8 @@ - convert - crypto - dart_style +- devtools_app_shared +- devtools_extensions - fake_async - ffi - gcloud