学习Intent 的意图

        Intent 是Android 系统开发学习中比较重要的知识点,它相当于一个传递命令的媒介,你想要做什么(比如启动一个Activity、Service或者BroadcastRecevier),只要赋给Intent 对象对应的参数和属性,就可以达到想要实现某些功能的目的。打个不太恰当的比喻,假使我有一辆Intent 牌的卡车,你想让我运水,就要在卡车的后车厢放些水桶(参数1)来盛放水;你想让我运送天然气,就要在后车厢放些煤气罐(参数2)盛放气体;。。。但是不管后车厢的水桶或者煤气罐怎么变化,这个Intent 牌的卡车是不变的。之所会这样设计,一方面提供了统一的编程模型,方便编写、管理,更重要的是,如果系统只是想启动某些特定功能的程序(同一个设备可能同时安装多个音乐播放器、浏览器等),避免了硬编码耦合的现象。
        从整体结构上来看,Intent 分为两种:显式的Intent 和隐式的Intent。区别在于,显式的Intent 指定了我要启动哪个Activity、Service或者BroadcastReceiver,但是隐式的Intent 却给定了限定条件,符合设定的一些action、data、category 等属性条件的都是我想要启动的对象。这个就好比电影【心花路放】里面的两个角色:黄徐峥饰演渤和徐峥,黄渤饰演的就属于显式的Intent,老子就要康小雨,除了她我谁都不爱;徐峥的角色就随(hao)意(se)多了,属于隐式的Intent,只要脸蛋好、身材辣(类似于action、data、category 等属性)的妹子,我都可以要。
        在介绍两种Intent 之前,我们先来讲解下关于Intent 的六个属性:

一、基本属性

         1)Component name
        Intent 的Component 属性需要接受一个ComponentName 对象,ComponentName 包含如下几个构造方法:
构造方法    
介绍
ComponentName(String pkg, String cls)
创建pkg包下cls 类所对应的组件
ComponentName(Context pkg, String cls)
创建pkg 所对应包下cls 类所对应的组件
ComponentName(Context pkg, Class<?> cls)
创建pkg 所对应包下cls 类(泛型)所对应的组件
ComponentName(Parcel in)
创建被序列化对象所对应的组件
        
        除此之外,Intent 还包含了如下三个方法:
方法
介绍
setClass(Context packageContext, Class<?> cls)
设置该Intent 将要启动组件对应的类
setClassName(Context packageContext, StringclassName)
设置该Intent 将要启动packageContext 对应的类名
setClassName(String packageName, StringclassName)
设置该Intent 将要启动包中对应的类名
       具体代码可参照【二、显式Intent】中的例子。

         2)Action
        Action 属性是要完成指定的动作,比如 ACTION_VIEW  可以展现相应的组件显示给用户; ACTION_SEND  则可以调用设备中的具备发送功能的app,如邮箱等。
系统给我们提供了一系列的Action,可以帮助我们完成一些常见的行为,如:
Action
目标组件
介绍
ACTION_CALL
Activity
初始化电话呼叫功能
ACTION_EDIT
Activity
提供编辑功能
ACTION_MAIN
Activity
作为程序的入口启动
......
Activity
......
ACTION_BATTERY_LOW
BroadcastReceiver
电量低的警告
ACTION_HEADSET_PLUG
BroadcastReceiver
耳机已经被插入或者拔出设备
......
BroadcastReceiver
......
      以上只是简单列出常见的一些系统级的Action 行为,你可以发现上面没有列出Service 相关的Action,不是我给略过没提,而是Android 的API 就没有给出相关的数据。
      这是因为,Android 系统只允许开发人员通过显式Intent 的方式直接启动Service(基于安全的角度考虑),否则的系统会抛出异常(自Android5.0 起)。

         3)Data
         关于Data 我们可以直接引用官方API 中的介绍说明:

        数据运行的URI和其MIME类型,不同的action被配与不同的data说明。例如,如果是ACTION_EDIT,那么他的data就包含提供编辑功能的文本的URI。如果是ACTION_CALL,那么他的data就是号码的URI--tel:。同样的,如果是ACTION_VIEW并且data是http: URI,那么接收Intent的activity将下载并显示URI所指向的内容。

当为某个组件匹配一个可以处理数据的Intent的时候,通常除了要了解Data的URI以外,重要的是要知道Data的类型(MIME type)。例如,一个可以展示图片的组件不应该被调用来播放音频。

        在很多情况下,Data的类型可以从URI中推测出来,特别是URI所展示的内容:指出了Data被用在什么位置及被哪种content provider控制(参考separate discussion on content providers)。但是Data的类型也可以在Intent中明确的设定。setData()方法设置Data的URI,setType()设置Data的类型(MIME type),setDataAndType()两者一起设置(注意:如果要同时设置Data和Type只能使用setDataAndType() 方法,如果先后使用了setData()setType(),那么后者会将前者覆盖,达不到同时设置两者的目的)。

​       

        4)Category

        Category 即种类、类别的意思,从它的单词中我们就可以看出它的作用,表示一种类型的组件来响应Action 中的行为(一般和Action 属性组合使用)。我们可以使用addCategory()方法往Intent 中添加属性,如果需要传入多种Category,那么继续调用此方法即可。


       5)Extra

        Intent 的Extra属性通常用于在多个Action 之间进行数据交换,Intent 的Extra 属性应该是一个Bundle 对象,Bundle 对象就像是一个Map 对象,它可以存入多个key-value 对,这样就可以通过Intent 在不同Activity 之间进行数据交换了。


        6)Flag

        Intent 的Flag 属性用于为该Intent 添加一些额外的标记,可以通知Android 系统决定如何启动Activity(如:此Activity 属于哪个任务)或者启动后需要做什么动作(比如,是否将此Activity 添加到Recent Activities 列表中),开发人员可调用 setFlags() 方法设置相应的标记。

二、显式Intent

        系统根据Intent 接收到的参数,直接跳转到参数指定的组件(Activity、Service或者BroadcastRecevier)当中。下面代码是以显式的方式制定跳转到SubActivity 的例子:

点击(此处)折叠或打开

  1.         button = (Button) this.findViewById(R.id.button);
  2.         button.setOnClickListener(new View.OnClickListener() {
  3.             public void onClick(View v) {
  4.                 Intent intent = new Intent();
  5.                 ComponentName component = new ComponentName(MainActivity.this, SubActivity.class);
  6.                 intent.setComponent(component);
  7.                 MainActivity.this.startActivity(intent);
  8.             }
  9.         });
        其实上面代码中的红色部分也可以简写成如下形式:

点击(此处)折叠或打开

  1.         button = (Button) this.findViewById(R.id.button);
  2.         button.setOnClickListener(new View.OnClickListener() {
  3.             public void onClick(View v) {
  4.                 Intent intent = new Intent(MainActivity.this, SubActivity.class);
  5.                 MainActivity.this.startActivity(intent);
  6.             }
  7.         });
        总之,只要指定了特定的组件,有明确的组件接收跳转,就属于显式的Intent。
        同样的,我们也可以使用相应的方法跳转到Service 和BroadcastReceiver,但是相应的 startActivity() startActivityForResult()  方法就要换成Service 的 startService()  和 bindService() 方法,以及BroadcastReceiver 的 sendBroadcast() sendOrderedBroadcast() 和  sendStickyBroadcast() 方法。具体相关操作,请直接参照Service 和BroadcastReceiver 的API。
        

三、隐式Intent

      在代码部分,开发人员可以按需给Intent 设置相应的属性,而在AndroidManifest.xml 中的组件也可以设置相应的【<intent-filter>......</intent-filter>】标签,当代码中的Intent 属性和xml 文件中组件的【<intent-filter>】标签相匹配的时候,就可以启动此标签所属的组件。当然,能够匹配的组件可能会有多个、一个甚至没有。所以,如果要启动的目标组件是Activity,在此之前可以通过Intent 对象调用resolveActivity(),当它返回的值非空时,那么开发人员就可以直接调用startActivity();而当返回的内容为空时,就不要调用startActivity() 方法了,以防App crash。

        下面是一个关于隐式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(HTTP.PLAIN_TEXT_TYPE); // "text/plain" MIME type

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

四、配置Intent Filter

        前面介绍了如何在代码中使用隐式的Intent, 然而如果开发人员不在AndroidManifest.xml 的组件中配置 <intent-filter> 】标签,那么隐式Intent 则无法使用。
      <intent-filter>】标签由上述所说的三种属性组成:action、data和category。
      对于Activity 而言,必须把CATEGORY_DEFAULT (<category android:name="android.intent.category.DEFAULT" />)配置在标签中,否则系统将无法找到正确匹配的Activity 以启动。
      下面是关于配置<intent-filter>的例子:
<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>



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值