intent
intent中文名字叫做意图,是一个将要执行的动作的抽象的描述,简单来说就是穿的消息,由Intent协助完成各个组件之间的通讯。
既能在Activity之间沟通,又能在Activity与Service之间沟通,也能在Activity与Broadcast之间沟通。它主要完成下列3部分工作:
(1) 标明本次通信请求从哪里来、到哪里去、要怎么走。
(2) 发起方携带本次通信需要的数据内容,接收方从收到的意图中解析数据。
(3) 发起方若想判断接收方的处理结果,意图就要负责让接收方传回应答的数据内容。
intent 属性
Intent对象大致包括7大属性:Action(动作)、Data(数据)、Category(类别)、Type(数据类型)、Component(组件)、Extra(扩展信息)、Flag(标志位)。
元素名称 |
设置方法 |
说明与用途 |
Action |
setAction |
动作,它指定意图的动作行为 |
Category |
addCategory |
类别,指定意图的操作类别 |
Data |
setData |
即Uri,它指定动作要操作的数据路径 |
Component |
setComponent |
组件,它指定意图的来源与目标 |
Type |
setType |
数据类型,表示一个MIMEtypes的string |
Extras |
putExtras |
扩展信息,它指定装载的包裹信息 |
Flags |
setFlags |
标志位,它指定活动的启动标志 |
1. Action
一个字符串变量(action 字符串 随便写,一般是包名+action名,为了防止不同应用混淆),用来指定Intent要执行的动作类别。系统提供常见的action有:
Intent 类的系统动作常量名 |
系统动作的常量值 |
作用 |
ACTION_MAIN |
android.intent.action.MAIN |
App启动时的入口 |
ACTION_VIEW |
android.intent.action.VIEW |
向用户显示数据 |
ACTION_SEND |
android.intent.action.SEND |
分享内容 |
ACTION_CALL |
android.intent.action.CALL |
直接拨号 |
ACITON_DIAL |
android.intent.action.DIAL |
准备拨号 |
ACTION_SENDTO |
android.intent.action.SENDTO |
发送短信 |
ACTION_ANSWER |
android.intent.action.ANSWER |
接听电话 |
动作名称既可以通过setAction方法指定,也可以通过构造函数Intent(String action)直接生成意图对象。
当然,由于动作是模糊匹配,因此有时需要更详细的路径, 比如仅知道某人住在天通苑小区,并不能直接找到他家,还得说明他住在天通苑的哪一期、哪栋楼、哪一层、哪一个单元。
Uri和Category便是这样的路径与门类信息,Uri数据可通过构造函数Intent(String action, Uri uri)在生成对象时一起指定,也可通过setData方法指定
(setData这个名字有歧义,实际相当于setUri) Category可通过addCategory方法指定,之所以用add而不用set方法,是因为一个意图允许设置多个Category,方便一起过滤。
<intent-filter>
<action android:name="com.example.demo.hhhh" /> // 自定义的action
<action android:name="android.intent.action.VIEW" /> // 系统提供的action
...
</intent-filter>
匹配规则: Action匹配只要有一个与Intent中携带Action相同即可
可以指定一个或者多个action ,Intent 中指定的action 必须与过滤器中列出的某一aciton匹配 即可通过。
intent.setAction 是set方法,所以intent只能指定一个Action请求,多个setAction的话,依最后的set为准。
2.Category
一个包含Intent额外信息的字符串(可以自定义,系统也有提供),用来表示action的类别。常用的category如下:
类型 |
作用 |
CATEGORY_DEFAULT |
默认的category |
CATEGORY_LAUNCHER |
决定应用程序是否显示在程序列表里 |
CATEGORY_BROWSABLE |
以通过浏览器打开的类别 |
我们通过action可以定位到一个组件,但是我还想细分。比方说action是一个小区,我通过action找到了这个人在对应的小区,现在我还想知道这个人他住在小区的哪一栋楼,category相当于楼号。action+category就知道了这个人在哪个小区哪个楼号。
注意:
-
android.intent.category.DEFAULT 是一种默认的category ,在调用StartActivity()方法的时候会自动将category添加到Intent中。
-
匹配规则 : intent filter中可以声明多个category。intent filter声明的category,Intent中可以不全部指定,但是Intent指定的类别,Intent Filter必须全部匹配。也就是说Intent 指定的类别 是Intent filter声明类别的子集。
这也说明了所以当我们执行StartActivity方法,打来另一个组件的时候,由于intent 会默认指定 android.intent.category.DEFAULT ,所以该组件的Intent filter一定要添加上这个默认类别。即 :如果该activity想要通过隐式intent方式激活,那么不能没有任何category设置,至少包含一个android.intent.category.DEFAULT
3.Data
名字起的有点歧义,其实就是Uri,接受一个Uri对象,通常都是以字符串的形式传入到Uri.parse()方法中解析产生,更精确的指定当前Intent能够响应什么类型的数据。
前面我们说Action是小区,category是楼栋,Data就相当于是门牌号了。<data>标签主要配置一下内容。
类型 |
说明 |
android:scheme |
用于指定数据的协议部分 如http: |
android:host |
用于指定数据的主机名部分 |
android:port |
用于指定数据的端口部分 |
android:path |
主机名和端口之后的部分。 |
android:mimeType |
指定可以处理的数据类型,允许使用通配符的方式指定 |
只有data标签中指定的内容和Intent中携带的Data完全一致时,当前活动才能响应该Intent。
4. Component
要启动的组件名称
package com.example.otherapp.test;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.os.Bundle;
import android.util.Log;
import com.example.otherapp.R;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ComponentName component = getIntent().getComponent();
String packageName = component.getPackageName(); // 返回android应用包名,而不是组件所在包名 com.example.otherapp
String className = component.getClassName(); //返回组件所在全包名 com.example.otherapp.test.MainActivity
Log.d(TAG, "onCreate: "+packageName);
Log.d(TAG, "onCreate: "+className);
}
}
类型 |
使用 |
说明 |
构造函数 |
intent(当前组件.this,目标组件.class) |
启动本地应用 |
setClass |
intent.setClass(当前组件.this,目标组件.class) |
启动本地应用 |
setClassName |
intent.setClassName(应用包名, 组件所在全包名) |
可以用于打开外部应用 |
setComponent |
intent.setComponent(new ComponentName(应用包名,组件所在全包名); |
可以用于打开外部应用 |
public class IntentActivityDemo1 extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.intent_activty_demo1);
findViewById(R.id.intent_btn1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 构造函数
Intent intent = new Intent(IntentActivityDemo1.this,IntentActivityDemo3.class);
// setClass
intent.setClass(IntentActivityDemo1.this,IntentActivityDemo3.class);
// setClassName
intent.setClassName("com.example.otherApp","com.example.otherApp.MainActivity");
// setComponent
intent.setComponent(new ComponentName("com.example.otherApp","com.example.otherApp.MainActivity"));
startActivity(intent);
}
});
}
}
注意:
- 包名说的的android应用包名,是android应用的唯一标识。 在manifest package属性指定
- setClassName内部也是调用的setComponent。
- 打开外部应用时,如果两个应用在一个项目可以直接打开,否则,外部应用必须处于运行状态下,才可以,要不然系统找不到。
5. Type
指的是 要执行action的目标Activity所能处理的MIME数据类型 比方说指定intent.setType(“image/*”), 会显示所有支持图片类型的应用。
Intent的Type属性显式指定Intent的数据类型(MIME)。一般Intent的数据类型能够根据数据本身进行判定,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导
注意:
在Intent对象中,Data项和Type项很多时候是互斥使用的。当调用Intent.setType时,之前设定的Data信息就会被清空;反过来,调用Intent.setData时,Type信息也会被清除。可以使用setDataAndType(Uri uri, String type)方法。
6. Extras
intent携带的参数信息都是放在Extras中的。。Intent重载了很多种putExtra方法传递各种类型的参数,包括整型、双精度型、字符串等基本数据类型,甚至Serializable、Parcelable这样的序列化结构。
putExtra方法接受两个参数,第一个参数是键,用于后面从Intent中取值,第二个参数才是真正要传递的数据。
存数据:
Intent intent = new Intent(IntentActivityDemo1.this,IntentActivityDemo3.class);
intent.putExtra("Integer",1);
intent.putExtra("String","hhhh");
intent.putExtra("boolean",true);
...
startActivity(intent);
取数据:
Intent intent = getIntent();
int num = intent.getIntExtra("Intenger");
String str = intent.getStringExtra("String");
Boolean boolean = intent.getBooleanExtar("boolean");
...
只是调用putExtra方法显然不好管理,像送快递一样大小包裹随便扔,不但找起来不方便,丢了也难以知道。所以Android引入了Bundle概念,可以把Bundle理解为超市的寄包柜或快递收件柜,大小包裹由Bundle统一存取,方便又安全。
Bundle内部用于存放消息的数据结构是Map映射,既可添加或删除元素,还可判断素是否存在。开发者若要把Bundle数据全部打包好,只需调用一次意图对象的putExtra方法;若要把Bundle数据全部取出来**,也只需调用一次意图对象的getExtras方法**
Bundle对各类型数据的读写方法说明如下:
数据类型 |
读方法 |
写方法 |
整型数 |
getInt |
putInt |
浮点数 |
getFloat |
putFloat |
双精度数 |
getDouble |
putDouble |
布尔值 |
getBoolean |
putBoolean |
字符串 |
getString |
putString |
字符串数组 |
getStringArray |
putStringArray |
字符串列表 |
getStringArrayList |
putStringArrayList |
可序列化结构 |
getSerializable |
putSerializable |
示例代码:
存数据:
// 创建一个意图对象,准备跳到指定的活动页面
Intent intent = new Intent(this, ActReceiveActivity.class);
Bundle bundle = new Bundle(); // 创建一个新包裹
// 往包裹存入名为request_time的字符串
bundle.putString("request_time", DateUtil.getNowTime());
// 往包裹存入名为request_content的字符串
bundle.putString("request_content", tv_send.getText().toString());
intent.putExtras(bundle); // 把快递包裹塞给意图
startActivity(intent); // 跳转到意图指定的活动页面
取数据:
// 从上一个页面传来的意图中获取快递包裹
Bundle bundle = getIntent().getExtras();
// 从包裹中取出名为request_time的字符串
String request_time = bundle.getString("request_time");
// 从包裹中取出名为request_content的字符串
String request_content = bundle.getString("request_content");
7. Flags
Intent的运行模式,与activity的启动模式相辅相成。用来指示系统如何启动一个Activity,可以通过setFlags()或者addFlags()可以把标签flag用在Intent中。
类型 |
作用 |
FLAG_ACTIVITY_CLEAR_TOP |
相当于SingleTask |
FLAGE_ACTIVITY_SINGLE_TOP |
相当于SingleTop |
FLAG_ACTIVITY_NEW_TASK |
类似于SingleInstance |
FLAG_ACTIVITY_NO_HISTORY |
当离开该Activity后,该Activity将被从任务栈中移除 |
参考链接
- 如何通过浏览器链接启动本地 Activity
- Action、Category、Data以及匹配规则
- 官方:intent和intent过滤器
- Intent解析