Intent深入学习

启动活动有一种是startActivityForResult,这个需要掌握。

启动服务,总是使用显式意图。

intent  filter表示这个组件可能要接受的意图的类型。也就说,意图有type??什么意思,如果不指定intent filter,只能显示启动了。

建立一个意图:

Component name:在显示意图,表示明确启动的类,使用setComponent,setClass,setClassName来设置,所以见过setClass设置的,

如果不加,就是隐式意图了。

Action:要执行的动作,比如ACTION_VIEW ACTION_SEND,一般可以作为被其他活动或应用启动,一般是定义在<intent-filter>中的

Data:在sunshine内容提供器的时候看到过,

Intent intent = new Intent(getApplicationContext(), DetailActivity.class)
        .setData(itemUir);

startActivity(intent);

在DetailActivity的OnCreate中:getIntent().getData()获得保存的这个Uri,用来查询具体的信息。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_detail);
    if (savedInstanceState == null) {
        Bundle arguments = new Bundle();
        arguments.putParcelable(DetailFragment.DETAIL_URI, getIntent().getData());
        DetailFragment fragment = new DetailFragment();
        fragment.setArguments(arguments);
        getSupportFragmentManager().beginTransaction()
                .add(R.id.weather_detail_container, fragment)
                .commit();
    }
}

Category:和Action一起定义在<intent-filter>中,二者组合出现。

Extras:传递额外的信息,这个也常用。

Flags:没用到还


一般定义的话,最多就是这样了:或者最简单,连<intent-filter>都没有,都比较简单,不过用起来也不简单啊。

<activity android:name=".app.IsolatedService$Controller"
        android:label="@string/activity_isolated_service_controller"
        android:launchMode="singleTop"
        android:enabled="@bool/atLeastJellyBean">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.SAMPLE_CODE" />
    </intent-filter>
</activity>

使用隐式意图注意:

为了确保有一个能响应,先测试下:

// 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);
}

使用createChooser,展示标题,让用户选择

Intent sendIntent = new Intent(Intent.ACTION_SEND);
...

// Always use string resources for UI text.
// This says something like "Share this photo with"
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);
}

intent-filer

<intent-filter>元素指定了接收的intent的type,以action,data和category为基础。

下面是一个例子:

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

如果intent要传递给组件,必须通过三个测试。一个组件可能有多个(?怎么定义)filter,所以只要通过一个就行。

服务不需要定义<intent-filter>.

对所有的活动,必须在Manifest文件中定义所有的intent filter。对于broadcast receiver可以动态注册通过调用registerReceiver。取消注册,

调用unregisterReceiver。

如果不想让其他应用访问我们的组件,使用intent-filter不是最安全是方式,应该是设置为exported=false才行。


下面这个例子:

<activity android:name="MainActivity">
    <!-- This activity is the main entry, should appear in app launcher -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity android:name="ShareActivity">
    <!-- This activity handles "SEND" actions with text data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
    <!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <action android:name="android.intent.action.SEND_MULTIPLE"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="application/vnd.google.panorama360+jpg"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="video/*"/>
    </intent-filter>
</activity>
  • The ACTION_MAIN action indicates this is the main entry point and does not expect any intent data.
  • The CATEGORY_LAUNCHER category indicates that this activity's icon should be placed in the system's app launcher. If the <activity> element does not specify an icon with icon, then the system uses the icon from the <application> element.
这两个必须同时存在让一个活动出现在系统启动。


Note: The MIME type,application/vnd.google.panorama360+jpg, is a special data type that specifiespanoramic photos, which you can handle with the Googlepanorama APIs.


使用Pending Intent

一个Pending intent是一个intent的包装。基本是目的是给外部应用授予权限使用他包含的intent就像是从我们应用自己的进程执行的一样。

主要使用情况:
  • Declare an intent to be executed when the user performs an action with your Notification (the Android system's NotificationManager executes the Intent).
  • Declare an intent to be executed when the user performs an action with your App Widget (the Home screen app executes the Intent).
  • Declare an intent to be executed at a specified time in the future (the Android system's AlarmManager executes the Intent). 
一个是通知,用户点击这个通知打开的组件,pending intent包含的这个intent指定组件
sunshihe这样使用,下面会有介绍为什么这么用的?使用的TaskStackBuilder,需要学习,一般可以使用
PendingIntent.getActivity() for an Intent that starts an Activity.
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getContext())
        .setSmallIcon(iconId)
        .setContentText(contentText)
        .setContentTitle(title);
Intent resultIntent = new Intent(context, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(getContext());
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
        0, PendingIntent.FLAG_UPDATE_CURRENT );
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager notificationManager = (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(WEATHER_NOTIFICATION_ID, mBuilder.build());


第二个是使用app widget执行动作?这个还没见过?
第三是指定一个在将来时间执行的intent,系统的AlarmManager执行这个intent
sunshine用过的一个广播:
PendingIntent.getBroadcast() for a Intent that starts an BroadcastReceiver.
Intent alarmIntent = new Intent(getActivity(), SunShineService.AlarmReceiver.class);
alarmIntent.putExtra(SunShineService.LOCATION_QUERY_EXTRA, location);
PendingIntent pi = PendingIntent.getBroadcast(getActivity(), 0, alarmIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager am = (AlarmManager)getActivity().getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 5000, pi);
同理启动服务:
PendingIntent.getService() for an Intent that starts a Service.

Intent 解析

Action Test
可以定义0或多个action
如果一个<intent-filter>不包含任何action,那么所有的intent都匹配失败;但是一个intent如果没有指定action,那么他会通过测试(只要
这个intent-filter包含至少一个action)

Category Test

可以定义0或多个action

intent只要通过一个Category就过了,如果intent不指定Category,总是通过测试,无论定义的什么Category。

官方说是有一个默认的Category:"android.intent.category.DEFAULT",我们必须指定,

也就说,如果要隐式启动还是要指定的?但是感觉没指定也可以啊,可能是显式的问题?官方不会说错的。

注意了,默认给一个"android.intent.category.DEFAULT"。


Data test

暂时没遇到,有时间在看

To specify accepted intent data, an intent filter can declare zero or more<data> elements. For example:

<intent-filter>
    <data android:mimeType="video/mpeg" android:scheme="http" ... />
    <data android:mimeType="audio/mpeg" android:scheme="http" ... />
    ...
</intent-filter>

Each <data>element can specify a URI structure and a data type (MIME media type). There are separateattributes — scheme, host, port,and path — for each part of the URI:

<scheme>://<host>:<port>/<path>

For example:

content://com.example.project:200/folder/subfolder/etc

In this URI, the scheme is content, the host is com.example.project,the port is 200, and the path is folder/subfolder/etc.

Each of these attributes is optional in a <data> element,but there are linear dependencies:

  • If a scheme is not specified, the host is ignored.
  • If a host is not specified, the port is ignored.
  • If both the scheme and host are not specified, the path is ignored.

When the URI in an intent is compared to a URI specification in a filter,it's compared only to the parts of the URI included in the filter. For example:

  • If a filter specifies only a scheme, all URIs with that scheme matchthe filter.
  • If a filter specifies a scheme and an authority but no path, all URIswith the same scheme and authority pass the filter, regardless of their paths.
  • If a filter specifies a scheme, an authority, and a path, only URIs with the same scheme,authority, and path pass the filter.

Note: A path specification cancontain a wildcard asterisk (*) to require only a partial match of the path name.

The data test compares both the URI and the MIME type in the intent to a URIand MIME type specified in the filter. The rules are as follows:

  1. An intent that contains neither a URI nor a MIME type passes thetest only if the filter does not specify any URIs or MIME types.
  2. An intent that contains a URI but no MIME type (neither explicit nor inferable from theURI) passes the test only if its URI matches the filter's URI formatand the filter likewise does not specify a MIME type.
  3. An intent that contains a MIME type but not a URI passes the testonly if the filter lists the same MIME type and does not specify a URI format.
  4. An intent that contains both a URI and a MIME type (either explicit or inferable from theURI) passes the MIME type part of the test only if thattype matches a type listed in the filter. It passes the URI part of the testeither if its URI matches a URI in the filter or if it has a content:or file: URI and the filter does not specify a URI. In other words,a component is presumed to support content: and file: data ifits filter lists only a MIME type.

This last rule, rule (d), reflects the expectationthat components are able to get local data from a file or content provider.Therefore, their filters can list just a data type and do not need to explicitlyname the content: and file: schemes.This is a typical case. A <data> elementlike the following, for example, tells Android that the component can get image data from a contentprovider and display it:

<intent-filter>
    <data android:mimeType="image/*" />
    ...
</intent-filter>

Because most available data is dispensed by content providers, filters thatspecify a data type but not a URI are perhaps the most common.

Another common configuration is filters with a scheme and a data type. Forexample, a <data>element like the following tells Android thatthe component can retrieve video data from the network in order to perform the action:

<intent-filter>
    <data android:scheme="http" android:type="video/*" />
    ...
</intent-filter>

Intent matching

Intent匹配intent filter不仅仅发现激活的目标组件,也可以找到设备上一系列复合intent条件的组件。PackageManager有一写query..()方法查询
返回所有接收一个特定intent的的组件,一些resolve...()方法,决定响应intent最好的组件。
对于活动 queryIntentActivities()
对于服务 queryIntentServices()
对于广播 queryBroadcastReceivers()
APIdemo使用了活动的,对这些查出来复合条件的挨个分类,这样一个类就可以显示,这设计很棒。
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_SAMPLE_CODE);

PackageManager pm = getPackageManager();
List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);



你可能感兴趣的:(Intent深入学习)