安卓Intent 机制

本文详细介绍了Android中的Intent机制,包括Intent的概念、组件间的交互方式、Intent的七种属性(组件、动作、类别、数据、数据类型、扩展信息、标志位)以及Intent的使用方法(显式和隐式)。Intent作为Android组件间通信的重要桥梁,允许应用启动其他组件或在同一应用内部进行通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

一. 什么是Intent

 

1. intent 概念

  • Android中提供了Intent机制来协助应用间的交互与通讯,或者采用更准确的说法是,Intent不仅可用于应用程序之间,也可用于应用程序内部的 activity,  service 和  broadcast receiver 之间的交互。Intent这个英语单词的本意是“目的、意向、意图”。

 

  • Intent是一种运行时绑定(runtime binding)机制,它能在程序运行的过程中连接两个不同的组件。通过Intent,你的程序可以向Android表达某种请求或者意愿,Android会根据意愿的内容选择适当的组件来响应。

activity、service和broadcast receiver之间是通过Intent进行通信的,而另外一个组件Content Provider本身就是一种通信机制,不需要通过Intent。

2. 三种组件的发送intent 不同的方式

  • Activity:使用Context.startActivity() 或 Activity.startActivityForResult(),传入一个intent来启动一个activity。使用 Activity.setResult(),传入一个intent来从activity中返回结果。
  • Service:将intent 对象传给 Context.startService() 来启动一个service或者传消息给一个运行的service。将intent对象传给 Context.bindService()来绑定一个service
  • BroadcastService:将intent对象传给 Context.sendBroadcast(),Context.sendOrderedBroadcast(),或者Context.sendStickyBroadcast()等广播方法,则它们被传给 broadcast receiver。

3. Intent 的七种属性

1)component(组件):目的组件:

Component属性明确指定Intent的目标组件的类名称。(属于直接Intent)

如果 component这个属性有指定的话,将直接使用它指定的组件。指定了这个属性以后,Intent的其它所有属性都是可选的。

例如,启动第二个Activity时,我们可以这样来写:

button1.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //创建一个意图对象
                Intent intent = new Intent();
                //创建组件,通过组件来响应
                ComponentName component = new ComponentName(MainActivity.this, SecondActivity.class);
                intent.setComponent(component);
                startActivity(intent);
            }
        });

但是,我们一般常有的是:

Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);

2)Action(动作):用来表现意图的行动

在Intent中,Action就是描述做、写等动作的,当你指明了一个Action,执行者就会依照这个动作的指示,接受相关输入,表现对应行为,产生符合的输出。在Intent类中,定义了一批量的动作,比如ACTION_VIEW,ACTION_PICK等, 基本涵盖了常用动作。加的动作越多,越精确。

Action 是一个用户定义的字符串,用于描述一个 Android 应用程序组件,一个 Intent Filter 可以包含多个 Action。在 AndroidManifest.xml 的Activity 定义时,可以在其 <intent-filter >节点指定一个 Action列表用于标识 Activity 所能接受的“动作”。

系统的默认组件(如:默认浏览器、图片浏览器、拨号页面等)都可以响应相应的 action。下面给出几个比较常见内置 action。

ACTION_VIEW
向用户展示某信息,比如使用浏览器打开网址,用图片应用显示图片等

ACTION_SEND
用于发送数据,比如电子邮件应用或者一些社交应用。

ACTION_DIAL
显示带拨号盘的页面,让用户可以进行拨号动作。

自定义action

供 Intent 在自己的应用内使用(或者供其他应用在自己的应用中调用组件)。如果定义自己的操作,请确保将应用的软件包名称作为前缀。 例如:

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

3)category(类别):用来表现动作的类别

该 Activity 是任务的初始 Activity,在系统的应用启动器中列出。

需要注意的是大部分 Intent 虽然不需要设置 Category,但是在调用使用 Intent 的方法(如starActivity()等)的时候,会默认为该 Intent 添加 CATEGORY_DEFAULT,相应目标组件的Intent过滤器应该添加该类别

 

例如:

<intent-filter>

  <action android:name="com.vince.intent.MY_ACTION"></action>

  <category android:name="com.vince.intent.MY_CATEGORY"></category> 

  <category android:name="android.intent.category.DEFAULT"></category> 

</intent-filter>   

新建一个工程文件smyh006_Intent01,在默认文件的基础之上,新建文件SecondActicity.java和activity_second.xml。

紧接着,我们要到清单文件中进行注册,打开AndroidManifest.xml,添加SecondActivity的action和category的过滤器:

如果定义自己的操作,请确保将应用的软件包名称作为前缀。

        <activity
            android:name=".SecondActivity">
            <intent-filter>
                 <action android:name="com.example.smyh006intent01.MY_ACTION"/>
                 <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

上方代码,表示SecondActicity可以匹配第4行的MY_ACTION这个动作,此时,如果在其他的Acticity通过这个action的条件来查找,那SecondActicity就具备了这个条件。

注:如果没有指定的category,则必须使用默认的DEFAULT(即上方第5行代码)。

也就是说:只有<action>和<category>中的内容同时能够匹配上Intent中指定的action和category时,这个活动才能响应Intent。如果使用的是DEFAULT这种默认的category,在稍后调用startActivity()方法的时候会自动将这个category添加到Intent中。

现在来修改MainActivity.java中按钮的点击事件,代码如下:

button1.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //启动另一个Activity,(通过action属性进行查找)
                Intent intent = new Intent();
                //设置动作(实际action属性就是一个字符串标记而已, 找到 sencond的activity )
                intent.setAction("com.example.smyh006intent01.MY_ACTION"); //方法:Intent android.content.Intent.setAction(String action)
                startActivity(intent);
            }
        });

4)data(数据):表示与动作要操纵的数据

  • Data属性是Android要访问的数据,和action和Category声明方式相同,也是在<intent-filter>中。
  • 多个组件匹配成功显示优先级高的; 相同显示列表。

Data是用一个uri对象来表示的,uri代表数据的地址,属于一种标识符。通常情况下,我们使用action+data属性的组合来描述一个意图:做什么

使用隐式Intent,我们不仅可以启动自己程序内的活动,还可以启动其他程序的活动,这使得Android多个应用程序之间的功能共享成为了可能。比如应用程序中需要展示一个网页,没有必要自己去实现一个浏览器(事实上也不太可能),而是只需要条用系统的浏览器来打开这个网页就行了。

打开指定网页:

此时只是使用默认浏览器打开

button1.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_VIEW);
                Uri data = Uri.parse("http://www.baidu.com");
                intent.setData(data);
                startActivity(intent);
            }
        });

如果需要多个组件,格外程序匹配,则需要使用 配置清单

       <activity
            android:name=".SecondActivity">
            <intent-filter>
                 <action android:name="android.intent.action.VIEW" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <data android:scheme="http" android:host="www.baidu.com"/>
            </intent-filter>
        </activity>

5) type(数据类型):对于data范例的描写

如果Intent对象中既包含Uri又包含Type,那么,在<intent-filter>中也必须二者都包含才能通过测试。

Type属性用于明确指定Data属性的数据类型或MIME类型,但是通常来说,当Intent不指定Data属性时,Type属性才会起作用,否则Android系统将会根据Data属性值来分析数据的类型,所以无需指定Type属性。

data和type属性一般只需要一个,通过setData方法会把type属性设置为null,相反设置setType方法会把data设置为null,如果想要两个属性同时设置,要使用Intent.setDataAndType()方法。

【任务】:data+type属性的使用
【实例】:播放指定路径的mp3文件。

button.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_VIEW);
                Uri data = Uri.parse("file:///storage/sdcard0/平凡之路.mp3");
                //设置data+type属性
                intent.setDataAndType(data, "audio/mp3"); //方法:Intent android.content.Intent.setDataAndType(Uri data, String type)
                startActivity(intent);
            }
        });

6)extras(扩展信息):扩展信息

是其它所有附加信息的集合。使用extras可以为组件提供扩展信息,比如,如果要执行“发送电子邮件”这个

动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。

比如:

基本类型的传出与回传

在目标组件中取出 Intent 的方法根据数据类型有非常多,这里不一一列举,只给出一般格式。

方法描述默认取值
getXxxExtra(String name,基本数据类型 默认值)Xxx 为基本数据类型Extra 中无对应键名时,取方法参数 2
getXxxExtra(String name)Xxx为Srting等引用类型Extra 中无对应键名时,取值 null
getBundleExtra(String name)取出Bundle对象的方法Extra 中无对应键名时,取值 null
getXxxArrayExtra()取出Xxx类型对应数组方法Extra 中无对应键名时,取值 null
    //添加 Extra 示例
    Intent intent = new Intent(this,TagerActivity.class);
    intent.putExtra("extra_int",1000);
    int[] ints={1,2,3};
    intent.putExtra("extra_int_array",ints);
    intent.putExtra("extra_string","teger Activity");
    startActivity(intent);

------------------------------------------
    //对应取出数据示例
    Intent intent=getIntent();
    int i=intent.getIntExtra("extra_int",0);
    int[] ints=intent.getIntArrayExtra("extra_int_array");
    String a=intent.getStringExtra("extra_string");

Activity的数据的回传

把数据传回上个活动也是 Intent 比较常用的方法之一。
实现的方式是在启动活动时使用startActivityForResult(Intent intent,int requestCode)代替startActivity(Intent intent),当被启动活动销毁时,就会携带一个 Intent 回调到调用startActivityForResult()方法的Activity的startActivityForResult() 方法。关于 Intent 添加 Extra,和数据的取出和普通的用法并没有什么区别。

基本的步骤是:
A、调用startActivityForResult()方法启动新 Activity,该方法有两个参数,参 1 为 Intent,参 2 为 int 类型的唯一请求码,用于判断数据来源。
B、在新 Activity 中调用setResult()方法把携带希望回传数据的 Intent 作为参数传入。
C、重写原 Activity 的onActivityResult() 方法。该方法携带 3 个参数,参 1 为启动 Activity 的请求码 requestCode,参 2 为表示处理结果是否成功的 resultCode,参 3 为携带数据的 Intent。
重写的主要逻辑是:先通过 requestCode 判断数据来源(根据场景,原 Activity 可能启动不同新 Activity);然后通过 resultCode 判断处理结果是否成功;最后取出 Intent 中数据进行处理即可。

    //原 Activity 中启动新 Activity 并请求返回数据
    Intent intent = new Intent(this,TagerActivity.class);
    startActivityForResult(intent,1);

------------------------------------

    //新 Activity 中设定返回 Intent 并销毁,销毁后会回调到原 Activity 的 onActivityResult()方法
    Intent intent=new Intent();
    intent.putExtra("extra_boolean",true);
    setResult(RESULT_OK,intent);
    finish();

------------------------------------

  //原 Activity 中重写 onActivityResult() 方法
  @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode){
      case 1:
        if (resultCode==RESULT_OK){
          boolean b=data.getBooleanExtra("extra_boolean",false);
        }
        break;
      default:
    }
  }

7)Flags(标志位):期望这个意图的运行模式

一个程序启动后系统会为这个程序分配一个task供其使用,另外同一个task里面可以拥有不同应用程序的activity。那么,同一个程序能不能拥有多个task?这就涉及到加载activity的启动模式

使用方法:

Intent intent = new Intent(MainActivity.this,SecondActivity.class);
//相当于singleTask
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

4. Intent的使用方法

Intent 主要分为显式 Intent 和隐式 Intent,根据显隐用法不同。

1)显式方法

显式 Intent 通常应用在自己的程序中,启动特定组件。用法比较简单,就是构造一个带有目标组件名的 Intent,作为参数传入上述方法即可,调用方法后会直接启动相应组件。
值得注意的就是在5.0之后的系统, Service 只能通过显式 Intent 启动

2)隐式方法

隐式 Intent 允许启动其他应用中的组件,在调用发送 Intent 的方法后,该 Intent 会交由 Android 系统进行匹配,(匹配根据信息是 action、data、category 这3项,即本文第一张图片 Intent 包含信息中标蓝色部分)筛选出整个设备可响应该 Intent 的组件。下图官方文档对隐式 Intent 如何传递启动其他应用组件的图解:

隐式 Intent 如何通过系统传递以启动其他 Activity 的图解:

[1] Activity A 创建包含操作描述的 Intent,并将其传递给 startActivity()。

[2] Android 系统搜索所有应用中与 Intent 匹配的 Intent 过滤器。 找到匹配项之后,

[3] 该系统通过调用匹配 Activity(Activity B)的 onCreate() 方法并将其传递给 Intent,以此启动匹配 Activity。

Intent过滤器

Intent 过滤器是 manifests 里组件的子标签<intent-filter>,一个控件可以声明一个或者**多个 **Intent 过滤器,只要其中一个通过匹配,该组件就可以相应相应 Intent。先来看一个官方给出的 Intent 过滤器示例:

<activity android:name="MainActivity">
    <!-- 应用的首页面,会显示在启动器中 -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity android:name="ShareActivity">
    <!-- 该活动可以处理 SEND这个 aciton,且处理数据类型为无格式文本 -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
     <!--需要响应隐式Intent的活动必须添加 android.intent.category.DEFAULT这个分类,因为starActivity()方法会默认为Intent添加-->
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
    <!-- 此为同一个 Activity 的第二个过滤器  该活动可以处理 "SEND" 和 "SEND_MULTIPLE"两种 aciton  处理数据类型为多媒体数据(包括图片、视频和全景照片) -->
    <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>

这里值得注意的几个点:

  • 1 Intent 只能有1个 action,而 Intent 过滤器可有多个 action
  • 2 需要响应隐式 Intent 的 Activity 的 Intent 过滤器中必须添加 android.intent.category.DEFAULT这个分类

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值