【安卓基础重点知识2】Intent

0 阅读6分钟

一、定义

1. Intent是什么?

Intent是一个信息传递对象,可以用来启动组件(Activity、Service、Broadcast Reciver)以及进行组件之间的数据传递,主要完成下列工作:

  • 标明本次通信从哪里来、到哪里去、要怎么走

  • 发起方携带本次通信需要的数据内容,接收方从收到的Intent中解析数据

  • 发起方若想判断接收方的处理结果,Intent就要负责让接收方传回应答数据内容

2. 组成部分

元素名称设置方法说明与用途
ComponentsetComponent()组件,设置组件名称,显示 Intent 必选参数
ActionsetAction()动作,指定动作行为,例如查看或者选取,隐式 Intent 必选参数
DatasetData()引用待操作数据或者该数据的MIME类型的URI对象,提供的数据类型通常由Intent的操作决定,用于隐式Inent
CategoryaddCategory()类别,指定意图的操作类别,用于隐式Intent,一般不需要设置
TypesetType()数据类型,表示数据的MIME类型
ExtrasputExtra()、putExtras()扩展信息,携带完成请求操作所需要的附加信息的键值对
FlagssetFlags()标志位,指定Intent的运行模式
  • 补充:

MIME是描述消息内容类型的标准,用来表示文档、文件或字节流的性质和格式。MIME消息能包含文本、图像、音频、视频以及其他应用程序专用的数据

通用结构:type/subtype

常见类型:

  • 超文本标记语言文本 .htmltext/html

  • 普通文本 .txttext/plain

  • RTF 文本 .rtfapplication/rtf

  • GIF 图形 .gifimage/gif

  • JPEG 图形 .jpeg、.jpgimage/jpeg

  • au 声音文件 .auaudio/basic

  • MIDI 音乐文件 mid、.midiaudio/midi、audio/x-midi

  • RealAudio 音乐文件 .ra、.ramaudio/x-pn-realaudio

  • MPEG 文件 .mpg、.mpegvideo/mpeg

  • AVI 文件 .avivideo/x-msvideo

  • GZIP 文件 .gzapplication/x-gzip

  • TAR 文件 .tarapplication/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满足条件,那么系统会弹出一个对话框,由用户决定启动哪个组件。

流程:

  1. 首先Activity A利用传入的Intent调用startActivity();

  2. 系统会根据该Intent的条件搜索Android系统中所有匹配的组件;

  3. 若找到了匹配intent的intent-filters所属的组件(Activity B),则启动该组件,并回调onCreate()方法,同时将Intent传递过去。

image.png

  • 用法示例

    在使用时候,通常在配置文件AndroidManifest.xml中配置Activity的过滤规则,然后在Activity中配置Intent

    1. AndroidMainfest.xml中的代码

    2. 标签说明

      <action />

      首先IntentFilter中可以有多个actionIntent最多能有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中可以有多个categoryIntent也可以有多个

      (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可以有多个dataIntent最多能有1个。

      <data>元素指定了可以接受的Intent传过来的数据URI和数据类型,当一个意图对象中的URI被用来和一个过滤器中的URI比较时,比较的是URI的各个组成部分。

      IntentFilter和Intent中的data必须完全匹配才能通过,也适用于通配符。

    3. 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();
    }
}

本文的图片和部分文字来源网络,如需添加引用联系我即可,立马添加