Intent就是一个消息传递对象,我们可以通过它在另外一个应用程序的组件上请求一个动作
Intent Filter的重点就在Filter

Intent的3种主要使用环境

开启一个Activity
startActivity(),startActivityForResult()

开启一个服务
startService(),bindService()

发送广播
sendBroadcast(), sendOrderedBroadcast(), sendStickyBroadcast()

Intent的分类

显示Intent
指定了组件的完全限定类名(fully-qualified class name),一般在启动自己APP里的Activity里使用 这种方法

隐式Intent
没有指定组件的完全限定类名,取而代之的是Action等其他属性

Intent的组成

Component name
Activity和Service的完全限定类名,这里我们需要注意的是Service一般都直接指定它的名字,因为使用隐式的,Service本身又是没有界面的,所以我们不知道到底是哪个Service被启动了。设置组件的名字可以使用Intent的下列方法构造函数, setComponent(), setClass(), setClassName()

Action
简单来说就是一个String对象,除了系统的Action,我们也可以在定义自己的Action,但是一定要带上包名,如下所示。

static final String ACTION_TIMETRAVEL = "com.renjinming.action.TIMETRAVEL";

指定Intent的Action我们可以通过以下方法,一个是Intent的构造方法,还有就是setAction。

data
哪两个部分?data的Uri引用和/或者data的MIME type
Uri主要包括scheme, host, port, and path

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

content就是scheme,com.example.project就是host,200就是port,
folder/subfolder/etc及时path。
data的MIME type很大程度上取决于intent的action
如果只是设置data的Uri,调用setData(),如果设置MIME type,调用 setType(),如果两个都设置,则调用setDataAndType() 。不能分别调用setData和setType,因为分别调用对于另外一个来说值为空。

Category
同样也是一个String对象。指定哪种组件将接受这个Intent
设置它通过Inent的 addCategory()方法。举两个常用的Category
CATEGORY_LAUNCHER
设置这个属性Activity将会出现在系统的启动界面上
CATEGORY_DEFAULT
如果想让组件通过隐式来启动,则一定要设置这个属性

Extras
一个键值对,可以设置额外的信息,通过两种方法来设置,一种是putExtra(),还有一种是putExtras()。后者的区别就是通过Bundle来创建所有的键值对象,然后把它传进去,我们需要注意的规范就是设置键这个字符串常量的时候,应该带上包名。命名的时候应该为EXTRA_*如下所示

static final String EXTRA_GIGAWATTS = "com.renjinming.EXTRA_GIGAWATTS";

Flags

Flags defined in the Intent class that function as metadata for the intent. The flags may instruct the Android system how to launch an activity (for example, which task the activity should belong to) and how to treat it after it’s launched (for example, whether it belongs in the list of recent activities).

显式Intent;隐式Intent

下面举两个例子
显式Intent,一定要定义组件的名字,其他的属性是可选的。

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

隐式Intent,没有组件的名字,在启动一个Activity之前需要调用Intent.resolveActivity() 这个方法,传入getPackageManager()来验证它是否为空

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

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

在这个实例中我们没有加入data,但是Extra的类型已经被type指定了。

接收隐式Intent

在manifest文件当中,在组件的结点里,指定<intent-filter>结点,在这个结点里我们又可以包含下面的结点,<data> <action> <category>,如果我们想接收到隐式的intent,就必须指定 CATEGORY_DEFAULT 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>

那么我们如何静止别人启动自己的组件呢,在组件的属性里,我们指定exported 的属性为false。
在代码当中我们也可以接收到Intent,registerReceiver()unregisterReceiver(),注意这里我们接收的是BroadcastIntent。

那么两者的区别呢,在manifest注册的总是活动的,即使你的应用没有启动,也会发生作用,而在代码当中的则不是。

PendingIntent

PendingIntent是Intent的一层包装,Intent是及时的,而PendingIntent则不是,以下是它的3种主要使用环境。

  • Notification
  • App Widget
  • AlarmManager
    下面是3种主要的使用方法
    PendingIntent.getActivity() 开启一个 Activity.
    PendingIntent.getService() 开启一个 Service.
    PendingIntent.getBroadcast() 获得一个 BroadcastReceiver.

Intent匹配

PackageManager有一系列相似的query…()和resolve…()方法。第二个方法返回决定最适合组件(返回对象不是组件)