【安卓基础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)

相关推荐
开心呆哥1 分钟前
【如何使用 ADB 脚本批量停止 Android 设备上的所有应用】
android·adb
CYRUS STUDIO1 小时前
ARM64汇编寻址、汇编指令、指令编码方式
android·汇编·arm开发·arm·arm64
weixin_449310842 小时前
高效集成:聚水潭采购数据同步到MySQL
android·数据库·mysql
Zender Han2 小时前
Flutter自定义矩形进度条实现详解
android·flutter·ios
白乐天_n4 小时前
adb:Android调试桥
android·adb
姑苏风8 小时前
《Kotlin实战》-附录
android·开发语言·kotlin
数据猎手小k11 小时前
AndroidLab:一个系统化的Android代理框架,包含操作环境和可复现的基准测试,支持大型语言模型和多模态模型。
android·人工智能·机器学习·语言模型
你的小1012 小时前
JavaWeb项目-----博客系统
android
风和先行12 小时前
adb 命令查看设备存储占用情况
android·adb
AaVictory.13 小时前
Android 开发 Java中 list实现 按照时间格式 yyyy-MM-dd HH:mm 顺序
android·java·list