From 8f684b79e2b65983daa8ed24572df2bc0ed5c7bd Mon Sep 17 00:00:00 2001 From: hellohuanlin <41930132+hellohuanlin@users.noreply.github.com> Date: Tue, 25 Mar 2025 14:11:46 -0700 Subject: [PATCH] Replace deprecated openURL API call (#164247) This PR replace the deprecated `openURL:` API with equivalent `openURL:options:completionHandler:` API. *List which issues are fixed by this PR. You must list at least one issue. An issue is not required if the PR fixes something trivial like a typo.* https://github.com/flutter/flutter/issues/164047 *If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].* ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [ ] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --- .../framework/Source/FlutterAppDelegate.mm | 4 ++- .../Source/FlutterAppDelegateTest.mm | 28 ++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm index e23d61dcca..c4ef0790cb 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm @@ -164,7 +164,9 @@ static NSString* const kRestorationStateAppModificationKey = @"mod-date"; completionHandler:^(BOOL success) { if (!success && throwBack) { // throw it back to iOS - [UIApplication.sharedApplication openURL:url]; + [UIApplication.sharedApplication openURL:url + options:@{} + completionHandler:nil]; } }]; } else { diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegateTest.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegateTest.mm index 79352d6589..df9e7c9b43 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegateTest.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegateTest.mm @@ -15,7 +15,7 @@ FLUTTER_ASSERT_ARC @interface FlutterAppDelegateTest : XCTestCase @property(strong) FlutterAppDelegate* appDelegate; - +@property(strong) FlutterViewController* viewController; @property(strong) id mockMainBundle; @property(strong) id mockNavigationChannel; @@ -37,6 +37,8 @@ FLUTTER_ASSERT_ARC self.appDelegate = appDelegate; FlutterViewController* viewController = OCMClassMock([FlutterViewController class]); + self.viewController = viewController; + FlutterMethodChannel* navigationChannel = OCMClassMock([FlutterMethodChannel class]); self.mockNavigationChannel = navigationChannel; @@ -172,4 +174,28 @@ FLUTTER_ASSERT_ARC OCMVerifyAll(self.mockNavigationChannel); } +- (void)testUseNonDeprecatedOpenURLAPI { + OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"]) + .andReturn(@YES); + NSUserActivity* userActivity = [[NSUserActivity alloc] initWithActivityType:@"com.example.test"]; + userActivity.webpageURL = [NSURL URLWithString:@"http://myApp/custom/route?query=nonexist"]; + OCMStub([self.viewController sendDeepLinkToFramework:[OCMArg any] completionHandler:[OCMArg any]]) + .andDo(^(NSInvocation* invocation) { + void (^handler)(BOOL success); + [invocation getArgument:&handler atIndex:3]; + handler(NO); + }); + id mockApplication = OCMClassMock([UIApplication class]); + OCMStub([mockApplication sharedApplication]).andReturn(mockApplication); + BOOL result = [self.appDelegate + application:[UIApplication sharedApplication] + continueUserActivity:userActivity + restorationHandler:^(NSArray>* __nullable restorableObjects){ + }]; + XCTAssertTrue(result); + OCMVerify([mockApplication openURL:[OCMArg any] + options:[OCMArg any] + completionHandler:[OCMArg any]]); +} + @end