• 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
                        }
                    });
        }
    }

    混淆配置

    参考资料

    Android分享---调用系统自带的分享功能

    探索Android调用系统的分享功能

    Intent.resolveActivity

    项目demo下载地址

    https://github.com/haiyuKing/ShareWithSystemDemo

  • 相关阅读:
    判断是否可以点击
    窗口截图
    设置等待操作
    时间控件处理
    eclipse小技巧
    Angular 学习1
    MVC 中引用Angularjs
    Bootstrap 侧边栏 导航栏
    C# 直接使用sql语句对数据库操作 (cmd.ExecuteNonQuery)
    sql 常用的语句(sql 创建表结构 修改列 清空表)
  • 原文地址:https://www.cnblogs.com/whycxb/p/9554954.html
Copyright © 2020-2023  润新知