‘壹’ android实现分享功能时,分享的内容怎么提取到,比如浏览一篇文章时,可以提取文章标题,链接等信息。
通常分享功能是调用者发起的,如果是文字分享调用都需要做
intent.putExtra(Intent.EXTRA_SUBJECT, "分享");
intent.putExtra(Intent.EXTRA_TEXT, "好东西,与您分享!");
传递这两个参数,接收都就拿这两个值就可以了。
各种接受分享的软件都是这样处理的,包括系统内置的短信功能,各种微博应用都是一样的。
‘贰’ 利用 Android 系统原生 API 实现分享功能(2)
在之前的一篇文章 利用 Android 系统原生 API 实现分享功能 中主要说了下实现流程,但具体实施起来其实还是有许多坑要面对。那这篇文章就是提供一个封装好的 Share2 库供大家参考。
GitHub 项目地址:Share2
看过上一篇文章的同学应该知道,要调用 Android 系统内建的分享功能,主要有三步流程:
更多相关内容请参考上一篇,这里就不再重复赘述了。
知道大致的实现流程后,其实只要解决下面几个问题后就可以具体实施了。
这其实是直接决定了最终的实现形态,我们知道常见的使用场景中,只是为了在应用间分享图片和一些文件,那对于那些只是分享文本的产品而言,两者实现起来要考虑的问题完全不同。
所以为了解决这个问题,我们可以预先定好支持的分享内容类型,针对不同类型可以进行不同的处理。
在 Share2 中,一共定义了5种类别的分享内容,基本能覆盖常见的使用场景。在调用分享接口时可以直接指定内容类型,比如像文本、图片、音视频、已经其他各种类型文件。
对于不同类别的内容,可能会有不同的来源。比如文本可能就只是一个字符串对象,而对于分享图片或其他文件,我们需要一个 Uri 来标识一个资源。这其实就引出来具体实施时的一个大问题,如何获取要分享文件的 Uri,并且这个 Uri 要能被接收分享内容的应用处理才行 。
那么,如何获取要分享内容文件的 Uri?如果处理才能让接收方也能够根据 Uri 获取到文件?
我们把文件 Uri 的来源划分为下面三种类型:
常见场景 :通过文件选择器获取一个文件的 Uri
通过这种方式获取到的 Uri 是由系统 ContentProvider 返回的,在 Android 4.4 之前的版本和之后的版本有较大的区别,我们后面再说怎么处理。只要先记住这种系统返回给我们的 Uri 就行了。
比如调用系统相机进行拍照或录制音视频,要传入一个生成目标文件的 Uri ,从 7.0 开始我们需要用到 FileProvider 来实现。
如果用到了 FileProvider 就要注意跟系统 ContentProvider 返回 Uri 的区别,比如我们在 Manifest 中对 FileProvider 配置 android:authorities="com.xx.xxx.fileProvider" 属性,那这时系统返回的 Uri 格式就变成了 : content://com.xx.xxx.fileProvider... ,对于这种类型的 Uri 我们姑且叫 自定义 FileProvider 返回的 Uri ,后面一并说怎么处理。
我们调用 new File 时需要传入指定的文件路径,这个绝对路径通常是: /storage/emulated/0/... 这种样式,我们要想调用分享时也要变成 Uri 的形式才可以,那么如何把文件路径变成一个文件 Uri ?这个问题下面也一并进行回答。
前面提到了文件 Uri 的三种分类,对应不同类型处理方式也不同,不然你最先遇到的问题就是:
这是由于对系统返回的 Uri 缺失访问权限导致,所以要对应用进行临时访问 Uri 的授权才行,不然会提示权限缺失。
对于要分享系统返回的 Uri 我们可以这样进行处理:
需要注意的是对于自定义 FileProvider 返回 Uri 的处理,即使是设置临时访问权限,但是分享到第三方应用也会无法识别该 Uri
典型的场景就是,我们如果把自定义 FileProvider 的返回的 Uri 设置分享到微信或 QQ 之类的第三方应用,会提示文件不存在,这是因为他们无法识别该 Uri。
关于这个问题的处理其实跟下面要说的把文件路径变成系统返回的 Uri 一样,我们只需要把自定义 FileProvider 返回的 Uri 变成第三方应用可以识别系统返回的 Uri 就行了。
创建 FileProvider 时需要传入一个 File 对象,所以直接可以知道文件路径,那就把问题都转换成了: 如何通过文件路径获取系统返回的 Uri
下面是根据传入的 File 对象和类型来查询系统 ContentProvider 来获取相应的 Uri,已经按照不同文件类型在不同系统版本下的进行了适配。
其中 forceGetFileUri 方法是通过反射实现的,处理 7.0 以上系统的特殊情况下的兼容性,一般情况下不会调用到。Android 7.0 开始不允许 file:// Uri 的方式在不同的 App 间共享文件,但是如果换成 FileProvider 的方式依然是无效的,我们可以通过反射把该检测干掉。
通过 File Path 转成 Uri 的方式,我们最终统一了调用系统分享时传入内容 Uri 的三种不同场景,最终全部转换为传递系统返回的 Uri,让第三方应用能够正常的获取到分享内容。
Share2 按照上述方法进行了具体实施,可以通过下面的方式进行集成:
分享图片到指定界面,比如分享到微信朋友圈
GitHub 项目地址:Share2
‘叁’ android studio开发应用分享功能怎么实现
1、项目组织结构区,用于浏览项目文件,默认Project以Android组织方式展示。
2、设计区,默认在打开布局文件时为设计模式,可直接拖动控件到界面上实现所见即所得,下方的Design和Text就是代码和设计模式的切换按钮,切换至TEXT时,左侧为代码编辑区,右侧为所见即所得的预览。
下图为切换至TEXT的界面
而我们常用的代码编辑时的界面就很简单,左边项目树,右侧代码编辑区,下图为代码编辑界面:
3、组件树,用于展示整个页面布局的层级关系。
4、属性区,显示选中控件的可编辑属性(仅在设计模式可见)。
5、工具栏,提供常用操作按钮
二、左侧Structure、Project、Captures面板
1、Structure面板
切换到Structure面板, Structure用于显示当前活动文件的结构,不仅仅支持 java 文件,同时支持 Xml 文件、 .properties 配置文件等多种类型的文件。在图中1位置可以设置过滤要显示的内容,如是否显示属性、内部匿
‘肆’ Android 系统原生 API 实现分享功能
GitHub 项目地址:LocalShare-master
直接上图,这是一个典型的调用系统原生分享场景下的界面,相信大家应该都很熟悉。
那下面说一下遇到的一些问题,特别针对是 7.0 以后的系统,以及兼容一些主流 app 时遇到的坑。
前面说到分享文件时需要知道文件的类型,不然的指定类型为 / ,这样分享到某些 App 会因为无法判断文件类型而导致失败,所以最好先根据文件路径获取其文件类型。
使用这种方法获取文件类型,一定要注意 ContentResolver 获取返回为 null 的情况,不然空指针异常的崩溃率可能会让你笑不出来。实际测试中,发现在某些国产机型下,这个方法可以说直接是不可用,查询返回一直都是空,所以单纯依赖这一个方法会很不可靠。具体问题原因请看: What causes Android's ContentResolver.query() to return null?
下面按照第二条思路,按照文件头信息简单实现一个获取文件类型的例子:
// 获取文件Uri
要向在 MediaStore 中查询到文件,要不就是通知媒体库更新查询或则往里面插入一条新记录(会比较耗时)
可以参考我的另外一篇文章: Android 系统原生 API 实现分享功能(2)
参考: https://www.jianshu.com/p/1d4bd2c5ef69
‘伍’ 基于android天气预报开发中的分享功能是怎么实现的
现在的分享基本上都是现成:
android 自带分享功能:虽然比较low,而且不同厂家显示的分享面板可能不一样,但是功能是可以用的,如果要开发写高级功能的那么需要使用到第三方的分享啦
/**3. 第三方分享:使用较多的分享->Umeng(友盟),链接:http://www.umeng.com/
*分享功能
*
*@paramcontext上下文
*@paramactivityTitleActivity的名字
*@parammsgTitle消息标题
*@parammsgText消息内容
*@paramimgPath图片路径,不分享图片则传null
*/
publicvoidshareMsg(StringactivityTitle,StringmsgTitle,StringmsgText,
StringimgPath){
Intentintent=newIntent(Intent.ACTION_SEND);
if(imgPath==null||imgPath.equals("")){
intent.setType("text/plain");//纯文本
}else{
Filef=newFile(imgPath);
if(f!=null&&f.exists()&&f.isFile()){
intent.setType("image/jpg");
Uriu=Uri.fromFile(f);
intent.putExtra(Intent.EXTRA_STREAM,u);
}
}
intent.putExtra(Intent.EXTRA_SUBJECT,msgTitle);
intent.putExtra(Intent.EXTRA_TEXT,msgText);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(Intent.createChooser(intent,activityTitle));
}
4. 第三方分享:使用较多的分享->ShareSDK ,链接:http://www.mob.com/