3. Activity
3. Activity
1. 基本用法
-
Activity
- 概念:可以包含用户界面的组件,主要用于和用户进行交互
- 每个 Activity 都应该重写 onCreate 方法
-
Layout
- res 中建立 layout 文件夹,并建立文件
- 最好每一个 Activity 对应一个布局 layout
- layout 创建好之后通过 setContentView 加载到 Activity 上
- 布局拖动内容可以直接修改 xml 代码
- 资源 id
R.layout.first_layoutR.id.button1
-
Toast
- 短暂提醒后消失
-
menu
- res 中建立 menu文件夹,并建立文件
- 由于版本不同,这里参照书中内容,进行如下修改,代码如下
- 继承
ComponentActivity layout文件增加Toolbarres/values/theme修改主题为Theme.AppCompat.Light.NoActionBar
- 继承
-
Main.kt
package com.example.helloworld
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.first_layout) // 设置 layout
val toolbar: Toolbar = findViewById(R.id.toolbar) // 绑定工具栏
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true) // 设置返回按钮
val button1: Button = findViewById(R.id.button) // 通过 id 找到 view, 并指明类型为 button
button1.setOnClickListener{
Toast.makeText(this, "You clicked Button 1", Toast.LENGTH_SHORT).show() // layout 为 context
}
Log.d("MainActivity", "onCreate execute")
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean { // 工具栏右边的 ... 菜单
menuInflater.inflate(R.menu.main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean { // 菜单按钮的点击逻辑
when(item.itemId){
R.id.add_item -> Toast.makeText(
this, "You clicked Add",
Toast.LENGTH_SHORT).show()
R.id.remove_item -> Toast.makeText(
this, "You clicked Remove",
Toast.LENGTH_SHORT).show()
}
return true
}
}
- layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme" />
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
- main_menu
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/add_item"
android:title="Add"/>
<item
android:id="@+id/remove_item"
android:title="Remove"/>
</menu>
- res/values/theme
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.HelloWorld" parent="Theme.AppCompat.Light.NoActionBar" />
</resources>
2. Intent
1. 总结
-
作用:
-
启动 Activity,启动 Service,发送广播,传递数据
-
主 Intent 中会有
intent-filter相关设置
-
-
分类
- 显式 Intent
- 在
Activity1中通过Intent对象和startActivity函数启动特定 Activity
- 在
- 隐式 Intent
- 显式 Intent
-
数据传输
- 发送数据
- Activity1
intent.putExtra(key, data)
- Activity2
data = intent.getStringExtra(key)
- Activity1
- 传回数据
- Activity1
startActivityForResult(intent, 1)- 重写
onActivityResult
- Activity2
intent.putExtra(key, data)setResult(RESULT_OK, intent
- Activity1
- 发送数据
2. 隐式 Intent 详解
1. 隐式 Intent
- 指定 action 和 category
- 在
AndroidManifest.xml和主代码中指定 - 内容似乎可以随意写,但是得对应上
- 只有两者都匹配时才会相应
.DEFAULT是默认 category,能自动添加到intent中- 每个
intent只能指定一个action,但是可以指定多个category - 注意
- 注意
xml的格式,以及android:exported需要改为 true
- 注意
- 在
- 优势
- 解构
2. 拓展
【暂不学习】
0. 代码
1. 显式 Intent + 数据传输代码
-
Activity1
-
package com.example.helloworld import android.app.ComponentCaller import android.content.Intent import android.os.Bundle import android.util.Log import android.view.Menu import android.view.MenuItem import android.widget.Button import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.first_layout) // 设置 layout val toolbar: Toolbar = findViewById(R.id.toolbar) // 绑定工具栏 setSupportActionBar(toolbar) supportActionBar?.setDisplayHomeAsUpEnabled(true) // 设置返回按钮 val button1: Button = findViewById(R.id.button) // 通过 id 找到 view, 并指明类型为 button button1.setOnClickListener{ Toast.makeText(this, "You clicked Button 1", Toast.LENGTH_SHORT).show() // layout 为 context val intent = Intent(this, MainActivity2::class.java) val data = "Hello Activity2" intent.putExtra("first_data", data) // 发送数据,类似map,第一个为键,用于选择哪个值,后者为值 // startActivity(intent) startActivityForResult(intent, 1) // 接受数据时调用这个函数表明需要返回一个结果,1代表请求码 } Log.d("MainActivity", "onCreate execute") } override fun onActivityResult( // 由于调用 startActivityForResult,因此需要重写方法来得到返回的数据 requestCode: Int, resultCode: Int, data: Intent?, caller: ComponentCaller ) { super.onActivityResult(requestCode, resultCode, data, caller) when(requestCode){ 1 -> if(resultCode == RESULT_OK){ val returnedData = data?.getStringExtra("data_return") Log.d("Activity1", "returned data is $returnedData") } } } override fun onCreateOptionsMenu(menu: Menu?): Boolean { // 工具栏右边的 ... 菜单 menuInflater.inflate(R.menu.main, menu) return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { // 菜单按钮的点击逻辑 when(item.itemId){ R.id.add_item -> Toast.makeText( this, "You clicked Add", Toast.LENGTH_SHORT).show() R.id.remove_item -> Toast.makeText( this, "You clicked Remove", Toast.LENGTH_SHORT).show() } return true } } -
Activity2
-
package com.example.helloworld import android.content.Intent import android.os.Bundle import android.util.Log import android.widget.Button import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar class MainActivity2 : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.second_layout) // 设置 layout val toolbar: Toolbar = findViewById(R.id.toolbar2) // 绑定工具栏 val extraData = intent.getStringExtra("first_data") // 接收数据 Log.d("Activity2", "data is $extraData") setSupportActionBar(toolbar) supportActionBar?.setDisplayHomeAsUpEnabled(true) // 设置返回按钮 toolbar.setNavigationOnClickListener { finish() } // 设置结束 act2 val button2: Button = findViewById(R.id.button2) // 通过 id 找到 view, 并指明类型为 button button2.setOnClickListener { val intent = Intent() intent.putExtra("data_return", "Hello Activity1") setResult(RESULT_OK, intent) finish() } } } -
firstlayout
-
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" android:minHeight="?attr/actionBarSize" android:theme="?attr/actionBarTheme" /> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Button" /> </LinearLayout> -
secondlayout
-
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar2" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" android:minHeight="?attr/actionBarSize" android:theme="?attr/actionBarTheme" /> <Button android:id="@+id/button2" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Button" /> </LinearLayout>
2. 隐式 Intent
-
activity1
-
package com.example.helloworld import android.app.ComponentCaller import android.content.Intent import android.os.Bundle import android.util.Log import android.view.Menu import android.view.MenuItem import android.widget.Button import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.first_layout) // 设置 layout val toolbar: Toolbar = findViewById(R.id.toolbar) // 绑定工具栏 setSupportActionBar(toolbar) supportActionBar?.setDisplayHomeAsUpEnabled(true) // 设置返回按钮 val button1: Button = findViewById(R.id.button) // 通过 id 找到 view, 并指明类型为 button button1.setOnClickListener{ val intent = Intent("com.example.helloworld.ACTION_START") intent.addCategory("com.example.helloworld.MY_CATEGORY") startActivity(intent) } Log.d("MainActivity", "onCreate execute") } } -
AndroidManifest
-
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.HelloWorld"> <activity android:name=".MainActivity2" android:exported="true" android:label="@string/title_activity_main2" android:theme="@style/Theme.HelloWorld" > <intent-filter> <action android:name="com.example.helloworld.ACTION_START"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="com.example.helloworld.MY_CATEGORY"/> </intent-filter> </activity> <activity android:name=".MainActivity" android:exported="true" android:label="@string/app_name" android:theme="@style/Theme.HelloWorld"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
3. 生命周期
1. 基础
1. 栈
- 在安卓中,Activity 的层叠关系可以用栈来表示
- 主动创建和销毁
- 创建的 Activity 出现在栈顶
- 返回后
finish的 Activity 在栈顶被移除
- 被动系统回收
- 根据 Activity 状态回收,不倾向于回收栈顶的 Activity
- 主动创建和销毁
2. Activity 状态和生存期
| 状态 | 内容 |
|---|---|
| 运行状态 | 返回栈的栈顶,最不容易被回收 |
| 暂停状态 | 不处于栈顶,但仍然可见 (运行 Activity 可能没全屏),不容易被回收 |
| 停止状态 | 不处于栈顶且不可见,仍保存对应的状态和成员变量,可能会被回收 |
| 销毁状态 | 从返回栈中被移除,最倾向于回收 |
| 生存期 | 操作 | 细节 | 操作 | 细节 | 整体细节 |
|---|---|---|---|---|---|
| 完整生存期 | onCreate |
第一次被创建时使用,完成 Activity 的初始化 | onDestrory |
销毁时使用 | 分别进行初始化和释放内存 |
| 可见生存期 | onStart |
不可见变为可见时调用 | onStop |
在变为完全不可见时调用,比如启动对话框(仍可见时),只会调用 onPause |
总是可见但不一定能交互,能管理可见资源,分别进行资源加载和释放,保证处于停止状态的 Activity 不会占用过多内存 |
| 前台生存期 | onResume |
准备进行交互时调用,此时位于栈顶 | onPause |
系统准备启动或者恢复另一个 Activity 时调用,会释放一些消耗 CPU 的资源,保存关键数据,执行要快 | 处于运行状态,可以进行交互 |
onRestart:从停止状态变为**运行状态 **- 左边从上到下,右边从下到上
3. 案例
有 MainActivity,NormalActivity 和 DialogActivity,其中 DialogActivity 不是全屏,点击 MainActivity 的两个按钮可以启动对应 Activity
- 启动时
- onCreate/onStart/onResume
- 退出时
- onPause/onStop/onDestrory
- 点击 NormalActivity 时(不可见)
- onPause/onStop
- 退出 NormalActivity 时
- onRestart/onStart/onResume
- 点击 DialogActivity 时
- onPause
- 退出 DialogActivity 时
- onResume
4. 回收
- 情况:当一个 Activity 点入其他 Activity 后进入停止状态(不可见时),然后从其他 Activity 返回,而原始 Activity 可能被回收
- 当没被回收时
- 仍处于停止状态
- onRestart/onStart/onResume
- 当被回收时
- 处于销毁状态,需要重新创建
- onCreate/onStart/onResume
- 此时临时数据被销毁,因此需要进行状态恢复
- 当没被回收时
- 恢复原理
- Activity 中提供
onSaveInstanceState回调- 该函数携带一个
Bundle类型参数,提供一些列方法保存不同的数据
- 该函数携带一个
- Activity 中提供
// 保存数据
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
val tempData = "Something"
outState.putString("data_key", tempData)
}
// 取出数据(在onCreate函数中)
if(savedInstanceState != null){ // 取出数据
val tempData = savedInstanceState.getString("data_key")
Log.d("saved_data", "tempData is $tempData")
}
val tempData = savedInstanceState?.getString("data_key") // 简化写法
tempData?.let{Log.d("saved_data", "tempData is $it")}
2. 启动模式
- 在 AndroidManifest.xml 的对应 Activity 处修改启动模式
| 启动模式 | 特征 | 具体 | 原理图 |
|---|---|---|---|
| standard | 每次创建一个新的 Activity | 可以递归创建若干次同一个 Activity,需要返回若干次回到第一个 Activity | |
| singleTop | 栈顶不会出现重复的 Activity | 在栈顶进行检查,判断是否需要启动新的 Activity,相同则不启动 | |
| singleTask | 整个栈不会出现重复的 Activity | 创建新的 Activity 时,如果发现该 Activity 已存在,则该 Activity 之上的全部出栈 | |
| singleInstance | 会有一个新的栈存储 Activity | 1 通过 singleInstance 调用2,2普通调用3,此时3返回1,然后返回2 |
4. 实践
1. 判断在哪个 Activity
- 创建一个 BaseActivity 类继承自 AppComPatActivity 类
- 增加一个 javaClass.simpleName 的 Log
- 后续继承自 BaseActivity
2. 随处退出程序
- 创建一个单例类 ActivityCollector 来管理 Activity 集合
- 维护一个 Activity 的 List
- 函数包括添加,移除和全部结束【问题:如果只需要结束一个呢,因为新版本似乎需要自己写 finish 逻辑】
3. 启动 Activity 的最佳写法
// 伴生类
companion object {
fun actionStart(context: Context, data1: String, data2: String) {
val intent = Intent(context, MainActivity2::class.java).apply {
putExtra("param1", data1)
putExtra("param2", data2)
}
context.startActivity(intent) // 没有 startActivityForResult
}
}
//调用启动
button1.setOnClickListener{
actionStart(this, "Activity1", "") // 启动 Activity
}
5. 汇总代码
【暂未完成返回数据到上一个 Activity】
MainActivity.kt
package com.example.helloworld
import android.app.ComponentCaller
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
class MainActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 设置 layout
setContentView(R.layout.first_layout)
ActivityCollector.addActivity(this)
// 绑定工具栏
val toolbar: Toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
// 设置返回按钮
supportActionBar?.setDisplayHomeAsUpEnabled(true)
// 取出保存的数据
val tempData = savedInstanceState?.getString("data_key")
tempData?.let{Log.d("saved_data", "tempData is $it")}
// 通过 id 找到 view, 并指明类型为 button
val button1: Button = findViewById(R.id.button)
// 启动 Activity
button1.setOnClickListener{
actionStart(this, "Activity1", "")
}
}
override fun onDestroy() {
super.onDestroy()
ActivityCollector.removeActivity(this)
}
// 工具栏右边的 ... 菜单
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.main, menu)
return true
}
// 菜单按钮的点击逻辑
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId){
R.id.add_item -> Toast.makeText(
this, "You clicked Add",
Toast.LENGTH_SHORT).show()
R.id.remove_item -> Toast.makeText(
this, "You clicked Remove",
Toast.LENGTH_SHORT).show()
}
return true
}
// 伴生类 启动 Activity
companion object {
fun actionStart(context: Context, data1: String, data2: String) {
val intent = Intent(context, MainActivity2::class.java).apply {
putExtra("param1", data1)
putExtra("param2", data2)
}
context.startActivity(intent) // 没有 startActivityForResult
}
}
// 保存杀死后台之后的数据
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
val tempData = "Something"
outState.putString("data_key", tempData)
}
}
MainAcitivity2.kt
package com.example.helloworld
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
class MainActivity2 : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.second_layout)
// toolbar 部分
val toolbar: Toolbar = findViewById(R.id.toolbar2)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true) // 设置返回按钮
toolbar.setNavigationOnClickListener { finish() } // 设置结束 act2
ActivityCollector.addActivity(this)
// 从前一个 Activity 接收数据
val extraData1 = intent.getStringExtra("param1")
val extraData2 = intent.getStringExtra("param2")
Log.d("Activity2", "param1 is $extraData1, param2 is $extraData2")
// 返回数据(但是未实现)
val button2: Button = findViewById(R.id.button2) // 通过 id 找到 view, 并指明类型为 button
button2.setOnClickListener {
val intent = Intent().apply { putExtra("data_return", "Hello Activity1") }
setResult(RESULT_OK, intent)
finish()
}
// 关闭所有 Activity
val button3: Button = findViewById(R.id.button3)
button3.setOnClickListener {
ActivityCollector.finishAll()
}
}
}
Util.kt
package com.example.helloworld
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.snackbar.Snackbar
// 输出当前是哪一个 Activity
open class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("BaseActivity", "${javaClass.simpleName} is created")
}
override fun onStart() {
super.onStart()
Log.d("BaseActivity", "${javaClass.simpleName} is started")
}
override fun onResume() {
super.onResume()
Log.d("BaseActivity", "${javaClass.simpleName} is resumed")
}
}
// Activity 管理
object ActivityCollector {
private val activities = ArrayList<Activity>()
fun addActivity(activity: Activity){
activities.add(activity)
}
fun removeActivity(activity: Activity){
activities.remove(activity)
}
fun finishAll() {
activities.forEach {
if(!it.isFinishing) {
it.finish()
}
}
activities.clear()
}
}
fun startNewActivity(context: Context, targetActivity: Class<out AppCompatActivity>) {
val intent = Intent(context, targetActivity)
context.startActivity(intent)
}
// 调用方法 startNewActivity(this, ActivityClass::class.java)
fun startNewActivity(context: Context, targetActivity: Class<out AppCompatActivity>, data1: String, data2: String) {
val intent = Intent(context, targetActivity).apply {
putExtra("param1", data1)
putExtra("param2", data2)
}
context.startActivity(intent)
}
fun startNewActivityAndFinish(activity: Activity, targetActivity: Class<out AppCompatActivity>) {
val intent = Intent(activity, targetActivity)
activity.startActivity(intent)
activity.finish()
}
// 调用方法 "This is Toast".showToast(context, Toast.LENGTH_LONG)
fun String.showToast(context: Context, duration: Int = Toast.LENGTH_SHORT) {
Toast.makeText(context, this, duration).show()
}
fun Int.showToast(context: Context, duration: Int = Toast.LENGTH_SHORT) {
Toast.makeText(context, this, duration).show()
}
/* 调用方法
* view.showSnackBar("This is SnackBar", "Action") {
* //
* 处理具体的逻辑
* }
**/
fun View.showSnackBar(text: String, actionText: String? = null,
duration: Int = Snackbar.LENGTH_SHORT, block: (() -> Unit)? = null) {
val snackBar = Snackbar.make(this, text, duration)
if (actionText != null && block != null) {
snackBar.setAction(actionText) {
block()
}
}
snackBar.show()
}
fun View.showSnackBar(resId: Int, actionResId: Int? = null,
duration: Int = Snackbar.LENGTH_SHORT, block: (() -> Unit)? = null) {
val snackBar = Snackbar.make(this, resId, duration)
if (actionResId != null && block != null) {
snackBar.setAction(actionResId) {
block()
}
}
snackBar.show()
}
first_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme" />
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
second_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme" />
<Button
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
<Button
android:id="@+id/button3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Quit App" />
</LinearLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.HelloWorld">
<activity
android:name=".MainActivity2"
android:exported="true"
android:label="@string/title_activity_main2"
android:theme="@style/Theme.HelloWorld" >
<intent-filter>
<action android:name="com.example.helloworld.ACTION_START"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="com.example.helloworld.MY_CATEGORY"/>
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.HelloWorld">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
themes.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.HelloWorld" parent="Theme.AppCompat.Light.NoActionBar" />
</resources>

浙公网安备 33010602011771号