From 1f7adb1a492c6870157c4ac475418210d4ebb644 Mon Sep 17 00:00:00 2001 From: Samat Gaiazov Date: Thu, 4 Jul 2019 16:18:19 +0200 Subject: [PATCH 1/7] Implementing sharedpreferences approach to keep quick action intents even if the app was in the background --- .../android/src/main/AndroidManifest.xml | 13 ++++--- .../quickactions/QuickActionsPlugin.java | 35 +++++++++++++++++-- packages/quick_actions/lib/quick_actions.dart | 21 ++++++++++- packages/quick_actions/pubspec.yaml | 1 + 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/packages/quick_actions/android/src/main/AndroidManifest.xml b/packages/quick_actions/android/src/main/AndroidManifest.xml index ed26d787b3e6..26daac952d28 100644 --- a/packages/quick_actions/android/src/main/AndroidManifest.xml +++ b/packages/quick_actions/android/src/main/AndroidManifest.xml @@ -1,7 +1,12 @@ + xmlns:tools="http://schemas.android.com/tools" + package="io.flutter.plugins.quickactions"> - - - + + + diff --git a/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java b/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java index f4ef7267a520..6b563e7f31dd 100644 --- a/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java +++ b/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java @@ -8,19 +8,22 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutManager; import android.graphics.drawable.Icon; import android.os.Build; import android.os.Bundle; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.plugin.common.PluginRegistry.Registrar; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; /** QuickActionsPlugin */ @SuppressWarnings("unchecked") @@ -109,6 +112,10 @@ private List deserializeShortcuts(List> shortc */ public static class ShortcutHandlerActivity extends Activity { + private final String sharedPreferencesName = "FlutterSharedPreferences"; + private final String sharedPreferencesKeyPrefix = "flutter."; + private final String sharedPreferencesActionKey = "action"; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -117,8 +124,30 @@ protected void onCreate(Bundle savedInstanceState) { String type = intent.getStringExtra("type"); if (channel != null) { channel.invokeMethod("launch", type); + } else { + setActionToSharedPreferences(type); + startActivity(getIntentToOpenMainActivity(this)); } finish(); } + + /** + * Returns Intent to launch the MainActivity. Used to start the app, if one of quick actions + * was called from the background. + */ + private Intent getIntentToOpenMainActivity(Context context) { + return context.getPackageManager() + .getLaunchIntentForPackage(context.getApplicationContext().getPackageName()); + } + + /** + * Saving action name to shared preferences to run requested quick action later, + * after app launch + */ + private void setActionToSharedPreferences(String type) { + SharedPreferences prefs = this.getSharedPreferences(sharedPreferencesName, Context.MODE_PRIVATE); + prefs.edit().putString(sharedPreferencesKeyPrefix + + sharedPreferencesActionKey, type).apply(); + } } } diff --git a/packages/quick_actions/lib/quick_actions.dart b/packages/quick_actions/lib/quick_actions.dart index c4292b5f6fdd..861288d6fae0 100644 --- a/packages/quick_actions/lib/quick_actions.dart +++ b/packages/quick_actions/lib/quick_actions.dart @@ -6,10 +6,13 @@ import 'dart:async'; import 'package:flutter/services.dart'; import 'package:meta/meta.dart'; +import 'package:shared_preferences/shared_preferences.dart'; const MethodChannel _kChannel = MethodChannel('plugins.flutter.io/quick_actions'); +const String _actionSharedPrefsKey = "action"; + /// Handler for a quick action launch event. /// /// The argument [type] corresponds to the [ShortcutItem]'s field. @@ -41,11 +44,27 @@ class QuickActions { /// Initializes this plugin. /// /// Call this once before any further interaction with the the plugin. - void initialize(QuickActionHandler handler) { + void initialize(QuickActionHandler handler) async { _kChannel.setMethodCallHandler((MethodCall call) async { assert(call.method == 'launch'); handler(call.arguments); }); + + final action = await _getActionFromSharedPreferences(); + if (action != null) { + handler(action); + _removeActionFromSharedPreferences(); + } + } + + Future _getActionFromSharedPreferences() async { + final prefs = await SharedPreferences.getInstance(); + return prefs.getString(_actionSharedPrefsKey); + } + + Future _removeActionFromSharedPreferences() async { + final prefs = await SharedPreferences.getInstance(); + return prefs.setString(_actionSharedPrefsKey, null); } /// Sets the [ShortcutItem]s to become the app's quick actions. diff --git a/packages/quick_actions/pubspec.yaml b/packages/quick_actions/pubspec.yaml index e324ae087c64..1200997d142f 100644 --- a/packages/quick_actions/pubspec.yaml +++ b/packages/quick_actions/pubspec.yaml @@ -15,6 +15,7 @@ dependencies: flutter: sdk: flutter meta: ^1.0.5 + shared_preferences: ^0.5.3+1 environment: sdk: ">=2.0.0-dev.28.0 <3.0.0" From a16b777619417d2b9fde7b7b879698eb4981c39b Mon Sep 17 00:00:00 2001 From: Samat Gaiazov Date: Thu, 4 Jul 2019 16:54:56 +0200 Subject: [PATCH 2/7] Fixing flutter_plugin_tools issues --- .../quickactions/QuickActionsPlugin.java | 25 +++++++++---------- packages/quick_actions/lib/quick_actions.dart | 6 ++--- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java b/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java index 6b563e7f31dd..88afd7ca27fe 100644 --- a/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java +++ b/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java @@ -14,16 +14,14 @@ import android.graphics.drawable.Icon; import android.os.Build; import android.os.Bundle; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.plugin.common.PluginRegistry.Registrar; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; /** QuickActionsPlugin */ @SuppressWarnings("unchecked") @@ -132,22 +130,23 @@ protected void onCreate(Bundle savedInstanceState) { } /** - * Returns Intent to launch the MainActivity. Used to start the app, if one of quick actions - * was called from the background. + * Returns Intent to launch the MainActivity. Used to start the app, if one of quick actions was + * called from the background. */ private Intent getIntentToOpenMainActivity(Context context) { - return context.getPackageManager() + return context + .getPackageManager() .getLaunchIntentForPackage(context.getApplicationContext().getPackageName()); } /** - * Saving action name to shared preferences to run requested quick action later, - * after app launch + * Saving action name to shared preferences to run requested quick action later, after app + * launch */ private void setActionToSharedPreferences(String type) { - SharedPreferences prefs = this.getSharedPreferences(sharedPreferencesName, Context.MODE_PRIVATE); - prefs.edit().putString(sharedPreferencesKeyPrefix - + sharedPreferencesActionKey, type).apply(); + SharedPreferences prefs = + this.getSharedPreferences(sharedPreferencesName, Context.MODE_PRIVATE); + prefs.edit().putString(sharedPreferencesKeyPrefix + sharedPreferencesActionKey, type).apply(); } } } diff --git a/packages/quick_actions/lib/quick_actions.dart b/packages/quick_actions/lib/quick_actions.dart index 861288d6fae0..f00eb14ecaf3 100644 --- a/packages/quick_actions/lib/quick_actions.dart +++ b/packages/quick_actions/lib/quick_actions.dart @@ -50,7 +50,7 @@ class QuickActions { handler(call.arguments); }); - final action = await _getActionFromSharedPreferences(); + final String action = await _getActionFromSharedPreferences(); if (action != null) { handler(action); _removeActionFromSharedPreferences(); @@ -58,12 +58,12 @@ class QuickActions { } Future _getActionFromSharedPreferences() async { - final prefs = await SharedPreferences.getInstance(); + final SharedPreferences prefs = await SharedPreferences.getInstance(); return prefs.getString(_actionSharedPrefsKey); } Future _removeActionFromSharedPreferences() async { - final prefs = await SharedPreferences.getInstance(); + final SharedPreferences prefs = await SharedPreferences.getInstance(); return prefs.setString(_actionSharedPrefsKey, null); } From 26d39292e972b6de43b1ea3e3cf4c081829b4aae Mon Sep 17 00:00:00 2001 From: Samat Gaiazov Date: Thu, 4 Jul 2019 17:03:34 +0200 Subject: [PATCH 3/7] Updating changelog and version --- packages/quick_actions/CHANGELOG.md | 4 ++++ packages/quick_actions/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/quick_actions/CHANGELOG.md b/packages/quick_actions/CHANGELOG.md index 61fb69e28c5b..9a5afedc61f4 100644 --- a/packages/quick_actions/CHANGELOG.md +++ b/packages/quick_actions/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.0+3 + +* Fixing the quick actions launch on Android when the app is killed. + ## 0.3.0+2 * Add missing template type parameter to `invokeMethod` calls. diff --git a/packages/quick_actions/pubspec.yaml b/packages/quick_actions/pubspec.yaml index 1200997d142f..21053b3d21b2 100644 --- a/packages/quick_actions/pubspec.yaml +++ b/packages/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. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/quick_actions -version: 0.3.0+2 +version: 0.3.0+3 flutter: plugin: From 25cf85bc4978529ca9479a11e293dccc48394a73 Mon Sep 17 00:00:00 2001 From: Samat Gaiazov Date: Sat, 13 Jul 2019 17:56:58 +0200 Subject: [PATCH 4/7] Implementing "intent extras" approach instead of shared preferences as suggested --- .../quickactions/QuickActionsPlugin.java | 40 +++++++++---------- packages/quick_actions/lib/quick_actions.dart | 16 +------- packages/quick_actions/pubspec.yaml | 1 - 3 files changed, 20 insertions(+), 37 deletions(-) diff --git a/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java b/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java index 88afd7ca27fe..6496f4ea17ec 100644 --- a/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java +++ b/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java @@ -8,7 +8,6 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutManager; import android.graphics.drawable.Icon; @@ -27,6 +26,8 @@ @SuppressWarnings("unchecked") public class QuickActionsPlugin implements MethodCallHandler { private final Registrar registrar; + private static final String intentExtraAction = "action"; + private static String passedAction = null; // Channel is a static field because it needs to be accessible to the // {@link ShortcutHandlerActivity} which has to be a static class with @@ -46,6 +47,7 @@ private QuickActionsPlugin(Registrar registrar) { public static void registerWith(Registrar registrar) { channel = new MethodChannel(registrar.messenger(), "plugins.flutter.io/quick_actions"); channel.setMethodCallHandler(new QuickActionsPlugin(registrar)); + passedAction = registrar.activity().getIntent().getStringExtra(intentExtraAction); } @Override @@ -69,6 +71,10 @@ public void onMethodCall(MethodCall call, Result result) { case "clearShortcutItems": shortcutManager.removeAllDynamicShortcuts(); break; + case "getPassedIntent": + result.success(passedAction); + passedAction = null; + return; default: result.notImplemented(); return; @@ -110,10 +116,6 @@ private List deserializeShortcuts(List> shortc */ public static class ShortcutHandlerActivity extends Activity { - private final String sharedPreferencesName = "FlutterSharedPreferences"; - private final String sharedPreferencesKeyPrefix = "flutter."; - private final String sharedPreferencesActionKey = "action"; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -123,8 +125,7 @@ protected void onCreate(Bundle savedInstanceState) { if (channel != null) { channel.invokeMethod("launch", type); } else { - setActionToSharedPreferences(type); - startActivity(getIntentToOpenMainActivity(this)); + startActivity(getIntentToOpenMainActivity(this, type)); } finish(); } @@ -133,20 +134,17 @@ protected void onCreate(Bundle savedInstanceState) { * Returns Intent to launch the MainActivity. Used to start the app, if one of quick actions was * called from the background. */ - private Intent getIntentToOpenMainActivity(Context context) { - return context - .getPackageManager() - .getLaunchIntentForPackage(context.getApplicationContext().getPackageName()); - } - - /** - * Saving action name to shared preferences to run requested quick action later, after app - * launch - */ - private void setActionToSharedPreferences(String type) { - SharedPreferences prefs = - this.getSharedPreferences(sharedPreferencesName, Context.MODE_PRIVATE); - prefs.edit().putString(sharedPreferencesKeyPrefix + sharedPreferencesActionKey, type).apply(); + private Intent getIntentToOpenMainActivity(Context context, String type) { + Intent launchIntentForPackage = + context + .getPackageManager() + .getLaunchIntentForPackage(context.getApplicationContext().getPackageName()); + if (launchIntentForPackage == null) { + return null; + } else { + launchIntentForPackage.putExtra(intentExtraAction, type); + return launchIntentForPackage; + } } } } diff --git a/packages/quick_actions/lib/quick_actions.dart b/packages/quick_actions/lib/quick_actions.dart index a2acefed35d3..8216b03595b1 100644 --- a/packages/quick_actions/lib/quick_actions.dart +++ b/packages/quick_actions/lib/quick_actions.dart @@ -6,13 +6,10 @@ import 'dart:async'; import 'package:flutter/services.dart'; import 'package:meta/meta.dart'; -import 'package:shared_preferences/shared_preferences.dart'; const MethodChannel _kChannel = MethodChannel('plugins.flutter.io/quick_actions'); -const String _actionSharedPrefsKey = "action"; - /// Handler for a quick action launch event. /// /// The argument [type] corresponds to the [ShortcutItem]'s field. @@ -58,23 +55,12 @@ class QuickActions { handler(call.arguments); }); - final String action = await _getActionFromSharedPreferences(); + final String action = await channel.invokeMethod('getPassedIntent'); if (action != null) { handler(action); - _removeActionFromSharedPreferences(); } } - Future _getActionFromSharedPreferences() async { - final SharedPreferences prefs = await SharedPreferences.getInstance(); - return prefs.getString(_actionSharedPrefsKey); - } - - Future _removeActionFromSharedPreferences() async { - final SharedPreferences prefs = await SharedPreferences.getInstance(); - return prefs.setString(_actionSharedPrefsKey, null); - } - /// Sets the [ShortcutItem]s to become the app's quick actions. Future setShortcutItems(List items) async { final List> itemsList = diff --git a/packages/quick_actions/pubspec.yaml b/packages/quick_actions/pubspec.yaml index 81cb07f79e46..a6d8b791f39a 100644 --- a/packages/quick_actions/pubspec.yaml +++ b/packages/quick_actions/pubspec.yaml @@ -15,7 +15,6 @@ dependencies: flutter: sdk: flutter meta: ^1.0.5 - shared_preferences: ^0.5.3+1 dev_dependencies: test: ^1.3.0 From bc8ca5b7b2f459957483c47f90f9a92d25b7ddfc Mon Sep 17 00:00:00 2001 From: Samat Gaiazov Date: Sun, 14 Jul 2019 21:45:45 +0200 Subject: [PATCH 5/7] Added some tests Method renaming Added ios placeholder for getLaunchAction method --- .../plugins/quickactions/QuickActionsPlugin.java | 10 +++++----- .../quick_actions/ios/Classes/QuickActionsPlugin.m | 2 ++ packages/quick_actions/lib/quick_actions.dart | 5 ++++- packages/quick_actions/test/quick_actions_test.dart | 12 ++++++++++++ 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java b/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java index 6496f4ea17ec..6fb276af0934 100644 --- a/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java +++ b/packages/quick_actions/android/src/main/java/io/flutter/plugins/quickactions/QuickActionsPlugin.java @@ -27,7 +27,7 @@ public class QuickActionsPlugin implements MethodCallHandler { private final Registrar registrar; private static final String intentExtraAction = "action"; - private static String passedAction = null; + private static String launchAction = null; // Channel is a static field because it needs to be accessible to the // {@link ShortcutHandlerActivity} which has to be a static class with @@ -47,7 +47,7 @@ private QuickActionsPlugin(Registrar registrar) { public static void registerWith(Registrar registrar) { channel = new MethodChannel(registrar.messenger(), "plugins.flutter.io/quick_actions"); channel.setMethodCallHandler(new QuickActionsPlugin(registrar)); - passedAction = registrar.activity().getIntent().getStringExtra(intentExtraAction); + launchAction = registrar.activity().getIntent().getStringExtra(intentExtraAction); } @Override @@ -71,9 +71,9 @@ public void onMethodCall(MethodCall call, Result result) { case "clearShortcutItems": shortcutManager.removeAllDynamicShortcuts(); break; - case "getPassedIntent": - result.success(passedAction); - passedAction = null; + case "getLaunchAction": + result.success(launchAction); + launchAction = null; return; default: result.notImplemented(); diff --git a/packages/quick_actions/ios/Classes/QuickActionsPlugin.m b/packages/quick_actions/ios/Classes/QuickActionsPlugin.m index f1ff0e41d20d..8f83cc4d9cd2 100644 --- a/packages/quick_actions/ios/Classes/QuickActionsPlugin.m +++ b/packages/quick_actions/ios/Classes/QuickActionsPlugin.m @@ -28,6 +28,8 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result } else if ([call.method isEqualToString:@"clearShortcutItems"]) { [UIApplication sharedApplication].shortcutItems = @[]; result(nil); + } else if ([call.method isEqualToString:@"getLaunchAction"]) { + result(nil); } else { result(FlutterMethodNotImplemented); } diff --git a/packages/quick_actions/lib/quick_actions.dart b/packages/quick_actions/lib/quick_actions.dart index 8216b03595b1..f240968eb8f5 100644 --- a/packages/quick_actions/lib/quick_actions.dart +++ b/packages/quick_actions/lib/quick_actions.dart @@ -54,8 +54,11 @@ class QuickActions { assert(call.method == 'launch'); handler(call.arguments); }); + runLaunchAction(handler); + } - final String action = await channel.invokeMethod('getPassedIntent'); + void runLaunchAction(QuickActionHandler handler) async { + final String action = await channel.invokeMethod('getLaunchAction'); if (action != null) { handler(action); } diff --git a/packages/quick_actions/test/quick_actions_test.dart b/packages/quick_actions/test/quick_actions_test.dart index 91f500af7fe8..e82611596131 100644 --- a/packages/quick_actions/test/quick_actions_test.dart +++ b/packages/quick_actions/test/quick_actions_test.dart @@ -54,5 +54,17 @@ void main() { isMethodCall('clearShortcutItems', arguments: null), ], ); + log.clear(); + }); + + test('runLaunchAction', () { + quickActions.runLaunchAction(null); + expect( + log, + [ + isMethodCall('runLaunchAction', arguments: null), + ], + ); + log.clear(); }); } From 0cffd7b100a8f280af8afb6f201b5c100467834b Mon Sep 17 00:00:00 2001 From: Samat Gaiazov Date: Sun, 14 Jul 2019 21:52:37 +0200 Subject: [PATCH 6/7] Test fix --- packages/quick_actions/test/quick_actions_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/quick_actions/test/quick_actions_test.dart b/packages/quick_actions/test/quick_actions_test.dart index e82611596131..115efc5786aa 100644 --- a/packages/quick_actions/test/quick_actions_test.dart +++ b/packages/quick_actions/test/quick_actions_test.dart @@ -62,7 +62,7 @@ void main() { expect( log, [ - isMethodCall('runLaunchAction', arguments: null), + isMethodCall('getLaunchAction', arguments: null), ], ); log.clear(); From 48de23dae8bfad847c60c1ef34c9d514ed585675 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 15 Jul 2019 07:21:28 -0700 Subject: [PATCH 7/7] Update CHANGELOG.md --- packages/quick_actions/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/quick_actions/CHANGELOG.md b/packages/quick_actions/CHANGELOG.md index eec568c5dfc1..4251ad7fd347 100644 --- a/packages/quick_actions/CHANGELOG.md +++ b/packages/quick_actions/CHANGELOG.md @@ -1,6 +1,6 @@ ## 0.3.2 -* Fixing the quick actions launch on Android when the app is killed. +* Fixed the quick actions launch on Android when the app is killed. ## 0.3.1