diff --git a/packages/quick_actions/CHANGELOG.md b/packages/quick_actions/CHANGELOG.md index 1afc92af7c06..32e7f860df1f 100644 --- a/packages/quick_actions/CHANGELOG.md +++ b/packages/quick_actions/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.4.0+7 + +* Fixed iOS lifecycle. Quick actions work when the app is running in + the background as well as not running at all + ## 0.4.0+6 * Post-v2 Android embedding cleanup. diff --git a/packages/quick_actions/example/ios/Runner.xcodeproj/project.pbxproj b/packages/quick_actions/example/ios/Runner.xcodeproj/project.pbxproj index fdd275fcede5..338ff6e8f744 100644 --- a/packages/quick_actions/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/quick_actions/example/ios/Runner.xcodeproj/project.pbxproj @@ -9,11 +9,7 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 83C36CAF23D629E5ABE75B2A /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CCC799F2B0AB50A9C34344F0 /* libPods-Runner.a */; }; - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -28,8 +24,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -40,14 +34,12 @@ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 5278439583922091276A37C9 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; @@ -63,8 +55,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 83C36CAF23D629E5ABE75B2A /* libPods-Runner.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -75,9 +65,7 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( - 3B80C3931E831B6300D905FE /* App.framework */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEBA1CF902C7004384FC /* Flutter.framework */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 9740EEB31CF90195004384FC /* Generated.xcconfig */, @@ -229,7 +217,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; @@ -269,9 +257,12 @@ files = ( ); inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${PODS_ROOT}/../Flutter/Flutter.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; diff --git a/packages/quick_actions/example/lib/main.dart b/packages/quick_actions/example/lib/main.dart index fc289810ea24..cc09646daf66 100644 --- a/packages/quick_actions/example/lib/main.dart +++ b/packages/quick_actions/example/lib/main.dart @@ -4,6 +4,7 @@ // ignore_for_file: public_member_api_docs +import 'dart:async'; import 'package:flutter/material.dart'; import 'package:quick_actions/quick_actions.dart'; @@ -32,17 +33,17 @@ class MyHomePage extends StatefulWidget { } class _MyHomePageState extends State { - String shortcut = "no action set"; + final QuickActions quickActions = QuickActions(); @override - void initState() { - super.initState(); + void didChangeDependencies() { + super.didChangeDependencies(); - final QuickActions quickActions = QuickActions(); + print('DidChangeDependencies'); quickActions.initialize((String shortcutType) { - setState(() { - if (shortcutType != null) shortcut = shortcutType; - }); + print('ShortcutType: $shortcutType'); + + _shortcutDialog(context, shortcutType); }); quickActions.setShortcutItems([ @@ -62,16 +63,39 @@ class _MyHomePageState extends State { ]); } + Future _shortcutDialog(BuildContext context, String shortcutType) { + return showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Opened via Actions'), + content: Text('Opened via shortcut: $shortcutType'), + actions: [ + FlatButton( + child: const Text('Ok'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text('$shortcut'), + title: const Text('Flutter Quick Actions Demo'), ), body: const Center( - child: Text('On home screen, long press the app icon to ' - 'get Action one or Action two options. Tapping on that action should ' - 'set the toolbar title.'), + child: Padding( + padding: EdgeInsets.all(32.0), + child: Text('On home screen, long press the app icon to ' + 'get Action one or Action two options. Tapping on that action should ' + 'set the toolbar title.'), + ), ), ); } diff --git a/packages/quick_actions/ios/Classes/FLTQuickActionsPlugin.m b/packages/quick_actions/ios/Classes/FLTQuickActionsPlugin.m index 88ff7397af8a..ab2c5ece9908 100644 --- a/packages/quick_actions/ios/Classes/FLTQuickActionsPlugin.m +++ b/packages/quick_actions/ios/Classes/FLTQuickActionsPlugin.m @@ -8,17 +8,19 @@ @interface FLTQuickActionsPlugin () @property(nonatomic, retain) FlutterMethodChannel *channel; +@property(nonatomic, strong) NSString *shortcutType; @end @implementation FLTQuickActionsPlugin + (void)registerWithRegistrar:(NSObject *)registrar { FlutterMethodChannel *channel = - [FlutterMethodChannel methodChannelWithName:CHANNEL_NAME - binaryMessenger:[registrar messenger]]; + [FlutterMethodChannel methodChannelWithName:CHANNEL_NAME + binaryMessenger:[registrar messenger]]; FLTQuickActionsPlugin *instance = [[FLTQuickActionsPlugin alloc] init]; instance.channel = channel; [registrar addMethodCallDelegate:instance channel:channel]; + [registrar addApplicationDelegate:instance]; } - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { @@ -30,7 +32,9 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result [UIApplication sharedApplication].shortcutItems = @[]; result(nil); } else if ([call.method isEqualToString:@"getLaunchAction"]) { - result(nil); + result(self.shortcutType); // This is used when the app is killed and open the first time via + // quick actions + self.shortcutType = nil; } else { result(FlutterMethodNotImplemented); } @@ -46,9 +50,28 @@ - (void)dealloc { } - (BOOL)application:(UIApplication *)application - performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem - completionHandler:(void (^)(BOOL succeeded))completionHandler - API_AVAILABLE(ios(9.0)) { +WillFinishLaunchingWithOptions: +(NSDictionary *)launchOptions { + if (@available(iOS 9.0, *)) { + UIApplicationShortcutItem *shortcutItem = + launchOptions[UIApplicationLaunchOptionsShortcutItemKey]; + if (shortcutItem != NULL) { + self.shortcutType = shortcutItem.type; + [self.channel invokeMethod:@"launch" arguments:shortcutItem.type]; + return NO; + } else { + [self.channel invokeMethod:@"launch" arguments:nil]; + self.shortcutType = nil; + } + } + return YES; +} + +- (BOOL)application:(UIApplication *)application +performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem + completionHandler:(void (^)(BOOL succeeded))completionHandler +API_AVAILABLE(ios(9.0)) { + self.shortcutType = shortcutItem.type; [self.channel invokeMethod:@"launch" arguments:shortcutItem.type]; return YES; } @@ -57,22 +80,22 @@ - (BOOL)application:(UIApplication *)application NS_INLINE void _setShortcutItems(NSArray *items) API_AVAILABLE(ios(9.0)) { NSMutableArray *newShortcuts = [[NSMutableArray alloc] init]; - + for (id item in items) { UIApplicationShortcutItem *shortcut = _deserializeShortcutItem(item); [newShortcuts addObject:shortcut]; } - + [UIApplication sharedApplication].shortcutItems = newShortcuts; } NS_INLINE UIApplicationShortcutItem *_deserializeShortcutItem(NSDictionary *serialized) - API_AVAILABLE(ios(9.0)) { +API_AVAILABLE(ios(9.0)) { UIApplicationShortcutIcon *icon = - [serialized[@"icon"] isKindOfClass:[NSNull class]] - ? nil - : [UIApplicationShortcutIcon iconWithTemplateImageName:serialized[@"icon"]]; - + [serialized[@"icon"] isKindOfClass:[NSNull class]] + ? nil + : [UIApplicationShortcutIcon iconWithTemplateImageName:serialized[@"icon"]]; + return [[UIApplicationShortcutItem alloc] initWithType:serialized[@"type"] localizedTitle:serialized[@"localizedTitle"] localizedSubtitle:nil diff --git a/packages/quick_actions/pubspec.yaml b/packages/quick_actions/pubspec.yaml index 570c864ffe38..fbfdd4496fd3 100644 --- a/packages/quick_actions/pubspec.yaml +++ b/packages/quick_actions/pubspec.yaml @@ -2,7 +2,7 @@ name: quick_actions description: Flutter plugin for creating shortcuts on home screen, also known as Quick Actions on iOS and App Shortcuts on Android. homepage: https://github.com/flutter/plugins/tree/master/packages/quick_actions -version: 0.4.0+6 +version: 0.4.0+7 flutter: plugin: