| Flutter iOS Embedder |

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
5 #include <Foundation/Foundation.h>
6
7 #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
8
9 FLUTTER_ASSERT_ARC
10
11 const NSString* kDefaultAssetPath = @"Frameworks/App.framework/flutter_assets";
12 static NSString* GetFlutterAssetsPathFromBundle(NSBundle* bundle, NSString* relativeAssetsPath);
13
14 NSBundle* FLTFrameworkBundleInternal(NSString* flutterFrameworkBundleID, NSURL* searchURL) {
15 NSDirectoryEnumerator<NSURL*>* frameworkEnumerator = [NSFileManager.defaultManager
16 enumeratorAtURL:searchURL
17 includingPropertiesForKeys:nil
18 options:NSDirectoryEnumerationSkipsSubdirectoryDescendants |
19 NSDirectoryEnumerationSkipsHiddenFiles
20 // Skip directories where errors are encountered.
21 errorHandler:nil];
22
23 for (NSURL* candidate in frameworkEnumerator) {
24 NSBundle* flutterFrameworkBundle = [NSBundle bundleWithURL:candidate];
25 if ([flutterFrameworkBundle.bundleIdentifier isEqualToString:flutterFrameworkBundleID]) {
26 return flutterFrameworkBundle;
27 }
28 }
29 return nil;
30 }
31
32 NSBundle* FLTGetApplicationBundle() {
33 NSBundle* mainBundle = NSBundle.mainBundle;
34 // App extension bundle is in <AppName>.app/PlugIns/Extension.appex.
35 if ([mainBundle.bundleURL.pathExtension isEqualToString:@"appex"]) {
36 // Up two levels.
37 return [NSBundle bundleWithURL:mainBundle.bundleURL.URLByDeletingLastPathComponent
38 .URLByDeletingLastPathComponent];
39 }
40 return mainBundle;
41 }
42
43 NSBundle* FLTFrameworkBundleWithIdentifier(NSString* flutterFrameworkBundleID) {
44 NSBundle* appBundle = FLTGetApplicationBundle();
45 NSBundle* flutterFrameworkBundle =
46 FLTFrameworkBundleInternal(flutterFrameworkBundleID, appBundle.privateFrameworksURL);
47 if (flutterFrameworkBundle == nil) {
48 // Fallback to slow implementation.
49 flutterFrameworkBundle = [NSBundle bundleWithIdentifier:flutterFrameworkBundleID];
50 }
51 if (flutterFrameworkBundle == nil) {
52 flutterFrameworkBundle = NSBundle.mainBundle;
53 }
54 return flutterFrameworkBundle;
55 }
56
57 NSString* FLTAssetPath(NSBundle* bundle) {
58 return [bundle objectForInfoDictionaryKey:@"FLTAssetsPath"] ?: kDefaultAssetPath;
59 }
60
61 NSString* FLTAssetsPathFromBundle(NSBundle* bundle) {
62 NSString* relativeAssetsPath = FLTAssetPath(bundle);
63 NSString* flutterAssetsPath = GetFlutterAssetsPathFromBundle(bundle, relativeAssetsPath);
64 if (flutterAssetsPath.length == 0) {
65 flutterAssetsPath = GetFlutterAssetsPathFromBundle(NSBundle.mainBundle, relativeAssetsPath);
66 }
67 return flutterAssetsPath;
68 }
69
70 static NSString* GetFlutterAssetsPathFromBundle(NSBundle* bundle, NSString* relativeAssetsPath) {
71 // Use the raw path solution so that asset path can be returned from unloaded bundles.
72 // See https://github.com/flutter/engine/pull/46073
73 NSString* assetsPath = [bundle pathForResource:relativeAssetsPath ofType:nil];
74 if (assetsPath.length == 0) {
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];
79 }
80 return assetsPath;
81 }
FLTFrameworkBundleWithIdentifier
NSBundle * FLTFrameworkBundleWithIdentifier(NSString *flutterFrameworkBundleID)
Definition: FlutterNSBundleUtils.mm:43
FLTFrameworkBundleInternal
NSBundle * FLTFrameworkBundleInternal(NSString *flutterFrameworkBundleID, NSURL *searchURL)
Definition: FlutterNSBundleUtils.mm:14
GetFlutterAssetsPathFromBundle
static NSString * GetFlutterAssetsPathFromBundle(NSBundle *bundle, NSString *relativeAssetsPath)
Definition: FlutterNSBundleUtils.mm:70
FlutterMacros.h
FLTAssetPath
NSString * FLTAssetPath(NSBundle *bundle)
Definition: FlutterNSBundleUtils.mm:57
FLTAssetsPathFromBundle
NSString * FLTAssetsPathFromBundle(NSBundle *bundle)
Definition: FlutterNSBundleUtils.mm:61
kDefaultAssetPath
const FLUTTER_ASSERT_ARC NSString * kDefaultAssetPath
Definition: FlutterNSBundleUtils.mm:11
FLTGetApplicationBundle
NSBundle * FLTGetApplicationBundle()
Definition: FlutterNSBundleUtils.mm:32
FLUTTER_ASSERT_ARC
Definition: FlutterChannelKeyResponder.mm:13