Android-系统分享使用小结

2023-11-19

概述

说到分享,有很多第三方的SDK可供使用,比如友盟,mob都很好用。虽然集成相对容易,但是需要针对每个平台申请APPID 。所以在对应用分享需求不是很强烈,对分享界面要求不大的时候使用系统自带的分享功能足以满足需求,当然如果要保证各个手机上的界面统一,那么第三方的SDK是最好的选择。下面就记录一下自己在实现系统分享时所遇到的问题,和实现步骤。

如何进行分享

系统分享通过调用Intent.createChooser方法构建一个分享界面,核心代码如下:

        Intent intent = new Intent(Intent.ACTION_SEND);//设置分享行为
        intent.setType("*/*");//设置分享内容的类型mime
        /**
          * 添加分享内容
          * 注意:单个文件ACTION_SEND调用{@link Intent#putExtra}方法,
          * 多个ACTION_SEND_MULTIPLE调用{@link Intent#putParcelableArrayListExtra}法
          */
        //intent.putExtra(Intent.EXTRA_SUBJECT, contentTitle);//添加分享内容标题
        //intent.putExtra(Intent.EXTRA_TEXT, content);//添加分享内容
        intent.putExtra(Intent.EXTRA_STREAM,data);//传递分享数据
        //创建分享界面
        intent = Intent.createChooser(intent , title);//title为分享界面的标题
        activity.startActivity(intent);

说明:

  1. 第一行设置分享行为,单个图片文件为Intent.ACTION_SEND,多个为Intent.ACTION_SEND_MULTIPLE
  2. 第二行设置分享类型,其中mime类型介绍详见 android之MIME
  3. 上述代码中的data为uri类型,传递图片时注意对路径进行转化
    上述代码运行结果大致如下图:
    显示支持当前分享的第三方APP

如何筛选分享项

第一步做完了,那如何过滤掉不需要的分享渠道呢?下面给出一个分享图片的例子(只留下微信分享渠道),部分代码参考了自导自演的机器人,感谢

    /**
     * 分享图片(触发场景单个)
     * @param context 上下文
     */
    public void shareSingleImage(Context context) {
        Intent intent = new Intent(Intent.ACTION_SEND);
        //获取选中图片
        Uri imageUri = Uri.parse("file://"+imagepath.toString());
        // Log.d("resolveInfos","imageUri--->" + imageUri);
        intent.setType("image/*");//设置mime格式为图片
        //查询所有可以分享的activity
        //进行筛选
        List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        List<Intent> targetShareIntents = new ArrayList<>();
        if (!resolveInfos.isEmpty()){
           //过滤选择非邮件应用
          for (ResolveInfo resolveInfo : resolveInfos){
                Intent target = new Intent(Intent.ACTION_SEND);//设置分享行为 单个文件、图片
               /**
                 * 添加分享内容
                 * 注意:单个文件ACTION_SEND调用{@link Intent#putExtra}方法,
                 * 多个ACTION_SEND_MULTIPLE调用{@link Intent#putParcelableArrayListExtra}方法
                 */
                target.putExtra(Intent.EXTRA_STREAM,imageUri);
                target.setType("image/*");//设置分享内容mime类型
                ActivityInfo activityInfo = resolveInfo.activityInfo;
                PackageManager pm = ((Activity)context).getApplication().getPackageManager();
                //打印所有符合条件的APP
                Log.d("resolveInfos","packageName--->" + activityInfo.packageName + "  name--->" + activityInfo.name+" label--->"+activityInfo.applicationInfo.loadLabel(pm).toString()+" activity label--->"+activityInfo.loadLabel(pm).toString()+" intent-filter label--->"+resolveInfo.loadLabel(pm).toString());
               /**
                 * 获取activityinfo类中的基本信息 如 包名 activity名称,应用label activity label等
                 *  {@link activityInfo.packageName}                     应用包名,对应{@link applicationId 属性}
                 *  {@link activityInfo.name}                            activity名称,对应{@link <activity>}中的{@linkplain android:name 属性}
                 *  {@link activityInfo.applicationInfo.loadLabel(pm)};  应用名称,对应{@link <application>}中的{@linkplain android:label 属性}
                 *  {@link activityInfo.loadLabel(pm)};                  activity名称(未设置默认为应用名称),对应{@link <activity>}中的{@linkplain android.label属性}
                 *  {@link resolveInfo.loadLabel(pm)};                   intent名称(未设置默认为前两个中优先级高的),对应{@link <intent-filter>}中的{@linkplain android:label属性}
                 */
                //微信
                if (activityInfo.packageName.contains(ShareVariables.WECHAT)){
                        target.setPackage(activityInfo.packageName);
                        target.setClassName(activityInfo.packageName, activityInfo.name);
                    /**
                     * 由于直接传递intent 会导致微信QQ等部分(为intent-filter设置标签)的APP标签,在分享途径中丢失
                     * (很多应用是为activity设置label,并没有为intent-filter设置标签),
                     * 所以需要为传递intent的添加筛选出的标签。
                     */
                        targetShareIntents.add(target);
                }
           }
        Intent chooseIntent = Intent.createChooser(targetIntents.remove(0),null);
        if (chooseIntent == null) {
            return;
        }
        chooseIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,targetIntents.toArray(new Parcelable[]{}));
        //startActivityForResult(Intent.createChooser(intent, "选择应用"), 1001);;

        try {
            context.startActivity(chooseIntent);
        } catch (android.content.ActivityNotFoundException ex) {

            Toast.makeText(context, "找不到该分享应用组件", Toast.LENGTH_SHORT).show();
        }
        }
        
    }

运行结果如下图所示
筛选微信后的显示
我们会发现满足了我们的要求,但是如何区分微信应用下的微信收藏,微信朋友,朋友圈呢?还有为什么之前显示的“发送给朋友”等不同字样都变成了微信呢?下面先解决第一个问题

如何区分部分APP下不同分享界面(以微信为例)

自导自演的机器人文章中通过标签解决了这个问题。因为每个activity都有自己的标签。但是这样指定在不同语言下会很麻烦。

下面给出自己的解决方法,首先贴一下之前代码打印出的log信息(部分)
log信息
我们可以通过activityInfo.name属性来区分不同的界面

如何还原过滤前APP分享途径的描述

在上一步的截图中我们发现朋友圈,微信,微信收藏的描述都变成了微信,那么如何变成过滤之前的描述呢?下面先来说明一下出现该问题的原因:
1、当我们执行

target.setPackage(activityInfo.packageName);
target.setClassName(activityInfo.packageName, activityInfo.name);

时,会将AndroidManufest文件中的activity标签中的label属性设置为分享渠道下的文字描述。而label属性的优先级为 application <activity<intent-filter 优先级高的标签中未设置label属性会默认只用上一级标签中的label属性
再看一下log
在这里插入图片描述
这里我们可以看到,微信没有为activity设置标签,默认显示为application的标签值,所以出现了上图所示的情况

解决方案:
我们需要将符合筛选条件的intent 设置label值。于是上网查找相应方法,结果没有找到。于是自己去intent类中寻找结果。找了半天没有找到如何为intent添加标签。于是寻找开发文档。果然在文档中找到了答案。intent 有个直接子类LabeledIntent 可以为其设置标签。通过其构造方法LabeledIntent(Intent origIntent, String sourcePackage,
CharSequence nonLocalizedLabel, int icon)设置标签
代码如下:

    /**
    * 分享图片(触发场景单个)
    * @param context 上下文
    */
   public void shareSingleImage(Context context) {
       Intent intent = new Intent(Intent.ACTION_SEND);
       //获取选中图片
       Uri imageUri = Uri.parse("file://"+imagepath.toString());
       // Log.d("resolveInfos","imageUri--->" + imageUri);
       intent.setType("image/*");//设置mime格式为图片
       //查询所有可以分享的activity
       //进行筛选
       List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
       List<LabeledIntent> targetShareIntents = new ArrayList<>();
       if (!resolveInfos.isEmpty()){
          //过滤选择非邮件应用
         for (ResolveInfo resolveInfo : resolveInfos){
               Intent target = new Intent(Intent.ACTION_SEND);//设置分享行为 单个文件、图片
              /**
                * 添加分享内容
                * 注意:单个文件ACTION_SEND调用{@link Intent#putExtra}方法,
                * 多个ACTION_SEND_MULTIPLE调用{@link Intent#putParcelableArrayListExtra}方法
                */
               target.putExtra(Intent.EXTRA_STREAM,imageUri);
               target.setType("image/*");//设置分享内容mime类型
               ActivityInfo activityInfo = resolveInfo.activityInfo;
               PackageManager pm = ((Activity)context).getApplication().getPackageManager();
               //打印所有符合条件的APP
               Log.d("resolveInfos","packageName--->" + activityInfo.packageName + "  name--->" + activityInfo.name+" label--->"+activityInfo.applicationInfo.loadLabel(pm).toString()+" activity label--->"+activityInfo.loadLabel(pm).toString()+" intent-filter label--->"+resolveInfo.loadLabel(pm).toString());
              /**
                * 获取activityinfo类中的基本信息 如 包名 activity名称,应用label activity label等
                *  {@link activityInfo.packageName}                     应用包名,对应{@link applicationId 属性}
                *  {@link activityInfo.name}                            activity名称,对应{@link <activity>}中的{@linkplain android:name 属性}
                *  {@link activityInfo.applicationInfo.loadLabel(pm)};  应用名称,对应{@link <application>}中的{@linkplain android:label 属性}
                *  {@link activityInfo.loadLabel(pm)};                  activity名称(未设置默认为应用名称),对应{@link <activity>}中的{@linkplain android.label属性}
                *  {@link resolveInfo.loadLabel(pm)};                   intent名称(未设置默认为前两个中优先级高的),对应{@link <intent-filter>}中的{@linkplain android:label属性}
                */
               //微信
               if (activityInfo.packageName.contains(ShareVariables.WECHAT)){
                       target.setPackage(activityInfo.packageName);
                       target.setClassName(activityInfo.packageName, activityInfo.name);
                   /**
                    * 由于直接传递intent 会导致微信QQ等部分(为intent-filter设置标签)的APP标签,在分享途径中丢失
                    * (很多应用是为activity设置label,并没有为intent-filter设置标签),
                    * 所以需要为传递intent的添加筛选出的标签。
                    */
                       LabeledIntent targeted = new LabeledIntent(target,activityInfo.packageName,resolveInfo.loadLabel(pm),resolveInfo.icon);
                   targetShareIntents.add(targeted);
               }
          }
       Intent chooseIntent = Intent.createChooser(targetIntents.remove(0),null);
       if (chooseIntent == null) {
           return;
       }
       chooseIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,targetIntents.toArray(new Parcelable[]{}));
       //startActivityForResult(Intent.createChooser(intent, "选择应用"), 1001);;

       try {
           context.startActivity(chooseIntent);
       } catch (android.content.ActivityNotFoundException ex) {

           Toast.makeText(context, "找不到该分享应用组件", Toast.LENGTH_SHORT).show();
       }
       }
       
   }

结果如下图所示:
在这里插入图片描述

参考
[1]: https://www.jianshu.com/p/88f166dd43b7

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android-系统分享使用小结 的相关文章

随机推荐

  • 实现java导出文件弹出下载框让用户选择路径

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 在实现导出文件时 弹出下载框主要是设置成文件流 stream类型的response 浏览器就会识别 然后弹出下载框让用户选择保存路径 这里总结三个方式 web struts
  • c# asp.net 如何在js文件中使用服务器变量,asp.net中JS,CS 调用后台变量的值多种方法...

    本文章介绍了关于asp net中JS CS 调用后台变量的值多种方法 有需了解的朋友可以参考一下 1 后台 Publicstringstr 123 最好为Public类型 直接在AspX前台页面HTML代码中要放的位置写入如下代码 2 用J
  • 解决${}EL表达式不起作用,无法获取数据,页面显示内容出错

    问题 EL表达式无法获取数据 解决办法 在jsp页面加入 这句话表示 可以使用EL 表达式 效果
  • html标签中src=“图片路径”,怎么用变量替换路径

    div style background image none bg0 gif bg5 gif div
  • C++中std::sort/std::stable_sort/std::partial_sort的区别及使用

    某些算法会重排容器中元素的顺序 如std sort 调用sort会重排输入序列中的元素 使之有序 它默认是利用元素类型的 lt 运算符来实现排序的 也可以重载sort的默认排序 即通过sort的第三个参数 此参数是一个谓词 predicat
  • 转载:IT项目管理-看板管理

    作为一个开发团队的管理者 例如当你是一个团队的项目经理的时候 任务的完成情况通常是你最关心的内容之一 比如说分配的任务是否能够按时间完成 整个项目的进度是否尚在计划之中 团队内的人是不是都在高效地工作 大家有没有什么困难 这些是你经常会关注
  • 无刷直流电机控制MATLAB仿真,使用Simulink进行无刷直流电机控制仿真

    这段时间刚开始接触Matlab中的Simulink仿真 我就结合自己的专业 利用Simulink进行了无刷直流电机的仿真 因为Simulink工具箱里面有很多可用的模块 所以建模过程变得非常简单 在Matlab界面中new gt model
  • MSP430F42X系列单片机SD16例程(16位AD采样)

    说明 该驱动程序库包含了常用的16位ADC SD16 操作与控制功能函数 如选择通道 设置信号放大倍数 设置数据格式 基准源输出开关等 以及常用采样函数 包括单通道采样 平均采样 多通道同时采样等 可以作为各种程序的底层驱动使用 要使用该库
  • 51单片机多机通信

    视频学习链接 https www bilibili com video BV1pi4y147A6 spm id from 333 880 my history page click vd source b91967c499b23106586
  • Zabbix的模板管理与配置

    Zabbix的模板管理与配置 一 查看默认模板的配置项 1 打开客户端信息配置界面 2 选择默认模板的监控项 二 服务端获取客户端的监控项 1 获取客户端系统相关监控项 2 获取客户端硬盘信息等相关监控项 三 创建自定义监控项的key 1
  • 如何在IDEA中使用JDBC

    如何在IDEA中使用JDBC 摘要 安装JDK及IDEA mysql下载安装及预处理 JDBC驱动下载 新建IDEA项目 添加JDBC驱动文件至项目 编写java测试语句 摘要 本文主要介绍了如何用IDEA新建一个java项目 并用JDBC
  • Docker私服之Harbor搭建全过程【安装+启动+jar镜像构建、推送、拉取、运行】

    1 docker安装 docker compose docker和docker compose安装参考链接 2 harbor安装 harbor下载 harbor offline installer v2 5 3 tgz 我下载的版本是2 5
  • 芯片制造系列全流程:设计、制造、封测

    目录 芯片制造系列全流程 简 一 芯片制造全流程简介 二 芯片设计 三 芯片制造 四 封装测试 芯片目前分为三个主要环节 分别是设计 制程 封测 设计水平 制造这一块 最后说说封测这一块 芯片设计 芯片制造 封装测试完整解读 01 芯 片
  • 手把手教你安装CUDA(一看就会)

    1 背景 学习深度学习的话 肯定需要安装PyTorch和TensorFlow 安装这两个深度学习框架之前得安装CUDA CUDA是什么 CUDA是一个并行计算平台和编程模型 能够使得使用GPU进行通用计算变得简单和优雅 Nvidia官方提供
  • 树状数组笔记

    数组 前缀和 树状数组的区别 数组 修改某点O 1 求区间O n 前缀和 修改某点O n 求区间O 1 树状数组 修改某点O logn 求区间O logn 树状数组采取折中的方式 降低整体的时间复杂度 由于算法复杂度取决于最坏的情况的复杂度
  • 1.vs2019 配置Eigen

    目录 一 下载Eigen 二 创建工程 三 测试代码 四 运行结果 一 下载Eigen 下载地址 http eigen tuxfamily org index php title Main Page Download 下载后 将文件解压 二
  • Python--pytesseract验证码识别处理实例

    linux ubuntu系统 安装过程 pytesser 调用了 tesseract 因此需要安装 tesseract 安装 tesseract 需要安装 leptonica 否则编译tesseract 的时候出现 configure er
  • mysql 自定义函数 if not exists_IF配合AND、OR以及NOT函数使用,可以解决工作中的不少难题...

    前面小编已经分别介绍了逻辑判断函数IF AND OR及NOT的用法 同时也提到它们比较少单独使用 那么 这篇文章我们就来介绍一下IF分别和AND OR及NOT的配合用法 1 函数定义回顾 首先来回顾下这4个逻辑判断函数的定义 1 IF函数
  • 每日一题:整齐的数组

    整齐的数组 题目 Daimayuan Online Judge 每一次可以选择一个ai减去k 可以进行若干次操作 使得所有数变相同 说明跟顺序无关 可以从小到大排个序 k大于等于1 说明了每个数只能变小不能变大 那么每个数只能变得和最小的那
  • Android-系统分享使用小结

    Android 系统分享使用小结 概述 如何进行分享 如何筛选分享项 如何区分部分APP下不同分享界面 以微信为例 如何还原过滤前APP分享途径的描述 概述 说到分享 有很多第三方的SDK可供使用 比如友盟 mob都很好用 虽然集成相对容易