Android调起系统分享,并指定分享的应用,不同应用分享的策略.以及分享自己的App

今天有同学问我,android系统怎么指定分享的App,把其他不需要显示的App全部过滤掉.我想了下,设置Intent过滤规则就可以了.

先来看看基础知识点:

1 Intent 和 Intent 过滤器

https://developer.android.google.cn/guide/components/intents-filters

Intent 分为两种类型:

  • 显式 Intent:按名称(完全限定类名)指定要启动的组件。 通常,您会在自己的应用中使用显式 Intent 来启动组件,这是因为您知道要启动的 Activity 或服务的类名。例如,启动新 Activity 以响应用户操作,或者启动服务以在后台下载文件。
  • 隐式 Intent :不会指定特定的组件,而是声明要执行的常规操作,从而允许其他应用中的组件来处理它。 例如,如需在地图上向用户显示位置,则可以使用隐式 Intent,请求另一具有此功能的应用在地图上显示指定的位置。

图 1. 隐式 Intent 如何通过系统传递以启动其他 Activity 的图解:

[1] Activity A 创建包含操作描述的 Intent,并将其传递给 startActivity()

[2] Android 系统搜索所有应用中与 Intent 匹配的 Intent 过滤器。 找到匹配项之后,

[3] 该系统通过调用匹配 Activity(Activity B)的 onCreate() 方法并将其传递给 Intent,以此启动匹配 Activity。

2 基本的分享功能:

Intent intent = new Intent(Intent.ACTION_SEND);
        intent.setType("text/plain");
        intent.putExtra(Intent.EXTRA_TITLE, title);
        intent.putExtra(Intent.EXTRA_SUBJECT, subject);
        intent.putExtra(Intent.EXTRA_TEXT, content);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
        Intent chooserIntent = Intent.createChooser(intent, "Select app to share");
        if (chooserIntent == null) {
            return;
        }
        try {
            startActivity(chooserIntent);
        } catch (android.content.ActivityNotFoundException ex) {
            Toast.makeText(this, "Can't find share component to share", Toast.LENGTH_SHORT).show();
        }
  1. 一般,通过上面的代码,提供的分享方式有各种应用:邮件,信息,蓝牙,微博,Twitter,二维码扫描器等。

3 分享策略

1 分享指定应用:

例如只分享到QQ,直接添加QQ的包名就好了

intent.setPackage("com.tencent.mobileqq");

如果分享的指定应用比较多,则可以使用集合将分别设置的Intent(此处每个包名都是一个新的Intent)添加到集合中,然后设置到Intent里面即可

例如,我写死了几个包名:

public void share(View view) {
        List<Intent> targetedShareIntents = new ArrayList<Intent>();


        for (int i = 0; i < 3; i++) {
            Intent intent = new Intent(Intent.ACTION_SEND);
            intent.setType("text/plain");
            intent.setType("image/jpeg");
            intent.putExtra(Intent.EXTRA_TITLE, "标题");
            intent.putExtra(Intent.EXTRA_SUBJECT, "内容");
            intent.putExtra(Intent.EXTRA_TEXT, "哈哈哈哈哈哈");
            if (i == 0) {
                intent.setPackage("com.tencent.mobileqq");
            } else if (i == 1) {
                intent.setPackage("com.tencent.mm");
            } else if (i == 2) {
                intent.setPackage("com.sina.weibo");
            }
            targetedShareIntents.add(intent);
        }
        Intent chooserIntent = Intent.createChooser(targetedShareIntents.get(0), "Select app to share");

        if (chooserIntent == null) {
            return;
        }
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{}));

        // A Parcelable[] of Intent or LabeledIntent objects as set with
        // putExtra(String, Parcelable[]) of additional activities to place
        // a the front of the list of choices, when shown to the user with a
        // ACTION_CHOOSER.
        try {
            startActivity(chooserIntent);
        } catch (android.content.ActivityNotFoundException ex) {
            Toast.makeText(this, "Can't find share component to share", Toast.LENGTH_SHORT).show();
        }
    }

2 分享到制定应用,每个应用分享的内容不一样

例如:过滤掉蓝牙,对邮件分享详细的内容,对信息和微博等分享较简短的内容,对二维码扫描器只分享URL。

解决的办法是得到所有能处理ACTION_SEND的应用程序包名,然后根据名字来过滤或者特殊处理。主要用到getPackageManager().queryIntentActivities方法。

        String contentDetails = "";
        String contentBrief = "";
        String shareUrl = "";

        Intent it = new Intent(Intent.ACTION_SEND);
        it.setType("text/plain");

        List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(it, 0);
        if (!resInfo.isEmpty()) {

            List<Intent> targetedShareIntents = new ArrayList<Intent>();

            for (ResolveInfo info : resInfo) {

                Intent targeted = new Intent(Intent.ACTION_SEND);
                targeted.setType("text/plain");

                ActivityInfo activityInfo = info.activityInfo;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                // judgments : activityInfo.packageName, activityInfo.name, etc.
                if (activityInfo.packageName.contains("bluetooth") || activityInfo.name.contains("bluetooth")) {
                    continue;
                }

                if (activityInfo.packageName.contains("gm") || activityInfo.name.contains("mail")) {
                    targeted.putExtra(Intent.EXTRA_TEXT, contentDetails);
                } else if (activityInfo.packageName.contains("zxing")) {
                    targeted.putExtra(Intent.EXTRA_TEXT, shareUrl);
                } else {
                    targeted.putExtra(Intent.EXTRA_TEXT, contentBrief);
                }

                targeted.setPackage(activityInfo.packageName);
                targetedShareIntents.add(targeted);
            }

            Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(0), "Select app to share");
            if (chooserIntent == null) {
                return;
            }

            // A Parcelable[] of Intent or LabeledIntent objects as set with
            // putExtra(String, Parcelable[]) of additional activities to place
            // a the front of the list of choices, when shown to the user with a
            // ACTION_CHOOSER.
            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[] {}));

            try {
                startActivity(chooserIntent);

            } catch (android.content.ActivityNotFoundException ex) {

                Toast.makeText(this, "Can't find share component to share", Toast.LENGTH_SHORT).show();

            }
        }

参考自: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2013/1005/1564.html

3 如何分享自己的app

例如,如果你创建了一个社交app可以分享信息和图片给用户的朋友,为了其他app可以启动activity,应该在manifest文件中添加<intent-filter>元素和响应的<activity>元素。

当app安装到设备上后,系统会识别intent filter然后把信息加到一个所有安装的app信息都存储在PackageManagerService中。

PKMS构造函数的主要功能是,扫描Android系统中几个目标文件夹中的APK,从而建立合适的数据结构以管理诸如Package信息、四大组件信息、权限信息等各种信息。抽象地看,PKMS像一个加工厂,它解析实际的物理文件(APK文件)以生成符合自己要求的产品。例如,PKMS将解析APK包中的AndroidManifest.xml,并根据其中声明的Activity标签来创建与此对应的对象并加以保管。

当app用模糊的intent调用startActivity()或者startActivityForResult()时,系统就会查询哪个activity(或哪些)可以响应这个intent。

Action

要指定的动作的名字。通常是平台预定义的值比如ACTION_SEND或者ACTION_VIEW。

Data

和intent相关的数据描述

在intent filter中的用<data>元素来指定。在这个元素中使用一个或多个属性,可以只指定MIME类型,URI前缀,或者这些和其他可接受数据类型的组合。

注意:如果不不声明数据Uri的细节(比如用户处理其他类型的数据,而不是URI),应该只指明android:mimeType属性来声明activity处理的数据类型,比如text/plain或image/jpeg。

Category

提供了一个附加的方式来表示activity处理的intent的特性,通常和用户手势或开始的位置相关。系统支持好几个不同的category,但是很少用到。但是,所有明确的intent都默认定义为CATEGORY_DEFAULT

每个引入的intent都指定了一个动作类型和数据类型,但是可以定义多个<action>,<category>,和<data>元素在每个<intent-filter>中。

如果两组动作和数据在他们的行为中相互冲突,应该创建另外一个intent-filter来指明接收哪个操作时对应哪些数据类型。

例如,假如activity可以处理ACTION_SEND和ACTION_SENDTO intent以及字符串和图片。这种情况下,应该为这两个操作定义两个不同的intent filter,因为ACTION_SENDTO intent在用必须使用URI数据来指定收件人地址,例如:

 1 <activity android:name="ShareActivity">
 2     <!-- filter for sending text; accepts SENDTO action with sms URI schemes -->
 3     <intent-filter>
 4         <action android:name="android.intent.action.SENDTO"/>
 5         <category android:name="android.intent.category.DEFAULT"/>
 6         <data android:scheme="sms" />
 7         <data android:scheme="smsto" />
 8     </intent-filter>
 9     <!-- filter for sending text or images; accepts SEND action and text or image data -->
10     <intent-filter>
11         <action android:name="android.intent.action.SEND"/>
12         <category android:name="android.intent.category.DEFAULT"/>
13         <data android:mimeType="image/*"/>
14         <data android:mimeType="text/plain"/>
15     </intent-filter>
16 </activity>

注意:为了可以接收模糊的intent,必须在intent filter中包括CATEGORY_DEFAULT。方法startActivity()和startActivityForResult()只处理带有CATEGORY_DEFAULT的intent。如果没有声明它,那么没有模糊的intent会传给你的activity。

参考自: https://www.cnblogs.com/fengquanwang/p/3144465.html

猜你喜欢

转载自blog.csdn.net/yang1349day/article/details/81514133