如何使用 AirDrop 发送和接收自定义数据

How to send and receive custom data with AirDrop

由于找不到任何详细示例,我已经为此苦苦挣扎了很长时间。

在我的应用程序中,我有一组自定义数据,我想通过 AirDrop 将这些数据发送给使用相同应用程序的另一个用户。

第一步是发送数据:

@IBAction func share_Button_Click(sender: UIBarButtonItem)
{
    let dataToShare: NSData = getMyCustomNSData()

    let controller = UIActivityViewController(activityItems: [dataToShare], applicationActivities: nil)
    controller.excludedActivityTypes = [UIActivityTypePostToFacebook, UIActivityTypePostToTwitter, UIActivityTypePostToWeibo, UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll, UIActivityTypePostToFlickr, UIActivityTypePostToTencentWeibo, UIActivityTypeMail, UIActivityTypeAddToReadingList, UIActivityTypeOpenInIBooks, UIActivityTypeMessage]

    self.presentViewController(controller, animated: true, completion: nil)
}

这会将我的数据转换为 NSData 对象,用户获得 AirDrop 共享选项,并且数据转到另一个 phone。到目前为止一切顺利...

但是其他用户的应用程序如何知道如何接收它?

我已经阅读了自定义 UTI 类型并声明了一个,但老实说我不知道​​在声明中放入什么。你如何向 iOS 表明你发送的数据符合这个特定的 UTI?

网上到处都有 AirDrop 示例,但它们侧重于共享图像等常见类型,我发现没有人详细介绍了自定义数据类型。

有人能帮忙吗?

AirDrop sample code 介绍了如何定义您自己的文件 type/UTI 并使用它通过 AirDrop 发送您的自定义数据。

主要需要的部分如下

  1. 您应用的 Info.plist

    中的以下键和值
    <...>
    <key>CFBundleDocumentTypes</key>
    <array>
    <dict>
        <key>CFBundleTypeName</key>
        <string>AirDrop Profile File Type</string>
        <key>LSHandlerRank</key>
        <string>Default</string>
        <key>LSItemContentTypes</key>
        <array>
            <string>com.apple.customProfileUTI.customprofile</string>
        </array>
    </dict>
    </array>
    <...>
    
  2. 支持接收自定义类型
    在应用程序委托中,通过实现

    处理使用 fileURL 启动

    Objective-C

    - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
    

    Swift

    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        // Check if your app can open the URL
        // If it can, do something with the url and options, then return true
        // otherwise return false
    }
    

    确保 remove/move 文件在 inbox 文件夹中清理,收到的文档就在这个文件夹中(在您的应用程序的沙箱中)。

  3. 支持发送自定义类型
    您传递给 UIActivityViewController 的项目应该是一个 fileURL 到您注册为自定义文件类型的扩展名的文件,或者是一个符合 UIActivityItemSource 协议和 returns NSData 输入

    - (id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController
    

    和你在

    中的实际 NSData blob
    - (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType
    

    然后在以下方法中,您需要 return 您在应用 Info.plist.

    中注册的自定义类型的 UTI
    - (NSString *)activityViewController:(UIActivityViewController *)activityViewController dataTypeIdentifierForActivityType:(NSString *)activityType
    

示例代码很好地说明了如何执行所有这些操作,以及如何通过包含适当大小和裁剪的预览照片来改善整个用户体验。

iOS13(及以上)

如果没有调用AppDelegate中的openurl委托方法

func application(_ app: UIApplication, open url: URL, options [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { ...}

您应该在 SceneDelegate 中使用 openURLContexts:

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    guard let url = URLContexts.first?.url else {return}    
}

然后您可以使用 'url' 在您的应用中执行您需要的操作。