diff --git a/shell/platform/darwin/common/framework/Source/FlutterNSBundleUtils.h b/shell/platform/darwin/common/framework/Source/FlutterNSBundleUtils.h index e9c9f323ccb6a..9e0ea22e5fadc 100644 --- a/shell/platform/darwin/common/framework/Source/FlutterNSBundleUtils.h +++ b/shell/platform/darwin/common/framework/Source/FlutterNSBundleUtils.h @@ -48,7 +48,7 @@ NSString* FLTAssetPath(NSBundle* bundle); // If the key is not set, `flutter_assets` is used as the raw path value. // // If no valid asset is found under the raw path, returns nil. -NSURL* FLTAssetsURLFromBundle(NSBundle* bundle); +NSString* FLTAssetsPathFromBundle(NSBundle* bundle); NS_ASSUME_NONNULL_END diff --git a/shell/platform/darwin/common/framework/Source/FlutterNSBundleUtils.mm b/shell/platform/darwin/common/framework/Source/FlutterNSBundleUtils.mm index bf0002d9ade34..4198fd33e0209 100644 --- a/shell/platform/darwin/common/framework/Source/FlutterNSBundleUtils.mm +++ b/shell/platform/darwin/common/framework/Source/FlutterNSBundleUtils.mm @@ -54,15 +54,17 @@ } NSString* FLTAssetPath(NSBundle* bundle) { - return [bundle objectForInfoDictionaryKey:@"FLTAssetsPath"] ?: kDefaultAssetPath; + return [bundle objectForInfoDictionaryKey:@"FLTAssetsPath"] ?: @"flutter_assets"; } -NSURL* FLTAssetsURLFromBundle(NSBundle* bundle) { +NSString* FLTAssetsPathFromBundle(NSBundle* bundle) { NSString* flutterAssetsPath = FLTAssetPath(bundle); - NSURL* assets = [bundle URLForResource:flutterAssetsPath withExtension:nil]; + // Use the raw path solution so that asset path can be returned from unloaded bundles. + // See https://github.com/flutter/engine/pull/46073 + NSString* assetsPath = [bundle pathForResource:flutterAssetsPath ofType:@""]; - if (!assets) { - assets = [[NSBundle mainBundle] URLForResource:flutterAssetsPath withExtension:nil]; + if (assetsPath.length == 0) { + assetsPath = [[NSBundle mainBundle] pathForResource:flutterAssetsPath ofType:@""]; } - return assets; + return assetsPath; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm index 3d434eb2179f2..8a79af3a35742 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm @@ -119,19 +119,20 @@ // Checks to see if the flutter assets directory is already present. if (settings.assets_path.empty()) { - NSURL* assetsURL = FLTAssetsURLFromBundle(bundle); + NSString* assetsPath = FLTAssetsPathFromBundle(bundle); - if (!assetsURL) { + if (assetsPath.length == 0) { NSLog(@"Failed to find assets path for \"%@\"", bundle); } else { - settings.assets_path = assetsURL.path.UTF8String; + settings.assets_path = assetsPath.UTF8String; // Check if there is an application kernel snapshot in the assets directory we could // potentially use. Looking for the snapshot makes sense only if we have a VM that can use // it. if (!flutter::DartVM::IsRunningPrecompiledCode()) { NSURL* applicationKernelSnapshotURL = - [assetsURL URLByAppendingPathComponent:@(kApplicationKernelSnapshotFileName)]; + [NSURL URLWithString:@(kApplicationKernelSnapshotFileName) + relativeToURL:[NSURL fileURLWithPath:assetsPath]]; NSError* error; if ([applicationKernelSnapshotURL checkResourceIsReachableAndReturnError:&error]) { settings.application_kernel_asset = applicationKernelSnapshotURL.path.UTF8String; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProjectTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartProjectTest.mm index a28aaf8beeab9..19774d21bc52c 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProjectTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProjectTest.mm @@ -89,31 +89,24 @@ - (void)testFLTGetApplicationBundleWhenCurrentTargetIsExtension { - (void)testFLTAssetsURLFromBundle { { - // Found asset path in info.plist (even not reachable) + // Found asset path in info.plist id mockBundle = OCMClassMock([NSBundle class]); OCMStub([mockBundle objectForInfoDictionaryKey:@"FLTAssetsPath"]).andReturn(@"foo/assets"); - NSURL* mockAssetsURL = OCMClassMock([NSURL class]); - OCMStub([mockBundle URLForResource:@"foo/assets" withExtension:nil]).andReturn(mockAssetsURL); - OCMStub([mockAssetsURL checkResourceIsReachableAndReturnError:NULL]).andReturn(NO); - OCMStub([mockAssetsURL path]).andReturn(@"foo/assets"); - NSURL* url = FLTAssetsURLFromBundle(mockBundle); - XCTAssertEqualObjects(url.path, @"foo/assets"); + NSString* resultAssetsPath = @"path/to/foo/assets"; + OCMStub([mockBundle pathForResource:@"foo/assets" ofType:@""]).andReturn(resultAssetsPath); + NSString* path = FLTAssetsPathFromBundle(mockBundle); + XCTAssertEqualObjects(path, @"path/to/foo/assets"); } { // No asset path in info.plist, defaults to main bundle id mockBundle = OCMClassMock([NSBundle class]); id mockMainBundle = OCMPartialMock([NSBundle mainBundle]); - NSURL* mockAssetsURL = OCMClassMock([NSURL class]); - OCMStub([mockBundle URLForResource:@"Frameworks/App.framework/flutter_assets" - withExtension:nil]) - .andReturn(nil); - OCMStub([mockAssetsURL checkResourceIsReachableAndReturnError:NULL]).andReturn(NO); - OCMStub([mockAssetsURL path]).andReturn(@"path/to/foo/assets"); - OCMStub([mockMainBundle URLForResource:@"Frameworks/App.framework/flutter_assets" - withExtension:nil]) - .andReturn(mockAssetsURL); - NSURL* url = FLTAssetsURLFromBundle(mockBundle); - XCTAssertEqualObjects(url.path, @"path/to/foo/assets"); + NSString* resultAssetsPath = @"path/to/foo/assets"; + OCMStub([mockBundle pathForResource:@"flutter_assets" ofType:@""]).andReturn(nil); + OCMStub([mockMainBundle pathForResource:@"flutter_assets" ofType:@""]) + .andReturn(resultAssetsPath); + NSString* path = FLTAssetsPathFromBundle(mockBundle); + XCTAssertEqualObjects(path, @"path/to/foo/assets"); } }