Flutter Engine
 
Loading...
Searching...
No Matches
FlutterNSBundleUtils.mm
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <Foundation/Foundation.h>
8
10
12
13NSString* const kDefaultAssetPath = @"Frameworks/App.framework/flutter_assets";
14
15static NSString* GetFlutterAssetsPathFromBundle(NSBundle* bundle, NSString* relativeAssetsPath);
16
17NSBundle* FLTFrameworkBundleInternal(NSString* flutterFrameworkBundleID, NSURL* searchURL) {
18 NSDirectoryEnumerator<NSURL*>* frameworkEnumerator = [NSFileManager.defaultManager
19 enumeratorAtURL:searchURL
20 includingPropertiesForKeys:nil
21 options:NSDirectoryEnumerationSkipsSubdirectoryDescendants |
22 NSDirectoryEnumerationSkipsHiddenFiles
23 // Skip directories where errors are encountered.
24 errorHandler:nil];
25
26 for (NSURL* candidate in frameworkEnumerator) {
27 NSBundle* flutterFrameworkBundle = [NSBundle bundleWithURL:candidate];
28 if ([flutterFrameworkBundle.bundleIdentifier isEqualToString:flutterFrameworkBundleID]) {
29 return flutterFrameworkBundle;
30 }
31 }
32 return nil;
33}
34
36 NSBundle* mainBundle = NSBundle.mainBundle;
37 // App extension bundle is in <AppName>.app/PlugIns/Extension.appex.
38 if ([mainBundle.bundleURL.pathExtension isEqualToString:@"appex"]) {
39 // Up two levels.
40 return [NSBundle bundleWithURL:mainBundle.bundleURL.URLByDeletingLastPathComponent
41 .URLByDeletingLastPathComponent];
42 }
43 return mainBundle;
44}
45
46NSBundle* FLTFrameworkBundleWithIdentifier(NSString* flutterFrameworkBundleID) {
47 NSBundle* appBundle = FLTGetApplicationBundle();
48 NSBundle* flutterFrameworkBundle =
49 FLTFrameworkBundleInternal(flutterFrameworkBundleID, appBundle.privateFrameworksURL);
50 if (flutterFrameworkBundle == nil) {
51 // Fallback to slow implementation.
52 flutterFrameworkBundle = [NSBundle bundleWithIdentifier:flutterFrameworkBundleID];
53 }
54 if (flutterFrameworkBundle == nil) {
55 flutterFrameworkBundle = NSBundle.mainBundle;
56 }
57 return flutterFrameworkBundle;
58}
59
60NSString* FLTAssetPath(NSBundle* bundle) {
61 return [bundle objectForInfoDictionaryKey:@"FLTAssetsPath"] ?: kDefaultAssetPath;
62}
63
64NSString* FLTAssetsPathFromBundle(NSBundle* bundle) {
65 NSString* relativeAssetsPath = FLTAssetPath(bundle);
66 NSString* flutterAssetsPath = GetFlutterAssetsPathFromBundle(bundle, relativeAssetsPath);
67 if (flutterAssetsPath.length == 0) {
68 flutterAssetsPath = GetFlutterAssetsPathFromBundle(NSBundle.mainBundle, relativeAssetsPath);
69 }
70 return flutterAssetsPath;
71}
72
73static NSString* GetFlutterAssetsPathFromBundle(NSBundle* bundle, NSString* relativeAssetsPath) {
74 // Use the raw path solution so that asset path can be returned from unloaded bundles.
75 // See https://github.com/flutter/engine/pull/46073
76 NSString* assetsPath = [bundle pathForResource:relativeAssetsPath ofType:nil];
77 if (assetsPath.length == 0) {
78 // In app extension, using full relative path (kDefaultAssetPath)
79 // returns nil when the app bundle is not loaded. Try to use
80 // the sub folder name, which can successfully return a valid path.
81 assetsPath = [bundle pathForResource:@"flutter_assets" ofType:nil];
82 }
83 return assetsPath;
84}
NSBundle * FLTFrameworkBundleWithIdentifier(NSString *flutterFrameworkBundleID)
NSString * FLTAssetsPathFromBundle(NSBundle *bundle)
NSBundle * FLTGetApplicationBundle()
static NSString * GetFlutterAssetsPathFromBundle(NSBundle *bundle, NSString *relativeAssetsPath)
NSBundle * FLTFrameworkBundleInternal(NSString *flutterFrameworkBundleID, NSURL *searchURL)
NSString * FLTAssetPath(NSBundle *bundle)
FLUTTER_ASSERT_ARC NSString *const kDefaultAssetPath