🏆作者简介:|康有为| ,大四在读,目前在小米安卓实习,毕业入职
🏆安卓学习资料推荐:
视频:b站搜动脑学院 视频链接 (他们的视频后面一部分没再更新,看看前面也挺好的)
书籍:《第一行代码》(第3版) by 郭霖 (z-lib.org)
思维导图: https://www.processon.com/view/link/62427cb2e0b34d0730e20e00(来自动脑学院)
🏆持续学习安卓知识中,共勉,我的【安卓】专栏中还有其他文章,持续更新中,欢迎关注
目录
[默认启动模式 Standard](#默认启动模式 Standard)
[栈顶复用模式 SingleTop](#栈顶复用模式 SingleTop)
[栈内复用模式 SingleTask](#栈内复用模式 SingleTask)
[单实例模式 SingleInstance](#单实例模式 SingleInstance)
[1. 清单文件Manifest](#1. 清单文件Manifest)
[2. 动态设置](#2. 动态设置)
[使用 Bundle](#使用 Bundle)
[使用startActivityForResult (Android11开始 不推荐)](#使用startActivityForResult (Android11开始 不推荐))
一、 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先后打开两个活动,此时活动栈的变动情况如下图所示。
依次结束已打开的两个活动,此时活动栈的变动情况如下图所示。
- Standard :标准模式
- SingleTop :栈顶复用模式
- SingleTask :栈内复用模式
- 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对象传递进去。
主要特征:
- Action(动作): Intent 的动作是指要执行的操作,例如 ACTION_VIEW 用于查看数据,ACTION_SEND 用于发送数据等。
- Data(数据): 通过setData()或setType()方法设置,指定要处理的数据的URI或MIME类型。
- 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 或其他配置管理方式。
给应用页面注册快捷方式
元数据不仅能传递简单的字符串参数,还能传送更复杂的资源数据,比如支付宝的快捷方式菜单。
- 在res下创建一个xml的文件夹
- 在xml文件夹里面创建一个shortcuts.xml文件
- 在清单文件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)