【安卓基础4】Activity(二)

🏆作者简介:|康有为| ,大四在读,目前在小米安卓实习,毕业入职

🏆安卓学习资料推荐:

视频:b站搜动脑学院 视频链接 (他们的视频后面一部分没再更新,看看前面也挺好的)

书籍:《第一行代码》(第3版) by 郭霖 (z-lib.org)

思维导图: https://www.processon.com/view/link/62427cb2e0b34d0730e20e00(来自动脑学院)

🏆持续学习安卓知识中,共勉,我的【安卓】专栏中还有其他文章,持续更新中,欢迎关注

目录

一、Activity四大启动模式

任务栈

[默认启动模式 Standard](#默认启动模式 Standard)

[栈顶复用模式 SingleTop](#栈顶复用模式 SingleTop)

[栈内复用模式 SingleTask](#栈内复用模式 SingleTask)

[单实例模式 SingleInstance](#单实例模式 SingleInstance)

组合示例

启动模式的一般使用场景

启动模式设置方法

[1. 清单文件Manifest](#1. 清单文件Manifest)

[2. 动态设置](#2. 动态设置)

二、在活动之间传递消息

Intent

Intent是什么?

Intent的组成部分

显示Intent

隐式Intent

启动内部Activity

主要特征:

用法示例:

向下一个Activity传递数据

putExtra()传字符串

[使用 Bundle](#使用 Bundle)

上一个Activity返回数据

[使用startActivityForResult (Android11开始 不推荐)](#使用startActivityForResult (Android11开始 不推荐))

使用ActivityResultContract

三、为活动补充附加信息

利用资源文件配置字符串

利用元数据传递配置信息

给应用页面注册快捷方式


一、 Activity 四大启动模式

任务栈

在分别描述四种启动模式的特性前,需先引出一个概念:任务栈(也可以叫返回栈),它是一种先进后出的数据结构。

每个Activity都依附着任务栈运行,系统在创建Activity前会先创建一个ActivityRecord对象,用于映射该Activity,并将ActivityRecord对象压入任务栈中并处于栈顶,然后再通过ActivityRecord对象生成Activity实例。每当我们按下Back键或调用finish()方法去销毁一个Activity时,处于栈顶的Activity就会出栈,前一个入栈的Activity就会重新处于栈顶的位置。系统总会显示处于栈顶的Activity给用户。

一部正在运行app的安卓手机中,会有一个前台任务栈和0个或多个后台任务栈。当前在手机上运行的窗口,会有一个前台的任务栈,而处于后台的任务列表,每一个都对应着一个后台任务栈。当用户将后台应用重新切换至前台时,也伴随着将当前运行的前台任务栈移至后台,将系统下一秒想要运行的后台任务栈切换至前台运行的过程。

可以通过配置的方式指定Activity想要依附的任务栈:

XML 复制代码
<activity android:name=".MainActivity"
        android:taskAffinity="com.jamgu.test">
</activity>

通过在AndroidManifest.xml文件中设置,给MainActivity设置想要的任务栈是名为"com.jamgu.test"的任务栈。如果不设置, Activity 默认所需任务栈的名字为程序的包名,即默认会将MainActivity压入与程序包名相同的任务栈。

某App先后打开两个活动,此时活动栈的变动情况如下图所示。

依次结束已打开的两个活动,此时活动栈的变动情况如下图所示。

  1. Standard :标准模式
  2. SingleTop :栈顶复用模式
  3. SingleTask :栈内复用模式
  4. SingleInstance :单实例模式

默认启动模式 Standard

该模式可以被设定,不在manifest设定时候,Activity 的默认模式就是standard。在该模式下,启动的Activity会依照启动顺序被依次压入Task栈中,按返回的就出栈:

栈顶复用模式 SingleTop

在该模式下,如果栈顶Activity为我们要新建的Activity(目标Activity),那么就不会重复创建新的Activity。

应用场景

适合开启渠道多、多应用开启调用的Activity,通过这种设置可以避免已经创建过的 Activity 被重复创建,多数通过动态设置使用。

栈内复用模式 SingleTask

与singleTop模式相似,只不过 singleTop模式是只是针对栈顶的元素,而singleTask模式下,如果task栈内存在目标Activity实例,则将task内的对应Activity实例之上的所有Activity 弹出栈,并将对应Activity置于栈顶,获得焦点。

应用场景

程序主界面 : 我们肯定不希望主界面被创建多次,而且在主界面退出的时候退出整个App是最好的效果。

耗费系统资源的 Activity: 对于那些及其耗费系统资源的Activity,我们可以考虑将其设为singleTask模式,减少资源耗费。(视频 很耗费资源)

单实例模式 SingleInstance

也可以说"全局唯一模式"

在该模式下,我们会为目标Activity创建一个新的Task栈,将目标Activity放入新的Task,并让目标Activity获得焦点。新的Task有且只有这一个Activity实例。―如果已经创建过目标Activity 实例,则不会创建新的Task,而是将以前创建过的Activity唤醒。

组合示例

看一个示例,Activity3设置为singleInstance,Activity1和Activity2默认(standard)。

下图程序流程中,黄色的代表Backround(后台)的Task,蓝色的代表Foreground(前台) 的Task。

返回时会先把Foreground的Task 中的Activity 弹出,直到Task销毁,然后才将Background的Task 唤到前台,所以最后将Activity3销毁之后,会直接退出应用。

启动模式的一般使用场景

|----------------------|--------------------------------------------------------------------------------------|
| standard 标准模式 | 默认的启动模式,适用于应用的大多数场景。 |
| singleTop 栈顶复用模式 | 为了满足特定功能,不需要重复创建显示的页面 登录页面、WXPayEntryActivity、WXEntryActivity 、推送通知栏 |
| singleTask 栈内复用模式 | 适用于重复创建比较耗性能的页面 主页面(Fragment的containerActivity)、WebView页面、扫一扫页面、电商中:购物界面,确认订单界面,付款界面 |
| singleInstance 单实例模式 | 这个启动模式我们一般用不到,系统级应用使用该模式比较多。 系统Launcher(启动器)、锁屏键、来电显示等系统应用 |

启动模式设置方法

实际开发中需要将 xml文件的设置方法 和 动态的设置方法结合起来用

1. 清单文件 Manifest

Manifest文件中正确设置 android:launchMode 属性

standard(默认值):无需特殊设置,因为它是默认值。

singleTop、singleTask、singleInstance:修改launchMode 的值

XML 复制代码
<activity
    android:name=".YourActivity"
    android:launchMode="singleTop">
</activity>

2. 动态设置

除了在清单文件中设置,还能动态的设置。

启动标志的取值说明如下:

  • Intent.FLAG_ACTIVITY_NEW_TASK:开辟一个新的任务栈
  • Intent.FLAG_ACTIVITY_SINGLE_TOP:当栈顶为待跳转的活动实例之时,则重用栈顶的实例
  • Intent.FLAG_ACTIVITY_CLEAR_TOP:当栈中存在待跳转的活动实例时,则重新创建一个新实例,

并清除原实例上方的所有实例

  • Intent.FLAG_ACTIVITY_NO_HISTORY:栈中不保存新启动的活动实例
  • Intent.FLAG_ACTIVITY_CLEAR_TASK:跳转到新页面时,栈中的原有实例都被清空

在Java代码中,你可以使用 Intent 对象来动态设置Activity的启动模式。在创建Intent的时候,可以通过 setFlags() 方法设置标志位来达到设置启动模式的效果。以下是一些示例代码:

standard模式:

java 复制代码
Intent intent = new Intent(this, YourActivity.class);
startActivity(intent);

singleTop模式:

java 复制代码
Intent intent = new Intent(this, YourActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);

singleTask模式:

java 复制代码
Intent intent = new Intent(this, YourActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);

singleInstance模式:

java 复制代码
Intent intent = new Intent(this, YourActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);

在上述代码中,Intent.FLAG_ACTIVITY_SINGLE_TOP 表示 singleTop 模式,Intent.FLAG_ACTIVITY_NEW_TASK 和 Intent.FLAG_ACTIVITY_CLEAR_TASK 组合表示 singleTask 模式。请根据需要选择适当的标志位。

二、在活动之间传递消息

Intent

Intent 是什么?

翻译:意图,Intent是各个组件之间信息沟通的桥梁,它用于Android各组件之间的通信,主要完成下列工作:

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

Intent 的组成部分

显示 Intent

显式Intent,直接指定来源活动与目标活动,属于精确匹配。

Intent有多个构造函数的重载,Intent(ContextpackageContext,Class<?>cls)是其中一个。

这个构造函数接收两个参数,第一个参数Context要求提供一个启动活动的上下文,第二个参数Class则是指定想要启动的目标活动,通过这个构造函数就可以构建出Intent的"意图"。

在构建 Intent 时,第一个参数可以选择: this 或 ActivityName.this 或getApplicationContext()

使用 getApplicationContext() 表明你希望使用应用程序的全局上下文来启动 ThirdActivity。这在一些特定场景下可能是合适的,但在其他情况下,你可能需要使用 this 或 ActivityName.this 作为上下文,具体取决于你的需求和上下文的生命周期。

它有三种构建方式:

1.在Intent的构造函数中指定。

java 复制代码
Intent intent = new Intent(this, ActNextActivity.class);
startActivity(intent);//启动目标活动

2.调用意图对象的setClass方法指定。

java 复制代码
Intent intent = new Intent;
intent.setClass(this,ActNextActivity.class);
startActivity(intent);//启动目标活动

3.调用意图对象的setComponent方法指定。

java 复制代码
Intent intent = new Intent();
ComponentName component = new ComponentName(this,ActNextActivity.class);
intent.setComponent(component);
startActivity(intent);//启动目标活动

隐式 Intent

相比于显式Intent,隐式Intent则含蓄了许多,它并不明确指出我们想要启动哪那一个活动,而是指定了一系列更为抽象的action和category等信息,然后交由系统去分析这个Intent,并帮我们找出合适的活动去启动。

请注意,使用隐式Intent时,系统会寻找匹配给定动作和数据的组件。如果有多个组件匹配,系统将提供一个选择框,让用户选择要使用的应用程序。因此,隐式Intent提供了更大的灵活性,但也需要谨慎使用以确保得到预期的结果。

启动内部 Activity

通过在标签下配置intent-filter:的内容,可以指定当前活动能够响应的action和category,打开AndroidManifest.xml,添加如下代码:

使用intent的另一个构造函数,直接将action的字符串传进去。

java 复制代码
Intent intent = new Intent("android.intent.action.Button2");
//运行intent对象的实例
startActivity(intent);

启动外部 Activity

使用隐式Intent,我们不仅可以启动自己程序内的活动,还可以启动其他程序的活动,这使得Android多个应用程序之间的功能共享成为了可能。比如说你的应用程序中需要展示一个网页,这时你没有必要自己去实现一个浏览器(事实上也不太可能),而是只需要调用系统的浏览器来打开这个网页就行了。

java 复制代码
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse("http://www.baidu.com"));
        startActivity(intent);
    }
});

这里我们首先指定了Intent的action是Intent.ACTION VIEW,这是一个Android系统内置的动作,其常量值为android.intent.action.VIEW。然后通过Uri.parse()方法,将一个地址字符串解析成一个Uri对象,再调用Intent的setData()方法将这个Uri对象传递进去。

主要特征:

  1. Action(动作): Intent 的动作是指要执行的操作,例如 ACTION_VIEW 用于查看数据,ACTION_SEND 用于发送数据等。
  2. Data(数据): 通过setData()或setType()方法设置,指定要处理的数据的URI或MIME类型。
  3. Category(类别): 可选的,用于限定组件的类型,例如 Intent.CATEGORY_BROWSABLE 表示可以通过浏览器打开。

用法示例:

1.打开网页:

java 复制代码
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.example.com"));
startActivity(intent);

2.发送邮件:

java 复制代码
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"recipient@example.com"});
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
intent.putExtra(Intent.EXTRA_TEXT, "Body of the email");
startActivity(intent);

3.查看地图位置

java 复制代码
Uri locationUri = Uri.parse("geo:0,0?q=latitude,longitude(label)");
Intent intent = new Intent(Intent.ACTION_VIEW, locationUri);
startActivity(intent);

4.拨打电话

java 复制代码
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:+123456789"));
startActivity(intent);

5.发送文本消息

java 复制代码
Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:" + Uri.encode("12345")));
intent.putExtra("sms_body", "Hello, how are you?");
startActivity(intent);

6.启动自定义组件(也就是上面讲的 启动内部Activity)

java 复制代码
Intent intent = new Intent("com.example.ACTION_NAME");
startActivity(intent);

向下一个 Activity 传递数据

就是从A 跳到 B时,A发送给B的数据。上一个Activity指的就是A,下一个Activity指的就是B。

核心:

  • 使用Intent来传输,使用putExtra()方法将数据添加到Intent中。
  • 使用getIntent().getExtras() 获取数据

可以直接在putExtra() 方法里面传字符串,也可以使用 Bundle 。

putExtra() 传字符串

在发送方Activity中传递字符串:

java 复制代码
// 在发送方Activity中
String messageToSend = "你好,这是信息!";
Intent intent = new Intent(this, ReceiverActivity.class);
intent.putExtra("key", messageToSend);
startActivity(intent);

在接收方Activity中获取并显示字符串:

java 复制代码
// 在接收方Activity中的onCreate()方法或其他适当的地方
Intent receivedIntent = getIntent();
String receivedMessage = receivedIntent.getStringExtra("key");

// 然后,你可以将接收到的字符串显示在界面上,例如,使用TextView
TextView textView = findViewById(R.id.textView);
textView.setText(receivedMessage);

确保在接收方Activity的布局文件(例如activity_receiver.xml)中包含一个TextView,以便显示接收到的字符串:

XML 复制代码
<!-- activity_receiver.xml -->
<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="接收的信息会展示在这里" />

使用 Bundle

使用 Bundle 可以更方便地传递多个数据项,因为你可以在Bundle中存储多个键值对。此外,Bundle 还提供了不同的数据类型的方法,以满足不同类型的数据传递需求。

在发送方Activity中传递字符串:

java 复制代码
// 在发送方Activity中
String messageToSend1 = "你好,这是信息1!";
String messageToSend2 = "你好,这是信息2!";
Intent intent = new Intent(this, ReceiverActivity.class);

Bundle bundle = new Bundle();
bundle.putString("key1", messageToSend1);
bundle.putString("key2", messageToSend2);
intent.putExtras(bundle);
startActivity(intent);

在接收方Activity中获取并显示字符串:

java 复制代码
// 在接收方Activity中的onCreate()方法或其他适当的地方
Intent intent = getIntent();
Bundle bundle = intent.getExtras();

if (bundle != null) {
    String message1 = bundle.getString("key1");
    String message2 = bundle.getString("key2");
    // 然后,你可以将接收到的字符串显示在界面上,例如,使用TextView
    TextView textView = findViewById(R.id.textView);
    textView.setText("接收到消息1: " + message1 +" 接收到消息2: "+ message2);
}

同样,确保在接收方Activity的布局文件中包含一个TextView,以便显示接收到的字符串。

XML 复制代码
<!-- activity_receiver.xml -->
<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="接收的信息会展示在这里" />

上一个 Activity 返回数据

意思就是,从A跳到B,A发送给B数据,B处理完这些数据后,B再返回给A数据。

核心:

  • 从A 发消息并跳转到 B 就是用 startActivity(intent);
  • 从A 发消息并跳转到 B,并接收B的返回的消息,就是用方法 startActivityForResult(intent, 1);
  • 从 Android 11 开始,Google 不再推荐使用 startActivityForResult() 方法,而是建议使用 ActivityResultContract API 来更灵活地进行 Activity 之间的数据传递。

示例:

A中有个按钮,点击就跳转到B,并给B发消息。B中有个按钮,接受到消息后,点击按钮就返回给A消息。

使用 startActivityForResult Android11 开始 不推荐)

在Activity A中发送消息:

java 复制代码
public class ActivityA extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);

        Button myButton = findViewById(R.id.activity_a_button);
        myButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 处理按钮点击事件的代码
                Intent intent = new Intent(ActivityA.this, ActivityB.class);
                intent.putExtra("key", "B你好,我是A,你最近过的怎么样?");
                startActivityForResult(intent, 1); // 1是请求码,可以是任何整数,用于标识请求
            }
        });
    }
    
    //接收B返回过来的数据,并展示
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        TextView resultTextView = findViewById(R.id.activity_a_textView) ;
        if (requestCode == 1) { // 判断请求码是否是你发送请求时设定的
            if (resultCode == RESULT_OK) { // 判断B返回的结果是否成功
                String returnedData = data.getStringExtra("response_message");
                // 在这里处理从B返回的数据
                resultTextView.setText("B返回:" + returnedData);
            }
        }
    }
}

activity_a.xml 中布局

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ActivityA"
    android:orientation="vertical">

    <TextView
        android:id="@+id/activity_a_textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="A接收到B返回的消息将会显示在这里" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <Button
            android:id="@+id/activity_a_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="跳转到B" />

    </LinearLayout>


</LinearLayout>

在Activity B中返回消息:

java 复制代码
public class ActivityB extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_b);

        TextView textView = findViewById(R.id.activity_b_textView);
        //接收A发过来的消息,并显示出来
        Bundle bundle = getIntent().getExtras();
        String str = bundle.getString("key");
        textView.setText("接收到A的消息: " + str);

        Button myButton = findViewById(R.id.activity_b_button);
        myButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 点击按钮,返回给A消息
                Intent intent = new Intent();
                Bundle bundle = new Bundle();
                bundle.putString("response_message","Hi,A,我最近很好,你呢");
                intent.putExtras(bundle);
                setResult(RESULT_OK,intent);
                finish();
            }
        });

    }
}

activity_b.xml 中布局

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ActivityB"
    android:orientation="vertical">
    <TextView
        android:id="@+id/activity_b_textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="B接收到A的消息将会显示在这里" />
    <Button
        android:id="@+id/activity_b_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="返回消息" />
</LinearLayout>

使用 ActivityResultContract

只需要替换上面ActivityA的代码

java 复制代码
package com.example.chapter03;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;

public class ActivityA extends AppCompatActivity {

    private TextView resultTextView ;

    //接收B返回过来的数据,并展示
    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);
        setContentView(R.layout.activity_a);

        resultTextView = findViewById(R.id.activity_a_textView);
        //点击按钮,发送数据给B,并等待B传回数据
        Button goToBButton = findViewById(R.id.activity_a_button);
        goToBButton.setOnClickListener(v -> {
            Intent intent = new Intent(ActivityA.this, ActivityB.class);
            intent.putExtra("key", "B你好,我是A,你最近过的怎么样?");
            activityLauncher.launch(intent);
        });
    }
}

三、为活动补充附加信息

利用资源文件配置字符串

在 Android 中,你可以使用资源文件(如 res/values/strings.xml)来配置字符串,以便在 Activity 中引用这些字符串。这样的做法有助于代码的维护和国际化支持。以下是一些简单的步骤:

1.在 res/values/strings.xml 中定义字符串:

在 strings.xml 文件中,你可以定义应用中使用的所有字符串。例如:

XML 复制代码
<resources>
    <string name="app_name">MyApp</string>
    <string name="welcome_message">Welcome to my app!</string>
</resources>

2.在 Activity 中引用字符串:

在你的 Activity 中,你可以通过调用 getString(R.string.string_name) 来引用字符串。例如:

java 复制代码
public class MyActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        String welcomeMessage = getString(R.string.welcome_message);
        // 现在,welcomeMessage 变量包含 "Welcome to my app!"
    }
}

这种做法的好处在于,如果你决定在应用中更改欢迎消息,你只需要在 strings.xml 文件中进行修改,而不需要修改代码中的硬编码字符串。

配置文件中的代码是不需要编译的,而 java 代码是需要编译的

如果需要在 XML 布局文件中引用字符串,也可以使用 @string/string_name 语法。

XML 复制代码
<TextView
    android:id="@+id/welcomeTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/welcome_message" />

利用元数据传递配置信息

在 Android 中,你可以使用元数据(metadata)来传递配置信息。元数据是一种在 AndroidManifest.xml 文件中定义的键值对,可以在应用的组件(如 Activity、Service、BroadcastReceiver 等)中访问。以下是一些步骤,演示如何使用元数据传递配置信息:

1.在 AndroidManifest.xml 文件中定义元数据:

在 <application> 或 <activity> 或其他组件的标签中,可以使用 <meta-data> 元素定义键值对。

XML 复制代码
<application>
    <activity android:name=".MainActivity">
        <meta-data
            android:name="com.example.app.CONFIG_KEY"
            android:value="your_configuration_value" />
        <!-- 其他 activity 相关配置 -->
    </activity>
    <!-- 其他组件和配置 -->
</application>

在上述例子中,CONFIG_KEY 是元数据的键,your_configuration_value 是相应的值。

2.在 Activity 中读取元数据:

你可以在 Activity 中使用 getPackageManager().getApplicationInfo().metaData 获取应用的元数据,然后检索你定义的键值对。

java 复制代码
import android.content.pm.ApplicationInfo;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        try {
            ApplicationInfo appInfo = getPackageManager().getApplicationInfo(getPackageName(), android.content.pm.PackageManager.GET_META_DATA);
            String configValue = appInfo.metaData.getString("com.example.app.CONFIG_KEY");

            // 在这里使用配置值
            // ...

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

注意:在使用 getApplicationInfo() 方法时,需要处理 PackageManager.NameNotFoundException 异常。

这样,你就可以通过在 AndroidManifest.xml 文件中定义的元数据来传递配置信息。这种方法对于在应用启动时读取一些配置信息非常有用。如果需要在运行时动态更新配置信息,可能需要考虑其他的方案,比如使用 SharedPreferences 或其他配置管理方式。

给应用页面注册快捷方式

元数据不仅能传递简单的字符串参数,还能传送更复杂的资源数据,比如支付宝的快捷方式菜单。

  1. 在res下创建一个xml的文件夹
  2. 在xml文件夹里面创建一个shortcuts.xml文件
  3. 在清单文件AndroidMainfest.xml 的 主Activity标签里面定义快捷方式

元数据的meta-data标签除了前面说到的name属性和value属性,还拥有resource属性, 该属性可指定一个XML文件,表示元数据想要的复杂信息保存于XML数据之中。

利用元数据配置快捷菜单的步骤如下所示:

  • 在res/values/strings.xml添加各个菜单项名称的字符串配置
  • 创建res/xml/shortcuts.xml,在该文件中填入各组菜单项的快捷方式定义(每个菜单 对应哪个活动页面)。
  • 给activity节点注册元数据的快捷菜单配置

具体实现步骤请看视频讲解: 2022 最新 Android 基础教程,从开发入门到项目实战,看它就够了,更新中 P45

也可以看这篇博客:Android 长按APP图标弹出快捷方式(shortcuts)

相关推荐
sunnyday042638 分钟前
Spring Boot 项目中使用 Dynamic Datasource 实现多数据源管理
android·spring boot·后端
幽络源小助理2 小时前
下载安装AndroidStudio配置Gradle运行第一个kotlin程序
android·开发语言·kotlin
inBuilder低代码平台2 小时前
浅谈安卓Webview从初级到高级应用
android·java·webview
豌豆学姐2 小时前
Sora2 短剧视频创作中如何保持人物一致性?角色创建接口教程
android·java·aigc·php·音视频·uniapp
白熊小北极2 小时前
Android Jetpack Compose折叠屏感知与适配
android
HelloBan2 小时前
setHintTextColor不生效
android
洞窝技术5 小时前
从0到30+:智能家居配网协议融合的实战与思考
android
QING6185 小时前
SupervisorJob子协程异常处理机制 —— 新手指南
android·kotlin·android jetpack
毕设源码-朱学姐5 小时前
【开题答辩全过程】以 基于安卓的停车位管理系统与设计为例,包含答辩的问题和答案
android
PWRJOY6 小时前
解决Flutter构建安卓项目卡在Flutter: Running Gradle task ‘assembleDebug‘...:替换国内 Maven 镜像
android·flutter·maven