diff --git a/packages/shared_preferences/CHANGELOG.md b/packages/shared_preferences/CHANGELOG.md index d56eb9b5f185..511cbe4863c6 100644 --- a/packages/shared_preferences/CHANGELOG.md +++ b/packages/shared_preferences/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.5.4 + +* Support the v2 Android embedding. +* Update to AndroidX. +* Migrate to using the new e2e test binding. + ## 0.5.3+5 * Define clang module for iOS. diff --git a/packages/shared_preferences/android/build.gradle b/packages/shared_preferences/android/build.gradle index 584d86abbbae..a96d1a3b04d8 100644 --- a/packages/shared_preferences/android/build.gradle +++ b/packages/shared_preferences/android/build.gradle @@ -53,3 +53,29 @@ android { disable 'InvalidPackage' } } + +// TODO(cyanglaz): Remove this hack once androidx.lifecycle is included on stable. https://github.com/flutter/flutter/issues/42348 +afterEvaluate { + def containsEmbeddingDependencies = false + for (def configuration : configurations.all) { + for (def dependency : configuration.dependencies) { + if (dependency.group == 'io.flutter' && + dependency.name.startsWith('flutter_embedding') && + dependency.isTransitive()) + { + containsEmbeddingDependencies = true + break + } + } + } + if (!containsEmbeddingDependencies) { + android { + dependencies { + def lifecycle_version = "1.1.1" + api "android.arch.lifecycle:runtime:$lifecycle_version" + api "android.arch.lifecycle:common:$lifecycle_version" + api "android.arch.lifecycle:common-java8:$lifecycle_version" + } + } + } +} diff --git a/packages/shared_preferences/android/src/main/java/io/flutter/plugins/sharedpreferences/MethodCallHandlerImpl.java b/packages/shared_preferences/android/src/main/java/io/flutter/plugins/sharedpreferences/MethodCallHandlerImpl.java new file mode 100644 index 000000000000..19b6be95d162 --- /dev/null +++ b/packages/shared_preferences/android/src/main/java/io/flutter/plugins/sharedpreferences/MethodCallHandlerImpl.java @@ -0,0 +1,202 @@ +// Copyright 2019 The Chromium 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.sharedpreferences; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.AsyncTask; +import android.util.Base64; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Implementation of the {@link MethodChannel.MethodCallHandler} for the plugin. It is also + * responsible of managing the {@link android.content.SharedPreferences}. + */ +class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler { + + private static final String SHARED_PREFERENCES_NAME = "FlutterSharedPreferences"; + + // Fun fact: The following is a base64 encoding of the string "This is the prefix for a list." + private static final String LIST_IDENTIFIER = "VGhpcyBpcyB0aGUgcHJlZml4IGZvciBhIGxpc3Qu"; + private static final String BIG_INTEGER_PREFIX = "VGhpcyBpcyB0aGUgcHJlZml4IGZvciBCaWdJbnRlZ2Vy"; + private static final String DOUBLE_PREFIX = "VGhpcyBpcyB0aGUgcHJlZml4IGZvciBEb3VibGUu"; + + private final android.content.SharedPreferences preferences; + + /** + * Constructs a {@link MethodCallHandlerImpl} instance. Creates a {@link + * android.content.SharedPreferences} based on the {@code context}. + */ + MethodCallHandlerImpl(Context context) { + preferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); + } + + @Override + public void onMethodCall(MethodCall call, MethodChannel.Result result) { + String key = call.argument("key"); + try { + switch (call.method) { + case "setBool": + commitAsync(preferences.edit().putBoolean(key, (boolean) call.argument("value")), result); + break; + case "setDouble": + double doubleValue = ((Number) call.argument("value")).doubleValue(); + String doubleValueStr = Double.toString(doubleValue); + commitAsync(preferences.edit().putString(key, DOUBLE_PREFIX + doubleValueStr), result); + break; + case "setInt": + Number number = call.argument("value"); + if (number instanceof BigInteger) { + BigInteger integerValue = (BigInteger) number; + commitAsync( + preferences + .edit() + .putString( + key, BIG_INTEGER_PREFIX + integerValue.toString(Character.MAX_RADIX)), + result); + } else { + commitAsync(preferences.edit().putLong(key, number.longValue()), result); + } + break; + case "setString": + String value = (String) call.argument("value"); + if (value.startsWith(LIST_IDENTIFIER) || value.startsWith(BIG_INTEGER_PREFIX)) { + result.error( + "StorageError", + "This string cannot be stored as it clashes with special identifier prefixes.", + null); + return; + } + commitAsync(preferences.edit().putString(key, value), result); + break; + case "setStringList": + List list = call.argument("value"); + commitAsync( + preferences.edit().putString(key, LIST_IDENTIFIER + encodeList(list)), result); + break; + case "commit": + // We've been committing the whole time. + result.success(true); + break; + case "getAll": + result.success(getAllPrefs()); + return; + case "remove": + commitAsync(preferences.edit().remove(key), result); + break; + case "clear": + Set keySet = getAllPrefs().keySet(); + SharedPreferences.Editor clearEditor = preferences.edit(); + for (String keyToDelete : keySet) { + clearEditor.remove(keyToDelete); + } + commitAsync(clearEditor, result); + break; + default: + result.notImplemented(); + break; + } + } catch (IOException e) { + result.error("IOException encountered", call.method, e); + } + } + + private void commitAsync( + final SharedPreferences.Editor editor, final MethodChannel.Result result) { + new AsyncTask() { + @Override + protected Boolean doInBackground(Void... voids) { + return editor.commit(); + } + + @Override + protected void onPostExecute(Boolean value) { + result.success(value); + } + }.execute(); + } + + private List decodeList(String encodedList) throws IOException { + ObjectInputStream stream = null; + try { + stream = new ObjectInputStream(new ByteArrayInputStream(Base64.decode(encodedList, 0))); + return (List) stream.readObject(); + } catch (ClassNotFoundException e) { + throw new IOException(e); + } finally { + if (stream != null) { + stream.close(); + } + } + } + + private String encodeList(List list) throws IOException { + ObjectOutputStream stream = null; + try { + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + stream = new ObjectOutputStream(byteStream); + stream.writeObject(list); + stream.flush(); + return Base64.encodeToString(byteStream.toByteArray(), 0); + } finally { + if (stream != null) { + stream.close(); + } + } + } + + // Filter preferences to only those set by the flutter app. + private Map getAllPrefs() throws IOException { + Map allPrefs = preferences.getAll(); + Map filteredPrefs = new HashMap<>(); + for (String key : allPrefs.keySet()) { + if (key.startsWith("flutter.")) { + Object value = allPrefs.get(key); + if (value instanceof String) { + String stringValue = (String) value; + if (stringValue.startsWith(LIST_IDENTIFIER)) { + value = decodeList(stringValue.substring(LIST_IDENTIFIER.length())); + } else if (stringValue.startsWith(BIG_INTEGER_PREFIX)) { + String encoded = stringValue.substring(BIG_INTEGER_PREFIX.length()); + value = new BigInteger(encoded, Character.MAX_RADIX); + } else if (stringValue.startsWith(DOUBLE_PREFIX)) { + String doubleStr = stringValue.substring(DOUBLE_PREFIX.length()); + value = Double.valueOf(doubleStr); + } + } else if (value instanceof Set) { + // This only happens for previous usage of setStringSet. The app expects a list. + List listValue = new ArrayList<>((Set) value); + // Let's migrate the value too while we are at it. + boolean success = + preferences + .edit() + .remove(key) + .putString(key, LIST_IDENTIFIER + encodeList(listValue)) + .commit(); + if (!success) { + // If we are unable to migrate the existing preferences, it means we potentially lost them. + // In this case, an error from getAllPrefs() is appropriate since it will alert the app during plugin initialization. + throw new IOException("Could not migrate set to list"); + } + value = listValue; + } + filteredPrefs.put(key, value); + } + } + return filteredPrefs; + } +} diff --git a/packages/shared_preferences/android/src/main/java/io/flutter/plugins/sharedpreferences/SharedPreferencesPlugin.java b/packages/shared_preferences/android/src/main/java/io/flutter/plugins/sharedpreferences/SharedPreferencesPlugin.java index affb56d33ce6..65753c1b1c1a 100644 --- a/packages/shared_preferences/android/src/main/java/io/flutter/plugins/sharedpreferences/SharedPreferencesPlugin.java +++ b/packages/shared_preferences/android/src/main/java/io/flutter/plugins/sharedpreferences/SharedPreferencesPlugin.java @@ -5,199 +5,40 @@ package io.flutter.plugins.sharedpreferences; import android.content.Context; -import android.content.SharedPreferences.Editor; -import android.os.AsyncTask; -import android.util.Base64; -import io.flutter.plugin.common.MethodCall; +import io.flutter.embedding.engine.plugins.FlutterPlugin; +import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.PluginRegistry; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; /** SharedPreferencesPlugin */ @SuppressWarnings("unchecked") -public class SharedPreferencesPlugin implements MethodCallHandler { - private static final String SHARED_PREFERENCES_NAME = "FlutterSharedPreferences"; +public class SharedPreferencesPlugin implements FlutterPlugin { private static final String CHANNEL_NAME = "plugins.flutter.io/shared_preferences"; - - // Fun fact: The following is a base64 encoding of the string "This is the prefix for a list." - private static final String LIST_IDENTIFIER = "VGhpcyBpcyB0aGUgcHJlZml4IGZvciBhIGxpc3Qu"; - private static final String BIG_INTEGER_PREFIX = "VGhpcyBpcyB0aGUgcHJlZml4IGZvciBCaWdJbnRlZ2Vy"; - private static final String DOUBLE_PREFIX = "VGhpcyBpcyB0aGUgcHJlZml4IGZvciBEb3VibGUu"; - - private final android.content.SharedPreferences preferences; + private MethodChannel channel; public static void registerWith(PluginRegistry.Registrar registrar) { - MethodChannel channel = new MethodChannel(registrar.messenger(), CHANNEL_NAME); - SharedPreferencesPlugin instance = new SharedPreferencesPlugin(registrar.context()); - channel.setMethodCallHandler(instance); - } - - private SharedPreferencesPlugin(Context context) { - preferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); - } - - private List decodeList(String encodedList) throws IOException { - ObjectInputStream stream = null; - try { - stream = new ObjectInputStream(new ByteArrayInputStream(Base64.decode(encodedList, 0))); - return (List) stream.readObject(); - } catch (ClassNotFoundException e) { - throw new IOException(e); - } finally { - if (stream != null) { - stream.close(); - } - } + final SharedPreferencesPlugin plugin = new SharedPreferencesPlugin(); + plugin.setupChannel(registrar.messenger(), registrar.context()); } - private String encodeList(List list) throws IOException { - ObjectOutputStream stream = null; - try { - ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); - stream = new ObjectOutputStream(byteStream); - stream.writeObject(list); - stream.flush(); - return Base64.encodeToString(byteStream.toByteArray(), 0); - } finally { - if (stream != null) { - stream.close(); - } - } + @Override + public void onAttachedToEngine(FlutterPlugin.FlutterPluginBinding binding) { + setupChannel(binding.getFlutterEngine().getDartExecutor(), binding.getApplicationContext()); } - // Filter preferences to only those set by the flutter app. - private Map getAllPrefs() throws IOException { - Map allPrefs = preferences.getAll(); - Map filteredPrefs = new HashMap<>(); - for (String key : allPrefs.keySet()) { - if (key.startsWith("flutter.")) { - Object value = allPrefs.get(key); - if (value instanceof String) { - String stringValue = (String) value; - if (stringValue.startsWith(LIST_IDENTIFIER)) { - value = decodeList(stringValue.substring(LIST_IDENTIFIER.length())); - } else if (stringValue.startsWith(BIG_INTEGER_PREFIX)) { - String encoded = stringValue.substring(BIG_INTEGER_PREFIX.length()); - value = new BigInteger(encoded, Character.MAX_RADIX); - } else if (stringValue.startsWith(DOUBLE_PREFIX)) { - String doubleStr = stringValue.substring(DOUBLE_PREFIX.length()); - value = Double.valueOf(doubleStr); - } - } else if (value instanceof Set) { - // This only happens for previous usage of setStringSet. The app expects a list. - List listValue = new ArrayList<>((Set) value); - // Let's migrate the value too while we are at it. - boolean success = - preferences - .edit() - .remove(key) - .putString(key, LIST_IDENTIFIER + encodeList(listValue)) - .commit(); - if (!success) { - // If we are unable to migrate the existing preferences, it means we potentially lost them. - // In this case, an error from getAllPrefs() is appropriate since it will alert the app during plugin initialization. - throw new IOException("Could not migrate set to list"); - } - value = listValue; - } - filteredPrefs.put(key, value); - } - } - return filteredPrefs; + @Override + public void onDetachedFromEngine(FlutterPlugin.FlutterPluginBinding binding) { + teardownChannel(); } - private void commitAsync(final Editor editor, final MethodChannel.Result result) { - new AsyncTask() { - @Override - protected Boolean doInBackground(Void... voids) { - return editor.commit(); - } - - @Override - protected void onPostExecute(Boolean value) { - result.success(value); - } - }.execute(); + private void setupChannel(BinaryMessenger messenger, Context context) { + channel = new MethodChannel(messenger, CHANNEL_NAME); + MethodCallHandlerImpl handler = new MethodCallHandlerImpl(context); + channel.setMethodCallHandler(handler); } - @Override - public void onMethodCall(MethodCall call, MethodChannel.Result result) { - String key = call.argument("key"); - try { - switch (call.method) { - case "setBool": - commitAsync(preferences.edit().putBoolean(key, (boolean) call.argument("value")), result); - break; - case "setDouble": - double doubleValue = ((Number) call.argument("value")).doubleValue(); - String doubleValueStr = Double.toString(doubleValue); - commitAsync(preferences.edit().putString(key, DOUBLE_PREFIX + doubleValueStr), result); - break; - case "setInt": - Number number = call.argument("value"); - if (number instanceof BigInteger) { - BigInteger integerValue = (BigInteger) number; - commitAsync( - preferences - .edit() - .putString( - key, BIG_INTEGER_PREFIX + integerValue.toString(Character.MAX_RADIX)), - result); - } else { - commitAsync(preferences.edit().putLong(key, number.longValue()), result); - } - break; - case "setString": - String value = (String) call.argument("value"); - if (value.startsWith(LIST_IDENTIFIER) || value.startsWith(BIG_INTEGER_PREFIX)) { - result.error( - "StorageError", - "This string cannot be stored as it clashes with special identifier prefixes.", - null); - return; - } - commitAsync(preferences.edit().putString(key, value), result); - break; - case "setStringList": - List list = call.argument("value"); - commitAsync( - preferences.edit().putString(key, LIST_IDENTIFIER + encodeList(list)), result); - break; - case "commit": - // We've been committing the whole time. - result.success(true); - break; - case "getAll": - result.success(getAllPrefs()); - return; - case "remove": - commitAsync(preferences.edit().remove(key), result); - break; - case "clear": - Set keySet = getAllPrefs().keySet(); - Editor clearEditor = preferences.edit(); - for (String keyToDelete : keySet) { - clearEditor.remove(keyToDelete); - } - commitAsync(clearEditor, result); - break; - default: - result.notImplemented(); - break; - } - } catch (IOException e) { - result.error("IOException encountered", call.method, e); - } + private void teardownChannel() { + channel.setMethodCallHandler(null); + channel = null; } } diff --git a/packages/shared_preferences/example/android/app/src/main/AndroidManifest.xml b/packages/shared_preferences/example/android/app/src/main/AndroidManifest.xml index 9640513d7d46..abb4a67db50c 100644 --- a/packages/shared_preferences/example/android/app/src/main/AndroidManifest.xml +++ b/packages/shared_preferences/example/android/app/src/main/AndroidManifest.xml @@ -4,12 +4,18 @@ - + + diff --git a/packages/shared_preferences/example/android/app/src/main/java/io/flutter/plugins/sharedpreferencesexample/EmbeddingV1Activity.java b/packages/shared_preferences/example/android/app/src/main/java/io/flutter/plugins/sharedpreferencesexample/EmbeddingV1Activity.java new file mode 100644 index 000000000000..68bb56444b65 --- /dev/null +++ b/packages/shared_preferences/example/android/app/src/main/java/io/flutter/plugins/sharedpreferencesexample/EmbeddingV1Activity.java @@ -0,0 +1,18 @@ +// Copyright 2017 The Chromium 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.sharedpreferencesexample; + +import android.os.Bundle; +import io.flutter.app.FlutterActivity; +import io.flutter.plugins.GeneratedPluginRegistrant; + +public class EmbeddingV1Activity extends FlutterActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + GeneratedPluginRegistrant.registerWith(this); + } +} diff --git a/packages/shared_preferences/example/android/app/src/main/java/io/flutter/plugins/sharedpreferencesexample/EmbeddingV1ActivityTest.java b/packages/shared_preferences/example/android/app/src/main/java/io/flutter/plugins/sharedpreferencesexample/EmbeddingV1ActivityTest.java new file mode 100644 index 000000000000..3eb677b21163 --- /dev/null +++ b/packages/shared_preferences/example/android/app/src/main/java/io/flutter/plugins/sharedpreferencesexample/EmbeddingV1ActivityTest.java @@ -0,0 +1,14 @@ + +package io.flutter.plugins.sharedpreferencesexample; + +import androidx.test.rule.ActivityTestRule; +import dev.flutter.plugins.e2e.FlutterRunner; +import org.junit.Rule; +import org.junit.runner.RunWith; + +@RunWith(FlutterRunner.class) +public class EmbeddingV1ActivityTest { + @Rule + public ActivityTestRule rule = + new ActivityTestRule<>(EmbeddingV1Activity.class); +} diff --git a/packages/shared_preferences/example/android/app/src/main/java/io/flutter/plugins/sharedpreferencesexample/MainActivity.java b/packages/shared_preferences/example/android/app/src/main/java/io/flutter/plugins/sharedpreferencesexample/MainActivity.java index 2411f387ebca..f40d0035c135 100644 --- a/packages/shared_preferences/example/android/app/src/main/java/io/flutter/plugins/sharedpreferencesexample/MainActivity.java +++ b/packages/shared_preferences/example/android/app/src/main/java/io/flutter/plugins/sharedpreferencesexample/MainActivity.java @@ -1,18 +1,19 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. +// Copyright 2019 The Chromium 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.sharedpreferencesexample; -import android.os.Bundle; -import io.flutter.app.FlutterActivity; -import io.flutter.plugins.GeneratedPluginRegistrant; +import io.flutter.embedding.android.FlutterActivity; +import io.flutter.embedding.engine.FlutterEngine; +import io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin; public class MainActivity extends FlutterActivity { - + // TODO(cyanglaz): Remove this once v2 of GeneratedPluginRegistrant rolls to stable. + // https://github.com/flutter/flutter/issues/42694 @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - GeneratedPluginRegistrant.registerWith(this); + public void configureFlutterEngine(FlutterEngine flutterEngine) { + super.configureFlutterEngine(flutterEngine); + flutterEngine.getPlugins().add(new SharedPreferencesPlugin()); } } diff --git a/packages/shared_preferences/example/android/app/src/main/java/io/flutter/plugins/sharedpreferencesexample/MainActivityTest.java b/packages/shared_preferences/example/android/app/src/main/java/io/flutter/plugins/sharedpreferencesexample/MainActivityTest.java new file mode 100644 index 000000000000..dc6c826bca19 --- /dev/null +++ b/packages/shared_preferences/example/android/app/src/main/java/io/flutter/plugins/sharedpreferencesexample/MainActivityTest.java @@ -0,0 +1,15 @@ +// Copyright 2019 The Chromium 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.sharedpreferencesexample; + +import androidx.test.rule.ActivityTestRule; +import dev.flutter.plugins.e2e.FlutterRunner; +import org.junit.Rule; +import org.junit.runner.RunWith; + +@RunWith(FlutterRunner.class) +public class MainActivityTest { + @Rule public ActivityTestRule rule = new ActivityTestRule<>(MainActivity.class); +} diff --git a/packages/shared_preferences/example/android/gradle.properties b/packages/shared_preferences/example/android/gradle.properties index 8bd86f680510..a6738207fd15 100644 --- a/packages/shared_preferences/example/android/gradle.properties +++ b/packages/shared_preferences/example/android/gradle.properties @@ -1 +1,4 @@ org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true +android.enableR8=true diff --git a/packages/shared_preferences/example/pubspec.yaml b/packages/shared_preferences/example/pubspec.yaml index 866185589c8d..4243e08cba34 100644 --- a/packages/shared_preferences/example/pubspec.yaml +++ b/packages/shared_preferences/example/pubspec.yaml @@ -11,6 +11,12 @@ dev_dependencies: flutter_driver: sdk: flutter test: any + e2e: ^0.2.0 flutter: uses-material-design: true + +environment: + sdk: ">=2.0.0-dev.28.0 <3.0.0" + flutter: ">=1.9.1+hotfix.2 <2.0.0" + diff --git a/packages/shared_preferences/example/test/shared_preferences_test.dart b/packages/shared_preferences/example/test/shared_preferences_test.dart deleted file mode 100644 index c5044730dd3f..000000000000 --- a/packages/shared_preferences/example/test/shared_preferences_test.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; - -import '../lib/main.dart'; - -void main() { - testWidgets('SharedPreferences example widget test', - (WidgetTester tester) async { - await tester.pumpWidget(MyApp()); - expect(find.text('SharedPreferences Demo'), findsOneWidget); - }); -} diff --git a/packages/shared_preferences/example/test/shared_preferences.dart b/packages/shared_preferences/example/test_driver/shared_preferences_e2e.dart similarity index 93% rename from packages/shared_preferences/example/test/shared_preferences.dart rename to packages/shared_preferences/example/test_driver/shared_preferences_e2e.dart index bf40888c43b4..1c09e2eb867e 100644 --- a/packages/shared_preferences/example/test/shared_preferences.dart +++ b/packages/shared_preferences/example/test_driver/shared_preferences_e2e.dart @@ -1,12 +1,10 @@ import 'dart:async'; -import 'package:flutter_driver/driver_extension.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:e2e/e2e.dart'; void main() { - final Completer completer = Completer(); - enableFlutterDriverExtension(handler: (_) => completer.future); - tearDownAll(() => completer.complete(null)); + E2EWidgetsFlutterBinding.ensureInitialized(); group('$SharedPreferences', () { const Map kTestValues = { diff --git a/packages/shared_preferences/example/test_driver/shared_preferences_e2e_test.dart b/packages/shared_preferences/example/test_driver/shared_preferences_e2e_test.dart new file mode 100644 index 000000000000..ff6e9ce74ad9 --- /dev/null +++ b/packages/shared_preferences/example/test_driver/shared_preferences_e2e_test.dart @@ -0,0 +1,15 @@ +// Copyright 2019, the Chromium project authors. Please see the AUTHORS file +// for details. 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 'dart:io'; +import 'package:flutter_driver/flutter_driver.dart'; + +Future main() async { + final FlutterDriver driver = await FlutterDriver.connect(); + final String result = + await driver.requestData(null, timeout: const Duration(minutes: 1)); + driver.close(); + exit(result == 'pass' ? 0 : 1); +} diff --git a/packages/shared_preferences/example/test_driver/shared_preferences_test.dart b/packages/shared_preferences/example/test_driver/shared_preferences_test.dart deleted file mode 100644 index 110203456c7b..000000000000 --- a/packages/shared_preferences/example/test_driver/shared_preferences_test.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:flutter_driver/flutter_driver.dart'; -import 'package:test/test.dart'; - -void main() { - test('SharedPreferences', () async { - final FlutterDriver driver = await FlutterDriver.connect(); - await driver.requestData(null, timeout: const Duration(minutes: 1)); - if (driver != null) { - driver.close(); - } - }); -} diff --git a/packages/shared_preferences/pubspec.yaml b/packages/shared_preferences/pubspec.yaml index be61e14ea2d9..889f1c2ac5d5 100644 --- a/packages/shared_preferences/pubspec.yaml +++ b/packages/shared_preferences/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for reading and writing simple key-value pairs. Wraps NSUserDefaults on iOS and SharedPreferences on Android. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/shared_preferences -version: 0.5.3+5 +version: 0.5.4 flutter: plugin: @@ -22,7 +22,8 @@ dev_dependencies: flutter_driver: sdk: flutter test: any + e2e: ^0.2.0 environment: sdk: ">=2.0.0-dev.28.0 <3.0.0" - flutter: ">=1.5.0 <2.0.0" + flutter: ">=1.6.7 <2.0.0"