Общий доступ к файлам в Flutter iOS - не удается открыть общий файл

Я создаю приложение Flutter для iOS. Я создал тип файла, которым мое приложение и другое приложение могут совместно использовать. Для этого я использую библиотеку flutter receive_sharing_intent. Чтобы проверить это, я внес все необходимые изменения в свой файл info.plist для обработки моего пользовательского типа файла, я поместил образец файла этого типа в папку загрузок своего устройства (тестирование на ipad) и щелкнул по нему. оттуда, чтобы открыть его в моем приложении. ОС знает, что мое приложение может с этим справиться. Итак, мое приложение открывается, оно получает путь к общему файлу, но мое приложение не может открыть файл. Вот код в моем main.dart, который обрабатывает прием файла:

StreamSubscription _intentDataStreamSubscription =
    ReceiveSharingIntent.getTextStream().listen((String value) {
      setState(() {
        try{

        //This was added to test and make sure the directory actually exists. 
        //The value for the directory path was added after I ran it once to capture where the shared file was coming from.
        Directory dir = Directory("/private/var/mobile/Containers/Shared/AppGroup/7DD4B316-3D73-4339-9B11-7516DE52F6FC/File Provider Storage/Downloads/");
        bool dirExists = dir.existsSync();
        
        var files = dir.listSync();
        File drawingFile = File.fromUri(Uri.parse(value));
        bool fileExists = drawingFile.existsSync();

        var contents = drawingFile.readAsStringSync();
        DrawingCanvas canvas = DrawingCanvas.fromFileContents(contents);
        DrawingCanvasBloc canvasBloc = DrawingCanvasBloc(canvas);

        Navigator.of(context).push(MaterialPageRoute(builder: (context) => CanvasScreen(canvasBloc)));
        }
        catch(e){
          log(e.toString());
        }
      });
    }, onError: (err) {
      print("getLinkStream error: $err");
    });

Сценарий: запускаю приложение. Захожу в папку загрузок в файлах на айпаде. Я выбираю свой файл example.fbg, расположенный там (мой собственный тип файла). Мое приложение открывается.

В приведенном выше коде он взрывается, когда я пытаюсь перечислить содержимое каталога. Я поместил это здесь (предварительно определив путь к каталогу и жестко его закодировав), чтобы проверить, чтобы убедиться, что я получил правильное местоположение. dirExists верно, но я не могу перечислить в нем файлы. Я получаю следующее сообщение об ошибке:

FileSystemException: Directory listing failed, path = '/private/var/mobile/Containers/Shared/AppGroup/7DD4B316-3D73-4339-9B11-7516DE52F6FC/File Provider Storage/Downloads/' (OS Error: Operation not permitted, errno = 1)

Если я возьму эту строку и продолжу до открытия файла (readAsStringSync), я получу:

FileSystemException: Cannot open file, path = '/private/var/mobile/Containers/Shared/AppGroup/7DD4B316-3D73-4339-9B11-7516DE52F6FC/File Provider Storage/Downloads/example.fbg' (OS Error: Operation not permitted, errno = 1)

Я не уверен, почему он не позволяет мне получить доступ к этому файлу. Есть ли какие-то разрешения, которые мне не хватает? Дайте мне знать, если мне нужно включить дополнительную информацию в вопрос, и я обновлю.


person mac    schedule 10.12.2020    source источник


Ответы (1)


Наконец нашел работу и заставил ее работать с помощью этот ответ. В итоге я открыл файл в делегате приложения, сохранил файл в каталоге документов приложений, а затем передал этот URL-адрес в приложение Flutter. Я открыл модуль iOS в xcode и изменил AppDelegate.swift на следующее:

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
 ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    var drawingFilename = ""
    do {
        let isAcccessing = url.startAccessingSecurityScopedResource()
        var error: Error? = nil
        let path = url.path
        
        let string = try String(contentsOf: url)
        drawingFilename = (url.path as NSString).lastPathComponent
        print(drawingFilename)
       
        let filename = getDocumentsDirectory().appendingPathComponent(drawingFilename)

        do {
            try string.write(to: filename, atomically: true, encoding: String.Encoding.utf8)
        } catch {
            // failed to write file – bad permissions, bad filename, missing permissions, or more likely it can't be converted to the encoding
        }
        if isAcccessing {
            url.stopAccessingSecurityScopedResource()
        }
      if #available(iOS 9.0, *) {
          return super.application(app, open: filename, options: options)
      } else {
         return false
      }
    } catch {
        print("Unable to load data: \(error)")
        return false
    }

    
      
}

func getDocumentsDirectory() -> URL {
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    return paths[0]
}
}

Надеюсь, это поможет кому-то в будущем.

person mac    schedule 11.12.2020