Android 之 intent内容解析

intent

intent中文名字叫做意图,是一个将要执行的动作的抽象的描述,简单来说就是穿的消息,由Intent协助完成各个组件之间的通讯。

既能在Activity之间沟通,又能在Activity与Service之间沟通,也能在Activity与Broadcast之间沟通。它主要完成下列3部分工作:

(1) 标明本次通信请求从哪里来、到哪里去、要怎么走。
(2) 发起方携带本次通信需要的数据内容,接收方从收到的意图中解析数据。
(3) 发起方若想判断接收方的处理结果,意图就要负责让接收方传回应答的数据内容。

intent 属性

Intent对象大致包括7大属性:Action(动作)、Data(数据)、Category(类别)、Type(数据类型)、Component(组件)、Extra(扩展信息)、Flag(标志位)。

元素名称设置方法说明与用途
ActionsetAction动作,它指定意图的动作行为
CategoryaddCategory类别,指定意图的操作类别
DatasetData即Uri,它指定动作要操作的数据路径
ComponentsetComponent组件,它指定意图的来源与目标
TypesetType数据类型,表示一个MIMEtypes的string
ExtrasputExtras扩展信息,它指定装载的包裹信息
FlagssetFlags标志位,它指定活动的启动标志

1. Action

一个字符串变量(action 字符串 随便写,一般是包名+action名,为了防止不同应用混淆),用来指定Intent要执行的动作类别。系统提供常见的action有:

Intent 类的系统动作常量名系统动作的常量值作用
ACTION_MAINandroid.intent.action.MAINApp启动时的入口
ACTION_VIEWandroid.intent.action.VIEW向用户显示数据
ACTION_SENDandroid.intent.action.SEND分享内容
ACTION_CALLandroid.intent.action.CALL直接拨号
ACITON_DIALandroid.intent.action.DIAL准备拨号
ACTION_SENDTOandroid.intent.action.SENDTO发送短信
ACTION_ANSWERandroid.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就知道了这个人在哪个小区哪个楼号。

注意:
  1. android.intent.category.DEFAULT 是一种默认的category ,在调用StartActivity()方法的时候会自动将category添加到Intent中。

  2. 匹配规则 : 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)启动本地应用
setClassintent.setClass(当前组件.this,目标组件.class)启动本地应用
setClassNameintent.setClassName(应用包名, 组件所在全包名)可以用于打开外部应用
setComponentintent.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);
            }
        });
    }
}

注意:

  1. 包名说的的android应用包名,是android应用的唯一标识。 在manifest package属性指定
  2. setClassName内部也是调用的setComponent。
  3. 打开外部应用时,如果两个应用在一个项目可以直接打开,否则,外部应用必须处于运行状态下,才可以,要不然系统找不到。

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对各类型数据的读写方法说明如下:

数据类型读方法写方法
整型数getIntputInt
浮点数getFloatputFloat
双精度数getDoubleputDouble
布尔值getBooleanputBoolean
字符串getStringputString
字符串数组getStringArrayputStringArray
字符串列表getStringArrayListputStringArrayList
可序列化结构getSerializableputSerializable

示例代码:

存数据:

// 创建一个意图对象,准备跳到指定的活动页面
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将被从任务栈中移除

参考链接

  1. 如何通过浏览器链接启动本地 Activity
  2. Action、Category、Data以及匹配规则
  3. 官方:intent和intent过滤器
  4. Intent解析
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值