Intents and Intent Filters

来源:互联网 发布:mac mini 换ssd 编辑:程序博客网 时间:2024/06/02 06:57

Intents 分为显示Intents和隐士intents

1:显示的Intents举例如下:一般用于启动特定的app 组件,如下例就是启动downloaderservice。

Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
startService(downloadIntent);

2:隐士的Intents不指定类名,而是指定满足某种条件就可以,当然符合条件的activity或者service 可能有好几个,这个时候系统就会弹出一个对话框,让用户自己选择。

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");

这样当所有在manifest中定义ACTION_SEND 的activity 或者service 都会响应这个Intent。但是如果没有一个activit或者service响应,你的app可能就要crash掉,所以我们一般先查询是否有activity 响应这个Intent,如果有响应,在发送,就像下面这样.

// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");


// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(sendIntent);
}

其中intent.resolveactivity 会调用pm.resolveactiviy 开查询是否有符合的activity.

/frameworks/base/core/java/android/content/Intent.java
5790    public ComponentName resolveActivity(PackageManager pm) {
5791        if (mComponent != null) {
5792            return mComponent;
5793        }
5794
5795        ResolveInfo info = pm.resolveActivity(
5796            this, PackageManager.MATCH_DEFAULT_ONLY);
5797        if (info != null) {
5798            return new ComponentName(
5799                    info.activityInfo.applicationInfo.packageName,
5800                    info.activityInfo.name);
5801        }
5802
5803        return null;
5804    }

而activity的信息是在安装的时候由PMS parse 出来。后面在详细分析.

如果有多个activity响应的话,可以弹出一个对话框让用户选择,sample code 如下:

Intent sendIntent = new Intent(Intent.ACTION_SEND);
// 选择Android 默认的chooser,也可以客制化
String title = getResources().getString(R.string.chooser_title);
// Create intent to show the chooser dialog
Intent chooser = Intent.createChooser(sendIntent, title);
// Verify the original intent will resolve to at least one activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(chooser);
}

resolveactivity 最终在ActivityStackSupervisor.java实现。重点是869行会向packagemanager 查询是否有符合的intent

/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
    ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
864            ProfilerInfo profilerInfo, int userId) {
865        // Collect information about the target of the Intent.
866        ActivityInfo aInfo;
867        try {
868            ResolveInfo rInfo =
869                AppGlobals.getPackageManager().resolveIntent(
870                        intent, resolvedType,
871                        PackageManager.MATCH_DEFAULT_ONLY
872                                    | ActivityManagerService.STOCK_PM_FLAGS, userId);

873            aInfo = rInfo != null ? rInfo.activityInfo : null;
874        } catch (RemoteException e) {
875            aInfo = null;
876        }
877
878        if (aInfo != null) {
879            // Store the found target back into the intent, because now that
880            // we have it we never want to do this again.  For example, if the
881            // user navigates back to this point in the history, we should
882            // always restart the exact same activity.
883            intent.setComponent(new ComponentName(
884                    aInfo.applicationInfo.packageName, aInfo.name));
885
886            // Don't debug things in the system process
887            if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
888                if (!aInfo.processName.equals("system")) {
889                    mService.setDebugApp(aInfo.processName, true, false);
890                }
891            }
892
893            if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
894                if (!aInfo.processName.equals("system")) {
895                    mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
896                }
897            }
898
899            if (profilerInfo != null) {
900                if (!aInfo.processName.equals("system")) {
901                    mService.setProfileApp(aInfo.applicationInfo, aInfo.processName, profilerInfo);
902                }
903            }
904        }
905        return aInfo;
906    }

intent filters 有两种方式注册,一种是在manifest文件中静态注册如下所示:只要action是send的intend 都会被myactivity 接收到.

<activity android:name="MyActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>


    </intent-filter>
</activity>

第二种方式是在java code中动态注册.

546        final IntentFilter filter = new IntentFilter();
547
548        filter.addAction(Intent.ACTION_TIME_TICK);
549        filter.addAction(Intent.ACTION_TIME_CHANGED);
550        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);

552        getContext().registerReceiver(mIntentReceiver, filter, null, getHandler());

注册三个action.


有两个action 需要额外主要:


ACTION_MAIN:这个是aplication的入口activity,不接收任何intent data。

CATEGOTY_LAUNCHER : 这个会把activity的icon放到桌面(launch)。
这两个必须按顺序放好,才能让activity在桌面上显示图标
pending intent:

pending intent 是intent的一个包装,其设计的目的是让其他process的application 有权限启动其他process的activity,service,broadcast,就像在自己process 一样.

主要由三种用途:

notification,alarmManager或者app wiget 的时候可以可以传递一个pending intent,这样当用户点击的时候其他一个activity,service,broadcast.



0 0
原创粉丝点击