据我所知,大多数颤振指南都可以从本地存储中打开,但与文件共享无关。任何人都知道如何做到这一点。这是专门为 ios https://developer.apple.com/library/archive/qa/qa1587/_index.html启用它的指南。
我的意思是有https://pub.dartlang.org/packages/open_file扩展名,但从文件存储中打开。
澄清这个问题不是关于与另一个应用程序共享文件,而是当从外部应用程序共享时被提示在这个颤振应用程序中打开。
据我所知,大多数颤振指南都可以从本地存储中打开,但与文件共享无关。任何人都知道如何做到这一点。这是专门为 ios https://developer.apple.com/library/archive/qa/qa1587/_index.html启用它的指南。
我的意思是有https://pub.dartlang.org/packages/open_file扩展名,但从文件存储中打开。
澄清这个问题不是关于与另一个应用程序共享文件,而是当从外部应用程序共享时被提示在这个颤振应用程序中打开。
要在 iOS 中执行此操作,您首先按照您提到的指南中的描述在 XCode 中定义文档类型和导入的 UTI,然后在您的 AppDelegate.m 文件中执行以下操作:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
/* custom code begin */
FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;
FlutterMethodChannel* myChannel = [FlutterMethodChannel
methodChannelWithName:@"my/file"
binaryMessenger:controller];
__block NSURL *initialURL = launchOptions[UIApplicationLaunchOptionsURLKey];
[myChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
if ([@"checkintent" isEqualToString:call.method]) {
if (initialURL) {
[myChannel invokeMethod:@"loaded" arguments: [initialURL absoluteString]];
initialURL = nil;
result(@TRUE);
}
}
}];
/* custom code end */
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
在飞镖方面:
class PlayTextPageState extends State<MyHomePage> with WidgetsBindingObserver{
static const platform = const MethodChannel('my/file');
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
platform.setMethodCallHandler((MethodCall call) async {
String method = call.method;
if (method == 'loaded') {
String path = call.arguments; // this is the path
...
}
});
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.paused) {
...
} else if (state == AppLifecycleState.resumed) {
platform.invokeMethod("checkintent")
.then((result) {
// result == 1 if the app was opened with a file
});
}
}
}
添加到 lastant 的答案,您实际上还需要覆盖 AppDelegate.swift 中的 application(_:open:options:) 才能使其正常工作。
所以想法是在 iOS 中使用 UIActivityViewController 在 Flutter 中打开文件(例如:从电子邮件将 SQL DB 的备份恢复到 Flutter 应用程序中)。
首先,您需要在 info.plist 中设置 UTI。这是一个很好的链接来解释它是如何工作的。https://www.raywenderlich.com/813044-uiactivityviewcontroller-tutorial-sharing-data
其次,在 AppDelegate.swift 中添加通道控制器代码。
我们还需要在 AppDelegate.swift 中覆盖 application(:open:options:),因为当外部应用程序想要向您的应用程序发送文件时,iOS 会调用 application(:open:options:)。因此,我们将文件名作为变量存储在 AppDelegate 中。
这里我们在 iOS 和 Flutter 之间有一个 2-way 通道控制器。每次 Flutter 应用程序进入 AppLifecycleState.resumed 状态时,它都会调用“checkIntent”来检查 AppDelegate 是否已设置文件名。如果已设置文件名,AppDelegate 将在颤振中调用“加载”方法,您可以对文件进行所需的处理。
完成处理后,请记住从 AppDelegate 中删除给您的文件。否则,它将使您的应用程序膨胀。
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
var initialURL: URL?
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
/* channel controller code */
let controller: FlutterViewController = self.window?.rootViewController as! FlutterViewController
let myChannel = FlutterMethodChannel(name: "my/file", binaryMessenger: controller.binaryMessenger)
myChannel.setMethodCallHandler({(call: FlutterMethodCall, result: @escaping FlutterResult)-> Void in
if(call.method == "checkintent"){
if(self.initialURL != nil){
myChannel.invokeMethod("loaded", arguments: self.initialURL?.absoluteString );
self.initialURL = nil;
result(true);
} else{
print("initialURL is null");
}
} else{
print("no such channel method");
}
});
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
print("import URL: \(url)");
initialURL = url;
// should not remove here.. remove after i get into flutter...
// try? FileManager.default.removeItem(at: url);
return true;
}
}