iOS实现App之间的内容分享

作者: SeraZheng | 来源:发表于2015-12-29 15:32 被阅读20876次

    前言

    我们在iOS平台上想要实现不同App之间的内容分享一般有几种常用方式:

    1. 第一种是通过AirDrop实现不同设备的App之间文档和数据的分享;
    2. 第二种是给每个App定义一个URL Scheme,通过访问指定了URL Scheme的一个URL,实现直接访问一个APP;
    3. 第三种是通过UIDocumentInteractionController或者是UIActivityViewController这俩个iOS SDK中封装好的类在App之间发送数据、分享数据和操作数据;
    4. 第四种是通过App Extension,在iOS 8的SDK中提供的扩展新特性实现跨App的数据操作和分享;
    5. 还有一种集成第三方SDK实现的有限个App的数据分享,比如社交平台(QQ,微信,新浪微博等)给我们提供的官方SDK,或者是集成了多个社交平台的ShareSDK组件和友盟分享组件等。

    关于集成第三方SDK的使用,各大平台官网上都有详细的文档说明,因此我们这系列文章主要是来谈谈苹果原生提供的基于iOS SDK的分享技术,同时推荐俩篇苹果开发者中心的文档:Inter-App CommunicationDocument Interaction Programming Topics for iOS。我们的第一篇文章就谈一下如何通过UTI让我们的App支持分享。

    原理

    我在“详解苹果提供的UTI(统一类型标识符)“这篇文章中,详细地讲解了一下UTI(Uniform Type Identifier),一套苹果给我们提供用来在基于Cocoa和Cocoa Touch应用程序中识别实体内容类型的规范,而关于实现内容关联的技术也正是基于这套规范。在iOS和Mac OS开发中,苹果给我们提供了注册文档类型的接口,而这种注册的文档类型是全局的,系统中所有的应用程序和服务都可以侦测到。因此我们通过这个底层侦测,可以使用其他可选的第三方App来预览我们的App中不支持的文档,而且我们还可以通过这个接口在我们的App中打开并处理第三方App的文档。

    如果我们的App可以处理某些类型的实体内容,那么我们就可以在我们项目中的Info.plist文件中进行注册。关于使用哪种类型和UTI,就要参考我在“详解苹果提供的UTI(统一类型标识符)“这篇文章中的讲解。当一个第三方App通过苹果的底层侦测技术检查有哪些App可以处理它所指定的内容类型时,如果我们的App已经注册了这种类型,那么我们的App图标就会显示在其中,并且作为我们自己的App的一个入口。

    主要技术

    主要应用到这种底层侦测的技术有iOS SDK中给我们提供的UIDocumentInteractionControllerUIActivityViewControllerQuick Look 框架。此外,在iOS 8中,苹果又给开发者提供了App Extension,一种更高大上的方式在App之间的实现分享内容。关于UIDocumentInteractionControllerUIActivityViewControllerQuick Look 框架以及App Extension的细节,我计划在后面的文章中详细讲解。这篇文章,我们主要是来谈谈如何注册我们App可用的文档类型以及简单使用我们的App来处理第三方App分享的内容

    注册可用类型

    我们需要在info.plist文件中,添加一个新的属性CFBundleDocumentTypes(实际上输入的是"Document types"),这是一个数组类型的属性,意思就是我们可以同时注册多个类型。而针对数组中的每一个元素,都有许多属性可以指定,详细的属性列表我们可以从官方文档上找到: Core Foundation Keys ---- CFBundleDocumentTypes。这里列举我们在做iOS开发时常用的属性:

    • CFBundleTypeName("Icon File Name")
      字符串类型,指定某种类型的别名,也就是用来指代我们规定的类型的别称,一般为了保持唯一性,我们使用UTI来标识。
    • CFBundleTypeIconFiles
      数组类型,包含指定的png图标的文件名,指定代表某种类型的图标,而图标有具体的尺寸标识:

    |Device |Sizes |
    |:------|:---------|
    |iPad |64 x 64 pixels, 320 x 320 pixels|
    |iPhone and iPod touch|22 x 29 pixels, 44 x 58 pixels (high resolution)|

    • LSItemContentTypes("Document Content Type UTIs")
      数组类型,包含UTI字符串,指定我们的应用程序所有可以识别的类型集合
    • LSHandlerRank("Handler rank")
      字符串类型,包含Owner,Default,Alternate,None四个可选值,指定对于某种类型的优先权级别,而Launcher Service会根据这个优先级别来排列显示的App的顺序。优先级别从高到低依次是OwnerAlternate,DefaultNone表示不接受这种类型。

    了解了这些基本属性,我们就需要在注册App可用类型时,指定这些属性,根据每个项目的需求不同,属性值也不同。具体的注册请参照我的GitHub上的项目:SeraZheng---ZSUTITest。下图示例作为一个参照:

    在info中添加Document types

    而当我们添加完所有属性后,开始运行我们的程序,然后再回到我们的Info界面,就会看到Document types这个列表已经发生了变化,这就证明我们成功的注册好了App可用的类型。

    注册成功,运行程序显示的结果

    打开第三方应用

    我们在上面的步骤中注册好了我们的App可以识别的类型,现在我们可以打开一个使用UIDocumentInteractionController或者是Quick Look框架来展示内容的第三方App,这里以iPhone 上的QQ程序为例。

    我们在上面的注册步骤中,注册的LSItemContentTypes仅包含了public.image这个UTI。所以我们先从QQ应用程序的我的文件中,打开不同类型的文件进行对比,大家可以看下图我的文件列表中包含俩种类型的文件,一种是.jpg扩展名的图片文件,一种是.pdf扩展名的文档文件。

    我的文件列表

    当我打开一个图片文件进行预览时,点击其他应用打开,就可以在App列表中看到我们的App图标。简单介绍一下这个页面,第一行是苹果在iOS 7之后给我们提供的使用AirDropiPhoneiPadiPod Touch设备之间通过iCloud共享内容的一种方式。第二行是通过文档类型关联技术识别的App的列表。第三行是通过文档关联技术识别的Action的列表,Action表示对文档可进行的操作,如复制,打印等。

    打开图片,显示ZSUTITestDemo App图标

    而如果我打开PDF文件的话,就看不到我们的App图标。


    打开PDF文件,看不到ZSUTITestDemo App图标

    程序回调

    当我们通过上面步骤,成功地显示了ZSUTITestDemo 的图标之后,点击图标,我们就可以跳转到ZSUTITestDemo应用中,而苹果在iOS SDK中给我们提供的接收回调的方法在iOS 9之后做出了改变,因此我们需要针对不同的设备版本做出改变:

    #if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_9_0
    - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(id)annotation
    {
        UINavigationController *navigation = (UINavigationController *)application.keyWindow.rootViewController;
        ViewController *displayController = (ViewController *)navigation.topViewController;
        
        [displayController.imageView setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:url]]];
        [displayController.label setText:sourceApplication];
        
        return YES;
    }
    
    #else
    - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(nonnull NSDictionary<NSString *,id> *)options
    {
        UINavigationController *navigation = (UINavigationController *)application.keyWindow.rootViewController;
        ViewController *displayController = (ViewController *)navigation.topViewController;
        
        [displayController.imageView setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:url]]];
        [displayController.label setText:[options objectForKey:UIApplicationOpenURLOptionsSourceApplicationKey]];
        
        return YES;
    }
    #endif
    

    Demo示例可以从GitHub项目上参照代码:SeraZheng---ZSUTITest。当点击ZSUTITestDemo程序图标回到调用代码中,我们可以在这里做各种我们想做的事,如上传图片、预览图片、操作图片等等。我只对图片做了简单的预览显示,然后显示文件的源程序的Bundle Identifier,示例如下图:

    显示图片和源程序的Bundle Identifier

    相关文章

      网友评论

      • dongzhensong:你好,请教,我使用UIDocumentInteractionController做的文件分享,弹出了系统的openin页面,点击"拷贝到'钉钉'"后,没反应了,请问遇到过这个问题吗?
        dongzhensong:@MichelLei 是文件夹的问题,inbox中的文件不能分享
        MichelLei:你好 我也遇到了这个问题。请问你怎么解决的
        dongzhensong:补充: 是inbox中的文件
      • i马:我在QQ里可以分享图片到自己的app 可为什么系统的相册不行?
      • 阿拉斯加的狗:兄弟 我只想问 怎么能用别的APP打开PDF 有我的APP出现呢 要什么参数呢 我都没找到哪个参数 求指教
      • 6080f38d378c:大神,我能请教一个问题吗?就是pdf打开了我的app之后,我需要将这个pdf文档使用我自己的app上传到服务器,请问我需要在回调的方法里写什么呢?
        阿拉斯加的狗:兄弟 我只想问 怎么能用别的APP打开PDF 有我的APP出现呢 要什么参数呢 我都没找到哪个参数 求指教
        飞鱼_all:我想问一下,我从微信分享PDF到我的APP里面后,如果多次分享同一个文件,文件名后面会多个“-”然后跟着数字,每分享一次就加1,应该是做了文件判重了,我想问,怎么能在沙盒里把分享过来的文件删掉
        飞鱼_all:- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(nonnull NSDictionary<NSString *,id> *)options
        在这个方法里拿到数据:
        NSData *data = [NSData dataWithContentsOfURL:url]
        传到服务器就好了嘛
      • 小小看护:请问下,如何做到像QQ那样,我分享一个图片或者链接,都在分享应用里面弹出一个框。
        幻想无极:share extends
      • HoyaWhite:ios 9 好像是有问题的 public.data都不可以出现。。。
      • 608b04cbc9a9:为何我下载运行后,没有任何效果???? 过期失效了吗
      • marko_gu:你好,我下载了你的demo为什么没有效果
      • 素酥:请问下。what app分享。。如何分享图片。文字。链接尼?而不是纯文字纯图片
      • 3790ebb877d1:怎么能让文件链接也能被我们的app接收呢,比如新闻中的链接如何通过系统分享,使自己的app接收到呢,试着public.data接收不到呢
      • 巴图鲁:膜拜
      • H大实诚:怎么能让它出了图片以外的文件也能让我们的app接收呢
        iPhone:@H大实诚 public.image 改成public.data
      • 广锅锅:那么,我想要分享我的数据到其他APP,要怎么做呢?
        SeraZheng:@广锅锅 使用UIActivity或者UIDocument,或者其他App的开放平台
      • 1550e427c1ee:能不能把英文如何转换为汉字的步骤写出来 :smiley:
        8d4bee890bad:@1658786291 你这个问题解决了吗?

      本文标题:iOS实现App之间的内容分享

      本文链接:https://www.haomeiwen.com/subject/rpobhttx.html