Android Intent

Intent在Android中用于组件间的交互,分为显式和隐式。显式Intent直接指定目标组件,而隐式Intent通过action、category等匹配规则选择合适组件。隐式Intent匹配需考虑action、category、data的匹配。Intent传递数据有限制,大数据可通过ContentProvider等方式传递。

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

Intent在实际工作的使用率可以说和四大组件一样的多

  1. 什么是Intent? ⭐⭐⭐⭐⭐

  1. 显式Intent和隐式Intent的区别?⭐⭐⭐⭐

  1. 在隐式启动中Intent可以设置多个action,多个category吗?⭐⭐⭐⭐

  1. 隐式Intent的匹配规则?⭐⭐⭐⭐⭐

  1. Activity之间传递数据的方式Intent是否有大小限制,如果传递的数据量偏大,有哪些方案?⭐⭐⭐

目录

  • 1、什么是Intent

  • 1.1 显示Intent

  • 1.2 隐式Intent

  • 1.3 Intent的组成部分

  • 1.3.1 componentName

  • 1.3.2 action

  • 1.3.3 category

  • 1.3.4 data

  • 1.3.5 type

  • 1.3.6 extras

  • 1.3.7 flags

  • 1.4 隐式Intent匹配规则总结

  • 1.5 显示Intent与隐式Intent的区别

  • 2、拓展

  • 2.1 Intent携带数据的大小

  • 2.2 PendingIntent

1、什么是Intent

Intent,中文可翻译为“意图”,可用于Android同个应用程序中各个组件之间的交互,或者不同应用程序之间的交互。可以用来表明当前组件的思想和意图,比如想执行某个动作,想发送某些数据等等。每个组件都有不同的启动方法:

  • Activity:可以调用startActivity() 或 startActivityForResult() 传递 Intent来打开新的Activity;

  • Service:可以调用startService()传递 Intent 来启动服务,也可通过 bindService() 传递 Intent 来绑定到该服务;

  • Broadcast,可以调用sendBroadcast()、sendOrderedBroadcast() 或 sendStickyBroadcast() 等方法传递 Intent 来发起广播;

Intent分为显式Intent和隐式Intent,我们以打开新的Activity为例进行讲解。

1.1 显示Intent

显式指定意图,系统就会根据我们指定的意图,打开我们想打开的Activity。Intent有如下构造函数:Intent(Context packageContext, Class<?> cls)。其中第二个参数就是指定想启动的Activity。

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

通过上面两行代码,我们可以显式指定打开SecondActivity.class。

1.2 隐式Intent

不指定特定的意图,而是通过清单文件里,每个Activity节点下事先配置好的(也就是“Intent过滤器”),由系统根据我们设定的Intent,从系统所有Activity中选出最符合的我们要求的Activity。先看看例子:

// 清单文件中 XuruiActivity 提前声明好如下:
	<activity android:name=".XuruiActivity">
		<intent-filter>
			<action android:name="com.example.android.xuruitest"/>
			<category android:name="android.intent.category.DEFAULT"/>
			<category android:name="com.example.android.xuruicategory"/>
		</intent-filter>
	</activity>
// 代码调用
    Intent intent = new Intent();
    intent.setAction(com.example.android.xuruitest);
    intent.addCategory(com.example.android.xuruicategory);
    startActivity(intent); //1

执行 [注释1]的代码后,系统会发现XuruiActivity的所设定的内容,和当前Intent所设定的内容最匹配,系统就会打开XuruiActivity,但这个过程中,我们并没有显式的指出打开XuruiActivity,而是通过设置了一些特定条件进行匹配,如“action”,“category”等,从而隐式地打开了XuruiActivity。

1.3 Intent的组成部分

“action”,“category”都是Intent的组成部分。为了更好的理解隐式Intent,需要了解一个Intent由几部分组成:

  • componentName:目的组件

  • action(动作):用来表现意图的行动

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

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

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

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

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

1.3.1 componentName

指定Intent目标组件的类名。可以这么记得,如果直接指定了componentName,那就是显式Intent。我们可以通过setComponent()、setClass()、setClassName()等方法指定:

// 1、Intent构造
Intent intent = new Intent(this, SecondActivity.class);  
startActivity(intent); 

// 2、setComponent()方法
ComponentName componentName = new ComponentName(this, SecondActivity.class);  //2
ComponentName componentName = new ComponentName(this, "com.example.android.SecondActivity");  //3 
ComponentName componentName = new ComponentName(this.getPackageName(), "com.example.android.SecondActivity");  //4 
  
Intent intent = new Intent();  
intent.setComponent(componentName);  
startActivity(intent); 

// 3、setClass/setClassName方法
Intent intent = new Intent();  
  
intent.setClass(this, SecondActivity.class);  
intent.setClassName(this, "com.example.android.SecondActivity");  
intent.setClassName(this.getPackageName(), "com.example.android.SecondActivity");  
          
startActivity(intent);  

我们看看[注释2-4]这三种方式:

  • [注释2]:this是当前Activity,直接写类名,则该Activity必须在同个包名内;

  • [注释3]:this是当前Activity,类名包括包名,则可以在当前包跳转到其他包的Activity;

  • [注释4]:this是当前Activity所在的应用程序,类名包括包名,则可以在当前包跳转到其他包的Activity;

在可以使用应用的Context代替Activity的Context时,都推荐使用应用的Context,且Activity名称前面加上包名可以打破同个包内的限制,所以推荐使用[注释4]的方式。

1.3.2 action

用来表示意图的行动,一个Intent只能有一个Action。以下是一些比较常见的Action。所有的Action可以在Android开发手册-Intent 查看。

Action

含义

ACTION_MAIN

Android 的程序入口

ACTION_VIEW

显示指定数据

ACTION_EDIT

编辑指定数据

ACTION_DIAL

显示拨号面板

ACTION_CALL

直接呼叫 Data 中所带的号码

ACTION_ANSWER

接听来电

ACTION_SEND

向其他人发送数据(例如:彩信/email)

打开手机的拨号界面的代码可以这么写:

    Intent intent=new Intent();
    intent.setAction(Intent.ACTION_DIAL);
    intent.setData(Uri.parse("tel:1234567"));
    startActivity(intent);

1.3.3 category

用来表示动作的类别,一个Intent可以有多个category,类别越多,代表动作越具体,意图越明确。

1.3.4 data

清单文件里标签具体如下:

属性

解释

scheme

协议

host

主机

port

端口

path

用来匹配完整的路径

pathPrefix

用来匹配路径的开头部分

pathPattern

用表达式来匹配整个路径

mimeType

用来匹配数据类型或MIME类型

举个例子:

<data android:scheme="http"  android:host="www.baidu.com"/>

系统内置的几个 Data 属性常量:

协议

含义

tel:

号码数据格式,后跟电话号码

mailto:

邮件数据格式,后跟邮件收件人地址

smsto:

短信数据格式,后跟短信接收号码

file:///

文件数据格式,后跟文件路径。注意必须是三根斜杠 ///

content://

内容数据格式,后跟需要读取的内容。ContentProvider 特有的格式

1.3.5 type

type 属性用于指定 data 所制定的 Uri 对应的 MIME 类型,通常应用于调用系统 App,比如实现查看文件(文本、图片、音频或者视频等),通过指定文件的 MIME 类型,可以让系统知道用什么程序打开该文件。

常用的 MIME 类型

文件格式

对应的MIME类型

.bmp

image/bmp

.gif

image/gif

.png

image/png

.tif .tiff

image/tiff

.jpe .jpeg .jpg

image/jpeg

.txt

text/plain

.xml

text/xml

.html

text/html

.css

text/css

.js

text/javascript

.mht .mhtml

message/rfc822

.doc

application/msword

.docx

application/vnd.openxmlformats-officedocument.wordprocessingml.document

.rtf

application/rtf

.xls

application/vnd.ms-excel application/x-excel

.xlsx

application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

.ppt

application/vnd.ms-powerpoint

.pptx

application/vnd.openxmlformats-officedocument.presentationml.presentation

.pps

application/vnd.ms-powerpoint

.ppsx

application/vnd.openxmlformats-officedocument.presentationml.slideshow

.pdf

application/pdf

.swf

application/x-shockwave-flash

.dll

application/x-msdownload

.exe

application/octet-stream

.msi

application/octet-stream

.chm

application/octet-stream

.cab

application/octet-stream

.ocx

application/octet-stream

.rar

application/octet-stream

.tar

application/x-tar

.tgz

application/x-compressed

.zip

application/x-zip-compressed

.z

application/x-compress

.wav

audio/wav

.wma

audio/x-ms-wma

.wmv

video/x-ms-wmv

.mp3 .mp2 .mpe .mpeg .mpg

audio/mpeg

.rm

application/vnd.rn-realmedia

.mid .midi .rmi

audio/mid

在清单文件中的里,只有<data>没有<type>。但在代码里就可以调用:

  • setType(): 调用后设置 mimeType,然后将 data 置为 null;

  • setData(): 调用后设置 data,然后将 mimeType 置为 null;

  • setDataAndType(): 调用后才会同时设置 data 与 mimeType。

举个打开百度的例子:

<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>
    intent = new Intent();
    intent.setAction(Intent.ACTION_VIEW);
    Uri data=Uri.parse("http://www.baidu.com");
    intent.setData(data);
    startActivity(intent);

1.3.6 extras

extras:拓展信息,通常用于多个Activity之间的数据交换,extras属性是一个Bundle对象,通过键值对,对数据进行存储。extras在日常开发中非常常见:

Intent intent = new Intent(this, SecondActivity.class);
intent.putExtra("name", "Tony");
intent.putExtra("age", 28);
startActivity(intent);

1.3.7 flags

flags:标志位,指明当前的Intent所期望的运行模式,具体有:

  • FLAG_ACTIVITY_CLEAR_TOP:新跳转的Activity如果已经在栈中,则将其上面的所有Activity都清出栈,相当于Activity四大启动模式中的singleTask;

  • FLAG_ACTIVITY_SINGLE_TOP:返回栈没有当前需要跳转的Activity,则新建该Activity并放入栈顶。但如果该Activity已经在栈顶了,则不会再重新创建新的Activity。相当于Activity四大启动模式中的singleTop;

  • FLAG_ACTIVITY_NEW_TASK:假设当前返回栈有A B C这3个Activity。此时C通过intent跳转到D,并且这个intent添加了FLAG_ACTIVITY_NEW_TASK标记,如果D这个Activity在AndroidManifest.xml中的声明中添加了Task affinity,系统首先会查找有没有和D的Task affinity相同的task栈存在,如果有存在,将D压入那个栈,如果不存在则会新建一个D的affinity的栈将其压入。但如果D的Task affinity默认没有设置,则会把其压入原来的返回栈,变成:A B C D,这样就和不加FLAG_ACTIVITY_NEW_TASK标记效果是一样的了。注意如果试图从非activity的非正常途径启动一个activity,比如从一个service中启动一个activity,则intent比如要添加FLAG_ACTIVITY_NEW_TASK标记。

1.4 隐式Intent匹配规则总结

隐式Intent的匹配规则,就是根据当前Intent所设置的action、category、data和清单文件中使用 <intent-filter> 元素为组件声明一个或多个 Intent 过滤器的、、几个属性做匹配,找到最合适的。总结如下:

  • 清单文件中:category如要使用默认值,则设为android.intent.category.DEFAULT,否者组件不会接收隐式 Intent;

  • 如果不希望自己的组件,如自定义的XXXActivity被其他应用程序调用,则清单文件中,XXXActivity下面不要声明 <intent-filter> ,并且将该组件的 exported 属性设置为 false;

  • 代码中:如果没有指定category,系统会默认设置为android.intent.category.DEFAULT;

  • 一个Intent只有一个action,但可以有多个category,只有当action和所有category和某个<intent-filter>都同时匹配,才算匹配成功。

  • 一个<intent-filter>可以设置一个或多个<action>,当Intent能和<intent-filter>的任意一个action匹配就算匹配成功;

  • 一个<intent-filter>可以设置一个或多个<category>,只有当Intent能和<intent-filter>的所有category匹配才算匹配成功;

  • 如果有多个组件被匹配成功,就会以对话框列表的方式让用户进行选择。

1.5 显示Intent与隐式Intent的区别

对明确指出了目标组件名称的Intent,我们称之为“显式Intent”。 对于没有明确指出目标组件名称的Intent,则称之为“隐式 Intent”。

2、拓展

2.1 Intent携带数据的大小

Intent传递数据大小的限制大概在1M左右,超过这个限制就会静默崩溃。所以,如果是同个应用程序之间的数据传输,可以使用文件缓存或者磁盘缓存,如果是应用程序之间,则推荐使用ContentProvider进行数据传输。

2.2 PendingIntent

PendingIntent就是延迟或者挂起的Intent,平时也会使用到,在此做个拓展。如接收到消息需要在桌面做通知时,可以这么写:

pendingIntent = PendingIntent.getActivities(
            applicationContext, 0, intents,
            PendingIntent.FLAG_UPDATE_CURRENT
        )

 val builder = NotificationCompat.Builder(applicationContext, FORCE_UPDATE_NOTIFY_CHANNEL_ID)
            builder.setWhen(System.currentTimeMillis())
            .setContentTitle(showTitle)
            .setContentText(showContent)
            .setContentIntent(pendingIntent) //5
            .setPriority(NotificationCompat.PRIORITY_MAX)
            .setCategory(NotificationCompat.CATEGORY_MESSAGE)
            .setVisibility(VISIBILITY_PUBLIC)
            .setAutoCancel(true)
            .setSmallIcon(R.drawable.ic_launcher)

其中,[注释5]的pendingIntent就是PendingIntent。PendingIntent的具体用法和实现原理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值