android系统分享分析Intent.createChooser

系统提供的分享实现代码如下:

Intent send = new Intent(Intent.ACTION_SEND);  
        send.setType("text/plain");  
        send.putExtra(Intent.EXTRA_TEXT, url);  
        send.putExtra(Intent.EXTRA_SUBJECT, title);    
        c.startActivity(Intent.createChooser(send, "share title"));

我们先扒一扒源码这个是怎么实现分享

  • Intent.ACTION_SEND很好理解,一个隐式intent的action,在这里调用会打开对应的暴漏出该action的app对应页面(可以自己写个app,然后暴漏该action 也会出现在分享列表中)
  • 剩下就是通过intent把分享参数title text add进去

重点扒一扒Intent.createChooser

  1. createChooser()方法new Intent(ACTION_CHOOSER),返回的是一个Intent对象,弹出的选择框是一个Activity,在源码中搜索一下Action为com.android.internal.app.ChooserActivity的Activity
/android/frameworks/base/core/res/AndroidManifest.xml  

<activity android:name="com.android.internal.app.ChooserActivity"  
                android:theme="@style/Theme.Holo.Dialog.Alert"  
                android:finishOnCloseSystemDialogs="true"  
                android:excludeFromRecents="true"  
                android:multiprocess="true">  
            <intent-filter>  
                <action android:name="android.intent.action.CHOOSER" />  
                <category android:name="android.intent.category.DEFAULT" />  
            </intent-filter>  
        </activity>

  1. ChooserActivity调用了其父类ResolverActivity的OnCreate(),ResolverActivity相当于一个Activity的选择器,ChooserActivity在onCreate()方法里先获取传递进来的Intent对象,取得其中携带的目标Intent。如果只有一个Activity适配,将直接启动。 ResolverActivity(queryIntentActivities)就是这个选择对话框的Activity,这里获得适配Activity的icon和title等信息显示到对话框。如果没有调用createChooser()方法,如果有多个Activity适配一个intent的话也会打开一个选择对话框,不过这个对话框多了两个选项.

总结:这下大家应该清楚了,原来在调用createChooser()方法时候,系统又创建了一个新的Action为ACTION_CHOOSER的Intent ,并把我们的原始Intent当成了参数传进去 。选择器的title是通过 EXTRA_TITLE传入进去的。

Custom choose intent

产品或者我们自己这个分享列表提出自己的要求,比如是否可以监听这个列表点击自定义跳转、把facebook whatsapp这两个app放在第一个、或者某个app不要出现在分享列表中 等这些需求该如何实现;

  1. 监听这个列表点击自定义跳转操作 答案是 NO,弹框是系统的ChooserActivity,并不存在暴漏出列表item点击的监听回调,而且从隐式intent设计来讲,列表中的app都是与其暴漏出的intent对应匹配上的,它的初衷就是匹配上来就跳转。参考回答 想实现监听跳转只能自定义分享列表list adapter填充列表数据 跳转等,我们上个版本就是这样实现的。核心代码是获取能分享的列表数据

         Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
         sharingIntent.setType("text/plain");
         PackageManager pm = App.getInstance().getPackageManager();
         List<List<ResolveInfo>> listArrayList = new ArrayList<>();
         List<ResolveInfo> activityList = pm.queryIntentActivities(sharingIntent, 0);
         List<ResolveInfo> newActivityList = new ArrayList<>();
    
         for (Iterator<ResolveInfo> it = activityList.iterator(); it.hasNext(); ) {
             ResolveInfo info = it.next();
             //过滤出facebook google+  whatapp  分享app单独处理
             if (info.activityInfo.packageName.equals("com.facebook.katana") || info.activityInfo.packageName.equals("com.google.android.apps.plus") || info.activityInfo.packageName.equals("com.facebook.orca") || info.activityInfo.packageName.contains("whatsapp")) {
                 it.remove();
                 newActivityList.add(info);
             }
         }
    
    
  2. 从上面的核心代码看既然能实现分享列表数据的过滤,那么排序和删除数据都可以简单实现。但也必须是自己自定义分享弹框列表实现。上个版本就是这么做的

  3. 放google+分享列表实现(先谈一个BottomSheetDialog展示特异强调的分享app和一个other按钮,点other再进入系统的分享列表) 1.难点是用过滤的分享数据实现系统的分享。之前系统的分享数据是在ChooserActivity中自己匹配的。可喜的找到了Intent中EXTRA_INITIAL_INTENTS参数。具体看代码源码

         List<Intent> targetIntents = new ArrayList<Intent>();
         Intent shareIntent = new Intent(Intent.ACTION_SEND);
         shareIntent.setType("text/plain");
         for (ResolveInfo candidate : packages) {
             String packageName = candidate.activityInfo.packageName;
             Intent target = new Intent(android.content.Intent.ACTION_SEND);
             target.setType("text/plain");
             if (uri != null) {
                 shareIntent.setType("image/*");
                 shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
             }
             target.putExtra(Intent.EXTRA_TEXT, shareText);
             target.setComponent(new ComponentName(packageName, candidate.activityInfo.name));
    
             targetIntents.add(target);
         }
         Intent chooserIntent = Intent.createChooser(targetIntents.remove(0), title);
         chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toArray(new Parcelable[]{}));
         context.startActivity(chooserIntent);
    
    

最终展现给用户的选择包括,符合createChooser第一个参数的应用(其实是指定了packageName和className的Intent),以及由EXTRA_INITIAL_INTENTS指定的应用

疑问

  1. 注意,这里没有使用Intent.setComponent来明确指定要启动的Activity,而是通过setPackageName和setClass来指定。这是因为,在createChooser处理过程中,第一个参数intent指定的component会在ResolverActivity中强制被设置为null。这样的结果是什么呢?当component被设置为null后,targetIntents.remove(0)其实就是emailIntent,那么createChooser会显示所有满足emailIntent的应用,然后在加上由EXTRA_INITIAL_INTENTS指定的应用。你会发现选择界面中出现了重复的应用。

2.过滤数据处理后的系统分享弹框,与原声系统分享弹框少了下面两个按钮,也少了上面最佳常用app的列表

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272

推荐阅读更多精彩内容