【问题标题】:Opening custom file from iCloud into Xamarin.iOS app doesn't work从 iCloud 打开自定义文件到 Xamarin.iOS 应用程序不起作用
【发布时间】:2021-05-18 17:01:29
【问题描述】:

我们有 Xamarin.iOS 应用程序,它声明了一个自定义文件扩展名 - *.msoisalesbak 作为导出类型声明

<key>UTExportedTypeDeclarations</key>
<array>
    <dict>
        <key>UTTypeIdentifier</key>
        <string>com.ewsgroup.msoisalesbak</string>
        <key>UTTypeConformsTo</key>
        <array>
            <string>com.pkware.zip-archive</string>
        </array>
        <key>UTTypeTagSpecification</key>
        <dict>
            <key>public.filename-extension</key>
            <string>msoisalesbak</string>
        </dict>
        <key>UTTypeDescription</key>
        <string>MSO&amp;I Sales application backup file</string>
    </dict>
</array>

这意味着,每当 iOS 系统检测到具有此扩展名的文件时,它将提供在我们的应用程序中打开此文件的可能性。

此外,在我们的AppDelegate 中,我们有这样的代码来处理委派文件共享:

public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
    ..................
    var fileHandlerService = ServiceLocator.Container.Resolve<IAssociatedFileHandlerService>();
    if(fileHandlerService.CanRestoreDatabaseFromOpenedAssociatedBackupFile(url))
    {
        ...................
        string filePath = url.Path;
        var destinationPath = "PATH_TO_APP_INTERNAL_FOLDER"
        using(FileStream sourceStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        using(FileStream destinationStream = File.Create(destinationPath))
        {
            sourceStream.CopyTo(destinationStream);
        }
        ....................
        return true;
    }

    return false;
}

我们基本上会仔细检查文件是否有效以及我们可以处理的内容,然后尝试将文件复制到内部存储并进行一些额外的处理,这与此问题无关。

现在,我们创建应用程序支持的自定义文件并将其放入 iCloud 下载文件夹。当我们单击该文件时,我们的应用程序成功打开,OpenUrl 委托被成功调用。但是,这样做我们会收到以下异常

System.IO.DirectoryNotFoundException: Could not find a part of the path "/private/var/mobile/Library/Mobile Documents/com~apple~CloudDocs/Downloads/637569517947945130-0.12.1.msoisalesbak".
  at System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.Boolean anonymous, System.IO.FileOptions options) [0x00177]

这意味着,出于某种原因,OpenUrl 收到的路径对于我们的应用程序来说是不可访问的。

事实上,OpenUrl 工作正常,如果我们在电子邮件中有自定义文件,或者我们从其他应用程序(例如聊天应用程序(例如 Microsoft Teams))打开自定义文件。但是,它不适用于 iCloud。

我们是否应该特别注意允许访问 iCloud 文件夹?我们错过了什么?

【问题讨论】:

  • 您是否调用了“startAccessingSecurityScopedResource”?并尝试修改 info.plist 中的“LSSupportsOpeningDocumentsInPlace”。
  • 只是好奇,没有异步你怎么有等待?
  • @IvanIčin 复制粘贴....该代码实际上不在该方法中:) 为简洁起见。我将让方法异步化以消除混乱!感谢您的关注
  • @KyleWang-MSFT 确实,添加 url.startAccessingSecurityScopedResource() 解决了这个问题。非常感谢。为了给你一个信用,你想创建一个答案,而不是我回答我自己的问题吗?
  • @KyleWang-MSFT 另一个观察结果。您可以简单地将 LSSupportsOpeningDocumentsInPlace 设置为 false,而不是使用 url.startAccessingSecurityScopedResource(),这将导致文件将被复制到临时位置,然后我的应用程序将像以前一样继续工作。我实际上依赖于它是一个临时文件这一事实,因为我们在处理文件后删除了 URL 路径。因此,在我的情况下,将 LSSupportsOpeningDocumentsInPlace 设置为 false 就足以解决问题。

标签: c# ios xamarin xamarin.forms icloud


【解决方案1】:

在从 iCloud“解锁”文件之前,您需要调用 startAccessingSecurityScopedResource 以使应用程序可以使用安全范围 URL 所指向的资源。然后别忘了拨打stopAccessingSecurityScopedResource

您还可以在 Info.plist 文件中创建一个新的布尔键 LSSupportsOpeningDocumentsInPlace。如果将其设置为 true,则 url 将指向 iCloud 中的文件,但尚未下载。所以你无法访问该文件。如果将其设置为 false,它将在应用程序沙箱中复制文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-29
    • 1970-01-01
    • 2015-10-04
    • 2017-07-20
    • 1970-01-01
    • 2012-11-19
    • 1970-01-01
    相关资源
    最近更新 更多