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

Commit 20bdf6a

Browse files
Chris Yangharryterkelsen
authored andcommitted
[ios] Fix app extension not able to find assets from unloaded bundle (#46283)
Directly use "flutter_assets" as the default path to find the asset path, this works for app extension when the bundle is unloaded. This PR also adds integration tests for app extensions, which also tests the asset path. Fixes flutter/flutter#124292 [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent 247931d commit 20bdf6a

File tree

32 files changed

+1163
-16
lines changed

32 files changed

+1163
-16
lines changed

shell/platform/darwin/common/framework/Source/FlutterNSBundleUtils.mm

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
FLUTTER_ASSERT_ARC
1010

1111
const NSString* kDefaultAssetPath = @"Frameworks/App.framework/flutter_assets";
12+
static NSString* GetFlutterAssetPathFromBundle(NSBundle* bundle);
1213

1314
NSBundle* FLTFrameworkBundleInternal(NSString* flutterFrameworkBundleID, NSURL* searchURL) {
1415
NSDirectoryEnumerator<NSURL*>* frameworkEnumerator = [NSFileManager.defaultManager
@@ -29,7 +30,7 @@
2930
}
3031

3132
NSBundle* FLTGetApplicationBundle() {
32-
NSBundle* mainBundle = [NSBundle mainBundle];
33+
NSBundle* mainBundle = NSBundle.mainBundle;
3334
// App extension bundle is in <AppName>.app/PlugIns/Extension.appex.
3435
if ([mainBundle.bundleURL.pathExtension isEqualToString:@"appex"]) {
3536
// Up two levels.
@@ -48,7 +49,7 @@
4849
flutterFrameworkBundle = [NSBundle bundleWithIdentifier:flutterFrameworkBundleID];
4950
}
5051
if (flutterFrameworkBundle == nil) {
51-
flutterFrameworkBundle = [NSBundle mainBundle];
52+
flutterFrameworkBundle = NSBundle.mainBundle;
5253
}
5354
return flutterFrameworkBundle;
5455
}
@@ -58,13 +59,23 @@
5859
}
5960

6061
NSString* FLTAssetsPathFromBundle(NSBundle* bundle) {
62+
NSString* flutterAssetsPath = GetFlutterAssetPathFromBundle(bundle);
63+
if (flutterAssetsPath.length == 0) {
64+
flutterAssetsPath = GetFlutterAssetPathFromBundle(NSBundle.mainBundle);
65+
}
66+
return flutterAssetsPath;
67+
}
68+
69+
static NSString* GetFlutterAssetPathFromBundle(NSBundle* bundle) {
6170
NSString* flutterAssetsPath = FLTAssetPath(bundle);
6271
// Use the raw path solution so that asset path can be returned from unloaded bundles.
6372
// See https://github.com/flutter/engine/pull/46073
64-
NSString* assetsPath = [bundle pathForResource:flutterAssetsPath ofType:@""];
65-
73+
NSString* assetsPath = [bundle pathForResource:flutterAssetsPath ofType:nil];
6674
if (assetsPath.length == 0) {
67-
assetsPath = [[NSBundle mainBundle] pathForResource:flutterAssetsPath ofType:@""];
75+
// In app extension, using full relative path (kDefaultAssetPath)
76+
// returns nil when the app bundle is not loaded. Try to use
77+
// the sub folder name, which can successfully return a valid path.
78+
assetsPath = [bundle pathForResource:@"flutter_assets" ofType:nil];
6879
}
6980
return assetsPath;
7081
}

shell/platform/darwin/ios/framework/Source/FlutterDartProjectTest.mm

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ - (void)testFLTAssetsURLFromBundle {
9393
id mockBundle = OCMClassMock([NSBundle class]);
9494
OCMStub([mockBundle objectForInfoDictionaryKey:@"FLTAssetsPath"]).andReturn(@"foo/assets");
9595
NSString* resultAssetsPath = @"path/to/foo/assets";
96-
OCMStub([mockBundle pathForResource:@"foo/assets" ofType:@""]).andReturn(resultAssetsPath);
96+
OCMStub([mockBundle pathForResource:@"foo/assets" ofType:nil]).andReturn(resultAssetsPath);
9797
NSString* path = FLTAssetsPathFromBundle(mockBundle);
9898
XCTAssertEqualObjects(path, @"path/to/foo/assets");
9999
}
@@ -102,9 +102,9 @@ - (void)testFLTAssetsURLFromBundle {
102102
id mockBundle = OCMClassMock([NSBundle class]);
103103
id mockMainBundle = OCMPartialMock([NSBundle mainBundle]);
104104
NSString* resultAssetsPath = @"path/to/foo/assets";
105-
OCMStub([mockBundle pathForResource:@"Frameworks/App.framework/flutter_assets" ofType:@""])
105+
OCMStub([mockBundle pathForResource:@"Frameworks/App.framework/flutter_assets" ofType:nil])
106106
.andReturn(nil);
107-
OCMStub([mockMainBundle pathForResource:@"Frameworks/App.framework/flutter_assets" ofType:@""])
107+
OCMStub([mockMainBundle pathForResource:@"Frameworks/App.framework/flutter_assets" ofType:nil])
108108
.andReturn(resultAssetsPath);
109109
NSString* path = FLTAssetsPathFromBundle(mockBundle);
110110
XCTAssertEqualObjects(path, @"path/to/foo/assets");

0 commit comments

Comments
 (0)