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"));

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

public static Intent createChooser(Intent target, CharSequence title) {
	Intent intent = new Intent(ACTION_CHOOSER);
	intent.putExtra(EXTRA_INTENT, target);
	if (title != null) {
		intent.putExtra(EXTRA_TITLE, title);
	}
	return intent;
}
  • 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);
         }
     }
  • 从上面的核心代码看既然能实现分享列表数据的过滤,那么排序和删除数据都可以简单实现。但也必须是自己自定义分享弹框列表实现。上个版本就是这么做的

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

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

    • 0
      点赞
    • 4
      收藏
      觉得还不错? 一键收藏
    • 2
      评论
    2009-01-18 Android应用协调器------Intent 关键字: android intent实例 刚起步的时候经常困扰我们的是一些本来容易解决的问题,往往我们会花掉很大的力气去找解决的办法,最后才知道原来这么简单,这就是英文世界造成的。 Intent在Android应用开发中,占有很大的分量,关于Intent在Android中的作用在网络上已经有很多资料了,这里不再累赘,本人喜欢直来直去。在网上看到很多关于Intent的资料,说那么多,你也许还是一头雾水,到底如何使用Intent呢?这里总结一些重用的Intent使用,仅供参考。 下面直接给我学习的实例片段。 1,调用web浏览器 Uri myBlogUri = Uri.parse("http://kuikui.javaeye.com"); returnIt = new Intent(Intent.ACTION_VIEW, myBlogUri); 2,地图 Uri mapUri = Uri.parse("geo:38.899533,-77.036476"); returnIt = new Intent(Intent.ACTION_VIEW, mapUri); 3,调拨打电话界面 Uri telUri = Uri.parse("tel:100861"); returnIt = new Intent(Intent.ACTION_DIAL, telUri); 4,直接拨打电话 Uri callUri = Uri.parse("tel:100861"); returnIt = new Intent(Intent.ACTION_CALL, callUri); 5,卸载 Uri uninstallUri = Uri.fromParts("package", "xxx", null); returnIt = new Intent(Intent.ACTION_DELETE, uninstallUri); 6,安装 Uri installUri = Uri.fromParts("package", "xxx", null); returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri); 7,播放 Uri playUri = Uri.parse("file:///sdcard/download/everything.mp3"); returnIt = new Intent(Intent.ACTION_VIEW, playUri); 8,调用发邮件 Uri emailUri = Uri.parse("mailto:[email protected]"); returnIt = new Intent(Intent.ACTION_SENDTO, emailUri); 9,发邮件 returnIt = new Intent(Intent.ACTION_SEND); String[] tos = { "[email protected]" }; String[] ccs = { "[email protected]" }; returnIt.putExtra(Intent.EXTRA_EMAIL, tos); returnIt.putExtra(Intent.EXTRA_CC, ccs); returnIt.putExtra(Intent.EXTRA_TEXT, "body"); returnIt.putExtra(Intent.EXTRA_SUBJECT, "subject"); returnIt.setType("message/rfc882"); Intent.createChooser(returnIt, "Choose Email Client"); 10,发短信 Uri smsUri = Uri.parse("tel:100861"); returnIt = new Intent(Intent.ACTION_VIEW, smsUri); returnIt.putExtra("sms_body", "shenrenkui"); returnIt.setType("vnd.android-dir/mms-sms"); 11,直接发邮件 Uri smsToUri = Uri.parse("smsto://100861"); returnIt = new Intent(Intent.ACTION_SENDTO, smsToUri); returnIt.putExtra("sms_body", "shenrenkui"); 12,发彩信 Uri mmsUri = Uri.parse("content://media/external/images/media/23"); returnIt = new Intent(Intent.ACTION_SEND); returnIt.putExtra("sms_body", "shenrenkui"); returnIt.putExtra(Intent.EXTRA_STREAM, mmsUri); returnIt.setType("image/png"); 用获取到的Intent直接调用startActivity(returnIt)就ok了。 今天就说这么多,有更大需求的可以看源代码。

    “相关推荐”对你有帮助么?

    • 非常没帮助
    • 没帮助
    • 一般
    • 有帮助
    • 非常有帮助
    提交
    评论 2
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值