Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit e2844d2

Browse files
authored
[quick_actions] handle cold start on iOS correctly (#3811)
1 parent e52725a commit e2844d2

File tree

5 files changed

+80
-5
lines changed

5 files changed

+80
-5
lines changed

packages/quick_actions/quick_actions/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.6.0+1
2+
3+
* Correctly handle iOS Application lifecycle events on cold start of the App.
4+
15
## 0.6.0
26

37
* Migrate to federated architecture.

packages/quick_actions/quick_actions/example/ios/Runner/AppDelegate.m

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ - (BOOL)application:(UIApplication *)application
1111
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
1212
[GeneratedPluginRegistrant registerWithRegistry:self];
1313
// Override point for customization after application launch.
14-
return [super application:application didFinishLaunchingWithOptions:launchOptions];
14+
[super application:application didFinishLaunchingWithOptions:launchOptions];
15+
return NO;
1516
}
16-
1717
@end

packages/quick_actions/quick_actions/example/ios/RunnerUITests/RunnerUITests.m

+39-1
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,45 @@ - (void)setUp {
1818
self.continueAfterFailure = NO;
1919
}
2020

21-
- (void)testQuickAction {
21+
- (void)testQuickActionWithFreshStart {
2222
XCUIApplication *app = [[XCUIApplication alloc] init];
2323
[app launch];
24+
[app terminate];
25+
26+
XCUIApplication *springboard =
27+
[[XCUIApplication alloc] initWithBundleIdentifier:@"com.apple.springboard"];
28+
XCUIElement *quickActionsAppIcon = springboard.icons[@"quick_actions_example"];
29+
if (![quickActionsAppIcon waitForExistenceWithTimeout:kElementWaitingTime]) {
30+
os_log_error(OS_LOG_DEFAULT, "%@", springboard.debugDescription);
31+
XCTFail(@"Failed due to not able to find the example app from springboard with %@ seconds",
32+
@(kElementWaitingTime));
33+
}
34+
35+
[quickActionsAppIcon pressForDuration:2];
36+
XCUIElement *actionTwo = springboard.buttons[@"Action two"];
37+
if (![actionTwo waitForExistenceWithTimeout:kElementWaitingTime]) {
38+
os_log_error(OS_LOG_DEFAULT, "%@", springboard.debugDescription);
39+
XCTFail(@"Failed due to not able to find the actionTwo button from springboard with %@ seconds",
40+
@(kElementWaitingTime));
41+
}
42+
43+
[actionTwo tap];
44+
45+
XCUIElement *actionTwoConfirmation = app.otherElements[@"action_two"];
46+
if (![actionTwoConfirmation waitForExistenceWithTimeout:kElementWaitingTime]) {
47+
os_log_error(OS_LOG_DEFAULT, "%@", springboard.debugDescription);
48+
XCTFail(@"Failed due to not able to find the actionTwoConfirmation in the app with %@ seconds",
49+
@(kElementWaitingTime));
50+
}
51+
XCTAssertTrue(actionTwoConfirmation.exists);
52+
53+
[app terminate];
54+
}
55+
56+
- (void)testQuickActionWhenAppIsInBackground {
57+
XCUIApplication *app = [[XCUIApplication alloc] init];
58+
[app launch];
59+
2460
XCUIElement *actionsReady = app.otherElements[@"actions ready"];
2561
if (![actionsReady waitForExistenceWithTimeout:kElementWaitingTime]) {
2662
os_log_error(OS_LOG_DEFAULT, "%@", app.debugDescription);
@@ -56,6 +92,8 @@ - (void)testQuickAction {
5692
@(kElementWaitingTime));
5793
}
5894
XCTAssertTrue(actionOneConfirmation.exists);
95+
96+
[app terminate];
5997
}
6098

6199
@end

packages/quick_actions/quick_actions/ios/Classes/FLTQuickActionsPlugin.m

+34-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
@interface FLTQuickActionsPlugin ()
1010
@property(nonatomic, retain) FlutterMethodChannel *channel;
11+
@property(nonatomic, retain) NSString *shortcutType;
1112
@end
1213

1314
@implementation FLTQuickActionsPlugin
@@ -50,12 +51,44 @@ - (BOOL)application:(UIApplication *)application
5051
performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem
5152
completionHandler:(void (^)(BOOL succeeded))completionHandler
5253
API_AVAILABLE(ios(9.0)) {
53-
[self.channel invokeMethod:@"launch" arguments:shortcutItem.type];
54+
[self handleShortcut:shortcutItem.type];
5455
return YES;
5556
}
5657

58+
- (BOOL)application:(UIApplication *)application
59+
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
60+
if (@available(iOS 9.0, *)) {
61+
UIApplicationShortcutItem *shortcutItem =
62+
launchOptions[UIApplicationLaunchOptionsShortcutItemKey];
63+
if (shortcutItem) {
64+
// Keep hold of the shortcut type and handle it in the
65+
// `applicationDidBecomeActure:` method once the Dart MethodChannel
66+
// is initialized.
67+
self.shortcutType = shortcutItem.type;
68+
69+
// Return NO to indicate we handled the quick action to ensure
70+
// the `application:performActionFor:` method is not called (as
71+
// per Apple's documentation:
72+
// https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622935-application?language=objc).
73+
return NO;
74+
}
75+
}
76+
return YES;
77+
}
78+
79+
- (void)applicationDidBecomeActive:(UIApplication *)application {
80+
if (self.shortcutType) {
81+
[self handleShortcut:self.shortcutType];
82+
self.shortcutType = nil;
83+
}
84+
}
85+
5786
#pragma mark Private functions
5887

88+
- (void)handleShortcut:(NSString *)shortcut {
89+
[self.channel invokeMethod:@"launch" arguments:shortcut];
90+
}
91+
5992
NS_INLINE void _setShortcutItems(NSArray *items) API_AVAILABLE(ios(9.0)) {
6093
NSMutableArray<UIApplicationShortcutItem *> *newShortcuts = [[NSMutableArray alloc] init];
6194

packages/quick_actions/quick_actions/pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: quick_actions
22
description: Flutter plugin for creating shortcuts on home screen, also known as
33
Quick Actions on iOS and App Shortcuts on Android.
44
homepage: https://github.com/flutter/plugins/tree/master/packages/quick_actions
5-
version: 0.6.0
5+
version: 0.6.0+1
66

77
flutter:
88
plugin:

0 commit comments

Comments
 (0)