外部打开文件,例如在ios上“打开”

时间:2019-01-17 23:56:29

标签: android ios file flutter external-application

据我所知,大多数抖动指南都可以从本地存储中打开,但是文件共享一无所获。任何人都知道该怎么做。这是专门针对ios https://developer.apple.com/library/archive/qa/qa1587/_index.html启用它的指南。

我的意思是扩展名为https://pub.dartlang.org/packages/open_file,但是从文件存储中打开。

要澄清这个问题,不是要与另一个应用程序共享文件,而是要从外部应用程序共享文件时,系统会提示您在此flutter应用程序中打开文件。

2 个答案:

答案 0 :(得分:0)

要在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];
}

在Dart一侧:

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
        });
    }
  }
}

答案 1 :(得分:0)

添加到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路通道控制器。每次Flutter应用程序进入AppLifecycleState.resumed状态时,它都会调用“ checkIntent”以签回到AppDelegate来查看文件名是否已设置。如果已设置文件名,AppDelegate将在flutter中调用“ load”方法,从而对文件进行所需的处理。

完成处理后,请记住从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;
  }

}