一、定义
1. Intent是什么?
Intent是一个信息传递对象,可以用来启动组件(Activity、Service、Broadcast Reciver)以及进行组件之间的数据传递,主要完成下列工作:
-
标明本次通信从哪里来、到哪里去、要怎么走
-
发起方携带本次通信需要的数据内容,接收方从收到的Intent中解析数据
-
发起方若想判断接收方的处理结果,Intent就要负责让接收方传回应答的数据内容
2. 组成部分
| 元素名称 | 设置方法 | 说明与用途 |
|---|---|---|
| Component | setComponent() | 组件,设置组件名称,显示 Intent 必选参数 |
| Action | setAction() | 动作,指定动作行为,例如查看或者选取,隐式 Intent 必选参数 |
| Data | setData() | 引用待操作数据或者该数据的MIME类型的URI对象,提供的数据类型通常由Intent的操作决定,用于隐式Inent |
| Category | addCategory() | 类别,指定意图的操作类别,用于隐式Intent,一般不需要设置 |
| Type | setType() | 数据类型,表示数据的MIME类型 |
| Extras | putExtra()、putExtras() | 扩展信息,携带完成请求操作所需要的附加信息的键值对 |
| Flags | setFlags() | 标志位,指定Intent的运行模式 |
- 补充:
MIME是描述消息内容类型的标准,用来表示文档、文件或字节流的性质和格式。MIME消息能包含文本、图像、音频、视频以及其他应用程序专用的数据
通用结构:type/subtype
常见类型:
-
超文本标记语言文本 .html:text/html
-
普通文本 .txt: text/plain
-
RTF 文本 .rtf: application/rtf
-
GIF 图形 .gif: image/gif
-
JPEG 图形 .jpeg、.jpg: image/jpeg
-
au 声音文件 .au: audio/basic
-
MIDI 音乐文件 mid、.midi: audio/midi、audio/x-midi
-
RealAudio 音乐文件 .ra、.ram: audio/x-pn-realaudio
-
MPEG 文件 .mpg、.mpeg: video/mpeg
-
AVI 文件 .avi: video/x-msvideo
-
GZIP 文件 .gz: application/x-gzip
-
TAR 文件 .tar: application/x-tar
二、分类
1. 显示Intent
通过指定具体类名启动一个组件,另外,Android5.0以后规定必须显示启动Service
Intent intent = new Intent(this, EndActivity.class);
startActivity(intent);
2. 隐式Intent
无需指定类名,通常用于启动其他应用程序的组件
-
主要特征
-
Action:例如 ACTION_VIEW 用于查看数据,ACTION_SEND 用于发送数据等
-
Data: 通过setData()或setType()方法设置,指定要处理的数据的URI或MIME类型(需要同时设置URI和MIME类型,只能调用setDataAndType()方法,而不能分别调用setData()和setType(),因为调用setData()时会首先将setType()中的内容置空,反之亦然)
-
Category: 可选,例如 Intent.CATEGORY_BROWSABLE 表示可以通过浏览器打开
-
-
原理
当隐式地启动一个service或activity时,Intent会根据其中的内容,匹配其他组件中manifest文件的Intent-filter,启动符合条件的组件,并把Intent中的参数传过去,如果有多个intent-filter满足条件,那么系统会弹出一个对话框,由用户决定启动哪个组件。
流程:
-
首先Activity A利用传入的Intent调用startActivity();
-
系统会根据该Intent的条件搜索Android系统中所有匹配的组件;
-
若找到了匹配intent的intent-filters所属的组件(Activity B),则启动该组件,并回调onCreate()方法,同时将Intent传递过去。
-
用法示例
在使用时候,通常在配置文件AndroidManifest.xml中配置Activity的过滤规则,然后在Activity中配置Intent
-
AndroidMainfest.xml中的代码
-
标签说明
<action />首先IntentFilter中可以有多个action,Intent最多能有1个。
(1) 如果
<intent-filter>标签中有多个<action/>,那么Intent请求的Action,只要匹配其中的一条<action/>就可以通过了这条的动作测试(2) 如果
<intent-filter>中没有<action/>,那么无论什么Intent请求都无法和这条匹配(3) 如果
<intent-filter>中有<action/>,若intent 中不存在action,那么可以通过;如果intent中存在action,那么intent中的action必须是IntentFilter中的其中一个(区分大小写)<category />首先IntentFilter中可以有多个category,Intent也可以有多个。
(1)如果IntentFilter不存在category,那么所有的intent都无法通过。有一个例外,Android把所有传给startActivity()的隐式意图当作他们包含至少一个类别:"android.intent.category.DEFAULT" 。 因此,想要接收隐式意图的活动必须在它们的意图过滤器中包含"android.intent.category.DEFAULT"。
(2)如果IntentFilter存在category,如果intent中不存在category,可以通过。如果intent中存在,那么intent中的所有category都包含在IntentFilter中,才可以通过。即:Intent中的类别必须全部匹配中的,但是中多余的将不会导致匹配失败。
<data />首先IntentFilter可以有多个data,Intent最多能有1个。
<data>元素指定了可以接受的Intent传过来的数据URI和数据类型,当一个意图对象中的URI被用来和一个过滤器中的URI比较时,比较的是URI的各个组成部分。IntentFilter和Intent中的data必须完全匹配才能通过,也适用于通配符。
-
Activity中代码
- 打开网页
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.mi.com")); startActivity(intent);- 发送邮件
Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"***.com"}); intent.putExtra(Intent.EXTRA_SUBJECT, "Subject"); intent.putExtra(Intent.EXTRA_TEXT, "Body of the email"); startActivity(intent);- 查看地图位置
Uri locationUri = Uri.parse("geo:0,0?q=latitude,longitude(label)"); Intent intent = new Intent(Intent.ACTION_VIEW, locationUri); startActivity(intent);- 拨打电话
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:+123456789")); startActivity(intent);- 发送文本消息
Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:" + Uri.encode("12345"))); intent.putExtra("sms_body", "Hello, how are you?"); startActivity(intent);- 启动自定义组件
Intent intent = new Intent("com.example.***"); startActivity(intent);
-
三、向下一个Activity传递数据
1. 使用putExtra()
核心:发送方使用putExtra();接收方使用getIntent().getExtra()
//发送方在布局文件中添加Button,设置监听
@Override
public void onClick(View v) {
String message = "消息发送过去啦!";
Intent intent = new Intent(this, ReceiveActivity.class);
intent.putExtra("key", message);
startActivity(intent);
}
//接收方在布局文件中添加TextView,在onCreate()方法中填充内容
Intent intent = getIntent();
String message = intent.getStringExtra("key");
TextView tv_receive = findViewById(R.id.tv_receive);
tv_receive.setText(message);
2. 使用Bundle
采用键值对的方式,可以方便的传多个数据项,还提供了不同数据类型的方法
//发送方
@Override
public void onClick(View v) {
String message1 = "消息1";
String message2 = "消息2";
Intent intent = new Intent(this, ReceiveActivity.class);
Bundle bundle = new Bundle();
bundle.putString("key1", message1);
bundle.putString("key2", message2);
intent.putExtras(bundle);
startActivity(intent);
}
//接收方
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
if (bundle != null){
String message1 = bundle.getString("key1");
String message2 = bundle.getString("key2");
TextView tv_receive = findViewById(R.id.tv_receive);
tv_receive.setText("接收消息1:"+message1 +"接收消息2:"+ message2);
}
四、向上一个Activity传递数据
使用ActivityResultLauncher
//发送端
public class SendActivity extends AppCompatActivity implements View.OnClickListener {
private TextView resultTextView;
private final ActivityResultLauncher<Intent> activityLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result ->{
if (result.getResultCode() == RESULT_OK){
Intent data = result.getData();
if (data != null){
String responseMessage = data.getStringExtra("response_message");
resultTextView.setText("从B返回的数据:" + responseMessage);
}
}
}
);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_send);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
resultTextView = findViewById(R.id.tv_back_message);
findViewById(R.id.btn_send).setOnClickListener(this);
}
@Override
public void onClick(View v) {
//发消息
Intent intent = new Intent(this, ReceiveActivity.class);
intent.putExtra("key", "你好,我是send端,今天天气如何?");
activityLauncher.launch(intent);
}
}
//接收端
public class ReceiveActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_receive);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
//接收来自发送端的数据
TextView tv_receive = findViewById(R.id.tv_receive);
Bundle bundle = getIntent().getExtras();
String str = bundle.getString("key");
tv_receive.setText(str);
findViewById(R.id.btn_back_message).setOnClickListener(this);
}
@Override
public void onClick(View v) {
//发送数据
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putString("response_message", "你好啊,今天天气很好");
intent.putExtras(bundle);
setResult(RESULT_OK, intent);
finish();
}
}
本文的图片和部分文字来源网络,如需添加引用联系我即可,立马添加