ShareIntentUtil【调用系统自带的分享的工具类】
版权声明:本文为HaiyuKing原创文章,转载请注明出处!
前言
根据参考资料的文章,整理了调用系统自带分享的工具类(实现了适配7.0FileProvider的功能),需要搭配《Android6.0运行时权限(基于RxPermission开源库)》。
效果图

代码分析
需要注意的代码主要包括:
ShareIntentUtil中适配7.0FileProvider的相关代码。
使用步骤
一、项目组织结构图



注意事项:
1、 导入类文件后需要change包名以及重新import R文件路径
2、 Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖
二、导入步骤
(1)将ShareIntentUtil.java文件复制到项目中
package com.why.project.sharewithsystemdemo.util; import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.support.v4.content.FileProvider;
import android.widget.Toast; import java.io.File;
import java.util.ArrayList; /**
* Created by haiyuKing
* Used 调用系统自带的分享的工具类
* 增加适配7.0FileProvider的功能
*/ public class ShareIntentUtil { //指定分享到的软件包名
public static final String PACKAGE_QQ = "com.tencent.mobileqq";//分享到QQ
public static final String PACKAGE_QZONE = "com.qzone";//分享会到QQ空间
public static final String PACKAGE_WBLOG = "com.tencent.WBlog";//分享到腾讯微博
public static final String PACKAGE_WXIN = "com.tencent.mm";//分享到微信
public static final String PACKAGE_WEIBO = "com.sina.weibo";//分享到新浪微博
public static final String PACKAGE_BAIDUYUN = "com.baidu.netdisk";//分享到百度云 //分享文本
public static void shareText(Context mContext, String shareText, String shareTitle){
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, shareText);
//适配7.0FileProvider
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件【很重要】
}
mContext.startActivity(Intent.createChooser(shareIntent, shareTitle));//可以设置标题
} //分享文本到指定应用
public static void shareTextTo(Context mContext, String shareText, String shareTitle, String packageName){
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setPackage(packageName);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, shareText);
//适配7.0FileProvider
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件【很重要】
} //通过Intent的resolveActivity方法,并想该方法传入包管理器可以对包管理器进行查询以确定是否有Activity能够启动该Intent
//https://blog.csdn.net/qq_15796477/article/details/72953514
PackageManager pm = mContext.getPackageManager();
ComponentName cn = shareIntent.resolveActivity(pm);
if(cn == null){
Toast.makeText(mContext,"未安装该应用",Toast.LENGTH_SHORT).show();
}else {
mContext.startActivity(Intent.createChooser(shareIntent, shareTitle));//可以设置标题
}
} //分享单张图片
public static void shareOneImg(Context mContext, String imgPath, String shareTitle){
File file = new File(imgPath);
if (!file.exists()) {
Toast.makeText(mContext,"文件不存在",Toast.LENGTH_SHORT).show();
return;
} //由文件得到uri
Uri imageUri = getUri(mContext,file); Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, imageUri);
shareIntent.setType("image/*");
//适配7.0FileProvider
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件【很重要】
}
mContext.startActivity(Intent.createChooser(shareIntent, shareTitle));//可以设置标题
} //分享多张图片
public static void shareMultImg(Context mContext, ArrayList<String> imgPathList, String shareTitle){ ArrayList<Uri> uriList = new ArrayList<>(); for(int i=0;i<imgPathList.size();i++){
File file = new File(imgPathList.get(i));
if (!file.exists()) {
Toast.makeText(mContext,"文件不存在",Toast.LENGTH_SHORT).show();
return;
}
uriList.add(getUri(mContext,file));
} Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uriList);
shareIntent.setType("image/*");
//适配7.0FileProvider
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件【很重要】
}
mContext.startActivity(Intent.createChooser(shareIntent, shareTitle));//可以设置标题
} //分享单个文件
public static void shareOneFile(Context mContext, String filePath, String shareTitle){
File file = new File(filePath);
if (!file.exists()) {
Toast.makeText(mContext,"文件不存在",Toast.LENGTH_SHORT).show();
return;
} //由文件得到uri
Uri fileUri = getUri(mContext,file); Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
shareIntent.setType("*/*");
//适配7.0FileProvider
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件【很重要】
}
mContext.startActivity(Intent.createChooser(shareIntent, shareTitle));//可以设置标题
} //获取到uri--适配7.0FileProvider
private static Uri getUri(Context mContext, File file){
Uri uri;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
String authority = mContext.getApplicationInfo().packageName + ".provider";
uri = FileProvider.getUriForFile(mContext.getApplicationContext(), authority, file);
//intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件【很重要】
} else {
uri = Uri.fromFile(file);
} return uri;
}
}
ShareIntentUtil.java
(2)在AndroidManifest.xml中添加权限以及配置7.0FileProvider【注意:provider中的android:authorities值:${applicationId}.provider,其中${applicationId}代表的真实值就是APP的build.gradle中的applicationId(包名)值】
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.why.project.sharewithsystemdemo"> <!-- =================ShareIntentUtil用到的权限========================== -->
<!-- 允许程序读取外部存储文件 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"> <!-- =================7.0上读取文件========================== -->
<!--参考资料https://blog.csdn.net/lmj623565791/article/details/72859156-->
<!--authorities:{app的包名}.provider
grantUriPermissions:必须是true,表示授予 URI 临时访问权限
exported:必须是false
resource:中的@xml/provider_paths是我们接下来要添加的文件-->
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider> <activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>
(3)将provider_paths文件复制到项目的res/xml目录下【适配7.0FileProvider】
<?xml version="1.0" encoding="utf-8"?>
<!--参考资料https://blog.csdn.net/lmj623565791/article/details/72859156-->
<!--<root-path/> 代表设备的根目录new File("/");-->
<!--<files-path/> 代表context.getFilesDir()-->
<!--<cache-path/> 代表context.getCacheDir()-->
<!--<external-path/> 代表Environment.getExternalStorageDirectory()-->
<!--<external-files-path>代表context.getExternalFilesDirs()-->
<!--<external-cache-path>代表getExternalCacheDirs()--> <!--path:需要临时授权访问的路径(.代表所有路径)-->
<!--name:就是你给这个访问路径起个名字-->
<paths>
<root-path name="root" path="." />
<files-path name="files" path="." />
<cache-path name="cache" path="." />
<external-path name="external" path="." />
<external-files-path name="external_file_path" path="." />
<external-cache-path name="external_cache_path" path="." />
</paths>
(4)参考《Android6.0运行时权限(基于RxPermission开源库)》导入相关文件。

三、使用方法
布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"> <Button
android:id="@+id/btn_share_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="分享文本"
android:layout_marginTop="10dp"/> <Button
android:id="@+id/btn_share_one_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="分享单张图片"
android:layout_marginTop="10dp"/> <Button
android:id="@+id/btn_share_mult_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="分享多张图片"
android:layout_marginTop="10dp"/> <Button
android:id="@+id/btn_share_to_qq"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="分享到qq"
android:layout_marginTop="10dp"/> <Button
android:id="@+id/btn_share_one_file"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="分享单个文件"
android:layout_marginTop="10dp"/> </LinearLayout>
activity_main.xml
在Activity中使用【先申请权限,然后执行相关方法:注意,Demo中指定了文件路径,实际项目中一般是动态获取的】
package com.why.project.sharewithsystemdemo; import android.Manifest;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast; import com.tbruyelle.rxpermissions2.RxPermissions;
import com.why.project.sharewithsystemdemo.util.ShareIntentUtil; import java.io.File;
import java.util.ArrayList; import io.reactivex.functions.Action;
import io.reactivex.functions.Consumer; public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); onePermission(); initEvents();
} private void initEvents() {
//分享文本
findViewById(R.id.btn_share_text).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ShareIntentUtil.shareText(MainActivity.this,"这是一段分享的文字","分享文本");
}
}); //分享单张图片
findViewById(R.id.btn_share_one_img).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Environment.getExternalStorageDirectory()=/storage/emulated/0
Log.e("why","Environment.getExternalStorageDirectory()="+Environment.getExternalStorageDirectory());
String imagePath = Environment.getExternalStorageDirectory() + File.separator + "DCIM/Camera/IMG_20160723_103940.jpg"; ShareIntentUtil.shareOneImg(MainActivity.this,imagePath,"分享单张图片"); }
}); //分享多张图片
findViewById(R.id.btn_share_mult_img).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Environment.getExternalStorageDirectory()=/storage/emulated/0
Log.e("why","Environment.getExternalStorageDirectory()="+Environment.getExternalStorageDirectory()); ArrayList<String> imgPathList = new ArrayList<>(); String path = Environment.getExternalStorageDirectory() + File.separator;
imgPathList.add(path+"DCIM/Camera/IMG_20160723_103940.jpg");
imgPathList.add(path+"DCIM/Camera/IMG_20170820_121408.jpg");
imgPathList.add(path+"DCIM/Camera/IMG_20171001_080012.jpg"); ShareIntentUtil.shareMultImg(MainActivity.this,imgPathList,"分享多张图片");
}
}); //分享到qq
findViewById(R.id.btn_share_to_qq).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) { ShareIntentUtil.shareTextTo(MainActivity.this,"这是一段分享的文字","分享到QQ",ShareIntentUtil.PACKAGE_QQ); }
}); //分享单个文件
findViewById(R.id.btn_share_one_file).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Environment.getExternalStorageDirectory()=/storage/emulated/0
Log.e("why","Environment.getExternalStorageDirectory()="+Environment.getExternalStorageDirectory());
String filePath = Environment.getExternalStorageDirectory() + File.separator + "why/AndroidNotesForProfessionals.pdf"; ShareIntentUtil.shareOneFile(MainActivity.this,filePath,"分享单个文件"); }
});
} /**只有一个运行时权限申请的情况*/
private void onePermission(){
RxPermissions rxPermissions = new RxPermissions(MainActivity.this); // where this is an Activity instance
rxPermissions.request(Manifest.permission.READ_EXTERNAL_STORAGE) //权限名称,多个权限之间逗号分隔开
.subscribe(new Consumer<Boolean>() {
@Override
public void accept(Boolean granted) throws Exception {
Log.e(TAG, "{accept}granted=" + granted);//执行顺序——1【多个权限的情况,只有所有的权限均允许的情况下granted==true】
if (granted) { // 在android 6.0之前会默认返回true
// 已经获取权限
Toast.makeText(MainActivity.this, "已经获取权限", Toast.LENGTH_SHORT).show();
} else {
// 未获取权限
Toast.makeText(MainActivity.this, "您没有授权该权限,请在设置中打开授权", Toast.LENGTH_SHORT).show();
}
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Log.e(TAG,"{accept}");//可能是授权异常的情况下的处理
}
}, new Action() {
@Override
public void run() throws Exception {
Log.e(TAG,"{run}");//执行顺序——2
}
});
}
}
混淆配置
无
参考资料
项目demo下载地址
https://github.com/haiyuKing/ShareWithSystemDemo
ShareIntentUtil【调用系统自带的分享的工具类】的更多相关文章
- Android分享---调用系统自带的分享功能
以前我们总想到友盟等平台分享功能的集成,集成这玩意还得下载对应的jar包.当然,用这些平台的分享并不是说什么好处都没有,至少人家的统计功能还是很实用的.不过有的时候我们是不需要多余功能的,只需要能分享 ...
- HttpURLConnection 当作请求调用接口不带返回参数的工具类
package cn.smartercampus.core.util; import java.io.BufferedReader; import java.io.InputStream; impor ...
- 应用程序间跳转 (友盟SSO 授权 与系统自带的分享)
应用程序间跳转的应用场景 使用第三方用户登录,如微信登录,返回用户名和密码 需要用户授权,返回到调用程序,同时返回授权的用户名 应用程序推广,跳转到itunes并显示指定app下载页 第三方支付,跳转 ...
- iOS程序中调用系统自带应用(短信,邮件,浏览器,地图,appstore,拨打电话,iTunes,iBooks )
在网上找到了下在记录下来以后方便用 在程序中调用系统自带的应用,比如我进入程序的时候,希望直接调用safar来打开一个网页,下面是一个简单的使用:
- (转)Android调用系统自带的文件管理器进行文件选择并获得路径
Android区别于iOS的沙盒模式,可以通过文件浏览器浏览本地的存储器.Android API也提供了相应的接口. 基本思路,先通过Android API调用系统自带的文件浏览器选取文件获得URI, ...
- 系统自带的日志管理工具-rsyslogd
系统自带的日志管理工具-rsyslogd 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.日志管理简介 1.什么是日志 系统日志是记录系统中硬件.软件和系统问题的信息,同时还可以 ...
- spring自带的MD5加密工具类
Spring 自带的md5加密工具类,本来打算自己找一个工具类的,后来想起来Spring有自带的,就翻了翻 //导入包import org.springframework.util.DigestUti ...
- 利用UIActivityController调用ios系统自带的分享功能,实现微信发布多图的功能
通过一番查找以后找到一个类UIActivityController,可以调用系统的social.framework中的分享接口.看下面的图就知道了,这个还是挺常见的 微信发布多图 借鉴了CSDN上的一 ...
- Android调用系统自带的设置界面
Android有很多系统自带的设置界面,如设置声音,设置网络等. 在开发中可以调用这些系统自带的设置界面. 点击以下列表中的选项,就可以调出相应的系统自带的设置界面. 如点击“无线和网络设置”,可以调 ...
随机推荐
- 再谈DOMContentLoaded与渲染阻塞—分析html页面事件与资源加载
浏览器的多线程中,有的线程负责加载资源,有的线程负责执行脚本,有的线程负责渲染界面,有的线程负责轮询.监听用户事件. 这些线程,根据浏览器自身特点以及web标准等等,有的会被浏览器特意的阻塞.两个很明 ...
- selenium 定位元素成功, 但是输入失败 (textarea)
问题描述 UI页面功能测试中, 定位元素并输入(通过sendKey()方法输入), 显示输入失败. 根本原因 为了修复一个bug, 这个元素从input改成了textarea, 而textarea是有 ...
- SQL基础操作汇总
SQL基础操作汇总 一.表操作 1.表的创建(CREATE TABLE): 基本语句格式: CREATE TABLE table_name ( col_name datatype, -- ...
- java可用与串口通信的一些库
java原生对串口的支持只有javax.comm,javax.comm比较老了,而且不支持64位系统,我在看jlibmodbus(一个java实现的modbus协议栈)的时候发现了几个可供使用的jav ...
- mysql输入中文出现ERROR 1366
MySQL输入中文出现如下错误: ERROR 1366: 1366: Incorrect string value: '\xE6\xB0\xB4\xE7\x94\xB5...' for column ...
- 用 fhq_Treap 实现可持久化平衡树
支持对历史版本进行操作的平衡树 Treap 和 Splay 都是旋来旋去的 这样平衡树可持久化听起来不太好搞? 还有 fhq_Treap ! 每次涉及操作就复制一个节点出来 操作历史版本就继承它的根继 ...
- DCGAN 代码简单解读
之前在DCGAN文章简单解读里说明了DCGAN的原理.本次来实现一个DCGAN,并在数据集上实际测试它的效果.本次的代码来自github开源代码DCGAN-tensorflow,感谢carpedm20 ...
- hystrix隔离策略(4)
hystrix提供了两种隔离策略:线程池隔离和信号量隔离.hystrix默认采用线程池隔离. 1.线程池隔离 不同服务通过使用不同线程池,彼此间将不受影响,达到隔离效果. 例如: 我们可以通过andT ...
- WebGL学习之纹理贴图
为了使图形能获得接近于真实物体的材质效果,一般会使用贴图,贴图类型主要包括两种:漫反射贴图和镜面高光贴图.其中漫反射贴图可以同时实现漫反射光和环境光的效果. 实际效果请看demo:纹理贴图 2D纹理 ...
- Unix中的I/O模型
本文所指的I/O均是网络I/O. 一. POSIX对同步.异步I/O的定义 我们先大致看看POSIX对同步.异步的定义,不用细究,重点看我标红的部分就行. 同步I/O会导致请求进程阻塞,直到I/O操作 ...