[Android开发向导]Intents and Intent Filters

Intent是用来请求其它组件的动作的消息对象,Intent方便了组件之间的通信,这里有三项基本用法:

  • 启动一个activity:

    你可以传入一个Intent参数来调用startActivity()。这个Intent记录着要被启动的activity和一些必要的数据。

    如果当activity被finish时想要接收它的结果,调用startActivityForResult()。包含结果的Intent对象在要接收activity的onActivityResult()回调方法中[译者的话:重写onActivityResult()方法,第三个参数就是包含结果的Intent]

  • 启动一个service:

    你可以传入一个Intent参数来调用startService()开始一个实时操作(比如下载文件)。这个Intent记录着要被启动的service和一些必要的数据。
    如果你用客户端-服务端接口设计,你可以传入Intent通过bindService()来绑定其他组件。

  • 发送一个broadcast:

    你可以传入Intent通过sendBroadcast()、sendOrderedBroadcast()、sendStickyBroadcast()来向其它应用发送broadcast

Intent 类型

  • Explicit intents  [明确的意图]

    特定的组件是通过名字(类的全名)来启动的。你通常可以使用明确Intent来启动你自己应用的组件,因为你知道你想启动的activity或者service的类名。

  • Implicit intents  [不明确的意图]

    不知道特定组件的名字时,我们可以通过指定action来查找。例如,你想让用户显示在地图上显示位置,你可以使用不明确的Intent来请求能够显示位置的应用

        当你创建一个Explicit intent 时来启动activity或者service是,系统将立即启动在Intent对象里面指定的组件

        当创建一个Implicit intents是,系统将在设备中其它应用的manifest文件中找Intent filter来和Intent对象里面的做比较,如果匹配就启动。如果从存在多个匹配的,会弹出一个对话框来让用户选择。

        intent filter 是manifest文件里的一种标记,用来指示可以接收到Intent的类型。例如,你可以指定intent filter让其它组件来启动,你不指定任何intent filter,意味着你只能用过Explicit intent来启动

注意:为了确保应用的安全,通常我们可以只使用Explicit intent来启动service,不指定任何intent filter。使用intent filter存在安全隐患,因为你不能确保service怎样来回应这个Intent,而且用户也看不到哪个service启动了。


上图显示了一个Activity通过Implicit intent来启动另外一个Activity

创建一个Intent

一个Intent对象携带了系统用来判断哪个组件应该启动的信息,附加的信息为了接收组件能正确处理action
下面是Intent包含的主要信息
  • Component name  [组件名字]

    要启动组件的名字。携带了这个信息,表示这是Explicit intent,没有它就表示是Implicit intent

    注意:当你启动时server时,你应该设置Component name,否则你不能确保service怎样来回应这个Intent,而且用户也看不到哪个service启动了。

  • Action  [动作]

    一个字符串用来指定执行特定的操作

    在broadcast Intent中,发生和被报告的action和大程度上取决于其余Intent的结构-特别是data和extras

    你可以为应用定义用户自己的action,但是通常还是使用intent类或者其它framework类定义的action常量,这里有一些公共的action来启动activity

    ACTION_VIEW 当你有一些信息要用其它应用来展示给用户时,例如用图集应用来展示图片或者用地图应用来显示位置,你可以使用包含这个action的Intent来startActivity()

    ACTION_SEND 又名分享Intent,当你有一些数据需要通过其它应用来分享时,例如邮件应用或者社交应用,你可以使用包含这个action的Intent来startActivity()

    去查看下Intent类下定义的通用action常量,其它的action定义在framework的其它地方,例如打开系统设置的action定义在Setting中

    你可以通过Intent的setAction()或者构造器来指定action

    如果要定义你自己的action保证用了你的包名做前缀。例如:

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

  • Data  [数据]

    Data应该包含这URI引用和数据的MIME类型。数据的类型通常是用action决定的。例如 ACTION_EDIT的数据应该包含着被编辑的文档的URI。

    当你创建一个Intent是,处理指定它数据的URI之外,数据类型(MIME类型)通常也是很重要的。一个activity可以显示图片但是也许不能播放音频,而这两种资源的URI是类似的。所以指定数据的MIME类型帮助系统找到接收你Intent的最好的组件。然而,MIME类型有时可以通过URI推测出来-当数据是content: URI,表明这个数据在设备上并且被ContentProvider控制。

    使用setData()设置URI,使用setType()设置MIME类型,必要时可以同时设置setDataAndType()

    注意:当你要同时设置URI和MIME类型时,用setDataAndType()。单独设置会使另外的值作废。

  • Category  [分类]

    一个字符串包含这个Intent应该被何种组件处理的附加信息,任何数字都可以用来描述Category,但是大部分Intent不需要Category。

    这里有一些的Category:

    CATEGORY_BROWSABLE  它的目标activity运行开启网页浏览器来显示链接数据-例如图片或者邮件消息

    CATEGORY_LAUNCHER   这是一个任务的主activity,并且会被系统launcher列入

    你可以通过addCategory()来指定Category

  • Extras  [附加信息]

    以键值对来携带请求action完成所需要的额外信息。有些action需要用到一些额外的准确信息

    我们可以通过putExtra()来添加数据,也可以创建Bundle对象然后通过putExtras()来添加到Intent里

    Intent类下定义了大量EXTRA_* 常量来使用。如果要定义你自己的action保证用了你的包名做前缀。例如:

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

  • Flags  [标识]

    Flags用来作为Intent的元数据。这些标志可以指示系统如何launch一个activity(例如:该任务的活动应该属于哪个)launched后如何处理它(例如:它是否属于最近活动)

implicit intent示例

注意:用户也许没有安装能够处理我们Intent的应用,这样会造成奔溃。为了确保有activity接收,我们也调用Intent对象的resolveActivity()。如果结果非空,表示至少有一个应用可以处理我们Intent。这样我们就可以安全调用startActivity()了。
// 创建 text message字符串
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType(HTTP.PLAIN_TEXT_TYPE); // "text/plain" MIME 类型

// 查找是否有activity可以处理我们Intent
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(sendIntent);
}

强制选择打开方式

Intent intent = new Intent(Intent.ACTION_SEND);
...
	String title = getResources().getString(R.string.chooser_title);

Intent chooser = Intent.createChooser(intent, title);

if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(chooser);
}
这样每次打开之前都要选择打开方式。不设置时,有时用户会选择记住某个打开方式,也行会造成麻烦。

接收Implicit Intent

注意:为了能够接收Implicit Intent,我们必须要设置Category为CATEGORY_DEFAULT。startActivity()和startActivityForResult()发送的都是CATEGORY_DEFAULT。如果你不定义这个Category你讲接收不到Implicit Intent。

注意:为了避免无意中调用了其它应用的Service,通常我们用explicit intent ,所以我们不定义Intent filter

注意:对于所以的activity我们必须定义在manifest文件中定义Intent filter来接受Implicit Intent。但是对于broadcast receiver我们可以通过registerReceiver()、unregisterReceiver()动态注册。这样你应用运行时可以在特定的时间监听特定的broadcast

注意:就算你不设置Intent filter,也不能保证其它应用访问你的组件。因为我们可以通过explicit intent 来访问。为此我们可以把exported 属性设置成false

filter示例

<activity android:name="MainActivity">
    <!-- 应用主入口activity -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity android:name="ShareActivity">
    <!-- 这个activity处理带文本数据的"SEND"action -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
    <!-- 这个activity也处理带多媒体数据的"SEND"和"SEND_MULTIPLE" action -->
    <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>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值