一、前言
对于一个 App 而言,分享是一个比较常见的功能。分享的主要功能,还是为了让 App 在用户之间形成一个自传播的效果,但是对于开发者而言,分享就是在不同的 App 之间,传递文本、文件等数据。
如果只是简单的分享内容,使用 ACTION_SEND 或者 ACTION_SEND_MULTIPLE 可能是一种简单的方式。可是从 Support v4 22.0.0 开始,引入了一个新的分享兼容库,ShareCompat ,它可以帮开发者更轻松的构造一个分享的 Intent 。
二、ShareCompat
2.1 什么是 ShareCompat
ShareCompat 可以帮助我们快速的实现应用间分享的数据的功能。既然是一个完整的功能,它主要包含了两个功能:快速的构建一个分享的 Intent,快速的读取别的 App 内分享来的内容。
所以,ShareCompat 是包含两部分内容的:IntentBuilder 、IntentReader。从名称上就可以看出来他们的用途。
2.2 分享文本
从最简单的开始,使用 IntentBuilder 分享一个纯文本,是非常简单的,IntentBuilder 从名称也能看出来,它是 Builder 模式,所以可以支持多个方法链式调用。
其中最重要的是,设置一个正确的 mimeType,它将是用于 Intent-filter 过滤器重要的过滤条件,表示这里知识分享一个纯文本的类型的内容。
在 startActivity()
之前,调用 resolveActivity()
做一层校验,是一个比较常规的保护措施。它避免了当前系统中没有任何 App 可以匹配上这个隐式的 Intent,而触发 ActivityNotFoundException 的异常。虽然没有可以接收 text/plain 类型的分享其实是非常不可能的,但是加上它也是一个很好的编码习惯。
2.3 分享 HTML 格式的文本
有一些 App ,例如 电子邮件客户端,是可以支持 HTML 格式的文本的,与纯文本相比,它可以显示更丰富的内容。
可以注意到,区别就在于 setType()
的时候,填写的是 text/html ,并且使用的是 setHtmlText()
方法去配置分享的内容。
既然分享 Html 内容,多用于发送 Email 内容,所以这里也配置了接收的邮件地址。
一般而言,使用 Html 的方式还需要接收分享内容的 App 支持这样的内容,所以还是需要谨慎使用,可能用户分享的 App ,并不能很好的显示我们需要分享的 Html 的内容。
2.4 发送一个Email
前面也提到如何在发送的 Email 中,添加一个 Html 的内容。而 ShareCompat 也提供了非常好的发送 Email 的体验,可以非常方便的构造一个用于发送 Email 的 Intent。
IntentBuilder 中,提供了非常方便的 Api,用于添加一些 Email 收件人、抄送之类的数据,都在 addEmailXxx()
的方法中,非常好理解,有兴趣的可以直接看看 Api 文档。
2.5 收一个文本内容
虽然大多数情况下,我们是需要开发一个支持分享的功能,但是也不影响我们了解如何接收一个分享的内容。
而分享传递过来的内容,都是可以在 Intent 中获取到的。而 IntentReader 也提供了非常便捷的 Api 让我们快速的拿到它的内容。
这里以接收一个文本内容为例,首先需要在 AndroidManifest.xml
中配置接收的 Activity 和 Intent-filter。
这就是一个比较常规的 ShareActivity 的配置。
IntentReader 使用起来也非常的简单,它实际上就是一个 Intent 数据的包装器,提供了很多方便的 Api ,从 Intent 中提取出我们需要的数据。
2.6 分享文件和图片
除了分享一段文本内容之外,有时候我们还需要向外分享一个文件(包括视频、图片等)。而发送这些,就需要具有额外的权限。
构造一个图片的分享也非常的简单,只需要使用 setStream()
方法,传递一个文件的 Uri 即可,并且配置好对应的 mimeType。
但是这种方式,就需要考虑到 Android 6.0 开始对分享的文件,以严格模式进行处理,所以对此我们需要使用 FileProvider 来支持。
有关 FileProvider 的内容,可以看看之前的文章:
一旦使用上 FileProvider 只需要将 Uri 替换成 FileProvider.getUriForFile()
返回的 Uri 即可,这都是 FileProvider 的标准内容,就不在这里详细说明了。
不过有一点需要特别注意的,使用 FileProvider 返回的 Uri ,就可以不用显式的设定 mimeType 类型了,因为它是可以通过这个 Uri 推断出正确的 mimeType 的类型的,所以就不需要显式的指定了。
2.7 接收文件内容
Android 6.0 对文件的接收,并没有任何的改变,所以我们只需要使用 IntentReader.getStream()
这个标准的 Api 就可以拿到分享过来的 Uri。
三、ShareCompat 都兼容了什么
Support v4 包下的库,其实都是为了向 Android 低版本做兼容而努力的,让开发者无需关注他们之间的差异,而通常我们看到一个类的命名中,有 Compat 字样,一般就可以断定,它又是一个兼容库。
那么 ShareCompat 对不同的 Android 版本,有做什么兼容处理呢?
ShareCompat 中,有一个静态的 ShareCompatImpl 对象,它就是为了出来兼容问题的,它是一个接口,先来看看它的定义。
可以看到,它实际上就是对 configureMenuItem()
和 html 的文本转义,做了兼容的处理。
在 ShareCompat 的静态代码块中,对其进行版本的区分,不同版本用不同的实现类。
简单来说,就是一些处理方法,可能在低版本上没有,所以它会使用另外的方法去实现。举个例子,ShareCompatImplJB 中,escapeHtml()
方法,最终调用的是 Html.escapeHtml()
方法,但是这个方法它是 Api Level 16 才有的支持,所以在 ShareCompatImplBase 中,实际上是把它的实现,完全的拷贝了出来,只是为了做一个 Html 中字符的转义。
四、结语
ShareCompat 如果只是简单的去分享一个内容,还是非常的好用的。但是大多数情况下,我们还是会选择使用第三方 App 提供的 SDK,来进行接入支持,因为会有一些定制的需要,例如拿到分享结果。
不过这并不影响我们了解 ShareCompat ,多看看 Google 开发人员写的代码,终归是对你有帮助的。