feat(android): 支持沉浸式状态栏、地图定位与自定义签名

- 配置 edge-to-edge 沉浸式状态栏与刘海屏适配
- 新增百度地图权限、AK 配置及定位权限说明
- 接入 MethodChannel 实现返回键退后台热启动优化
- 配置自定义签名并更新构建逻辑
- 完善 token 刷新与鉴权失效统一处理
- 新增地图页与截图页路由
- 修复返回键拦截导致的 PopScope 失效问题
This commit is contained in:
TongTongStudio
2026-08-19 03:43:12 +08:00
parent 41d815336a
commit 06cdc77172
51 changed files with 3988 additions and 634 deletions

View File

@@ -1,3 +1,6 @@
import java.util.Properties
import java.io.FileInputStream
plugins {
id("com.android.application")
id("kotlin-android")
@@ -5,6 +8,13 @@ plugins {
id("dev.flutter.flutter-gradle-plugin")
}
// 读取签名配置
val keystoreProperties = Properties()
val keystorePropertiesFile = rootProject.file("key.properties")
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}
android {
namespace = "com.ttstd.familycare"
compileSdk = flutter.compileSdkVersion
@@ -30,11 +40,22 @@ android {
versionName = flutter.versionName
}
signingConfigs {
create("own") {
keyAlias = keystoreProperties["keyAlias"] as String?
keyPassword = keystoreProperties["keyPassword"] as String?
storeFile = keystoreProperties["storeFile"]?.let { file(it) }
storePassword = keystoreProperties["storePassword"] as String?
}
}
buildTypes {
debug {
signingConfig = signingConfigs.getByName("own")
}
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug")
// 使用自有签名配置
signingConfig = signingConfigs.getByName("own")
}
}
}

View File

@@ -1,17 +1,43 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
<!-- 百度地图所需权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:label="ttstd_family_care"
android:name="${applicationName}"
android:name=".AppApplication"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:launchMode="singleTask"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize"
android:windowLayoutInDisplayCutoutMode="shortEdges">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
@@ -30,16 +56,10 @@
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<!-- 百度地图 AK -->
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="bTdW9YqOykriIUvXe4RpZ2SEgVciR33B" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>

View File

@@ -0,0 +1,15 @@
package com.ttstd.familycare;
import com.baidu.mapapi.base.BmfMapApplication;
/**
* 应用入口 Application。
*
* 继承插件提供的 {@link BmfMapApplication},其 onCreate 会自动执行
* {@code SDKInitializer.setAgreePrivacy(...)} 与 {@code SDKInitializer.initialize(this)}。
*
* 必须完成该原生初始化,否则地图页创建 BMFMapWidget(平台视图)时会抛出
* "you have not supplyed the global app context info from SDKInitializer.initialize(Context)"。
*/
public class AppApplication extends BmfMapApplication {
}

View File

@@ -1,6 +1,38 @@
package com.ttstd.familycare;
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "com.ttstd.familycare/app";
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler(
(call, result) -> {
if (call.method.equals("moveTaskToBack")) {
// 将应用退到后台而不销毁 Engine,实现热启动优化
moveTaskToBack(false);
result.success(true);
} else {
result.notImplemented();
}
}
);
}
/**
* 注意:不再直接拦截 onBackPressed。
* 贪婪拦截会导致 Flutter 内部的 PopScope 失效,使得子页面(如 AppsPage)点击返回键时
* 无法执行 Flutter 侧定义的返回逻辑(如 context.pop()),而是直接退到桌面。
*
* 优化后的方案:
* 1. 移除这里的贪婪拦截,让返回键事件传递给 Flutter 引擎。
* 2. 在 Flutter 的首页 Root 节点使用 PopScope 拦截返回,弹出退出确认。
* 3. 用户确认退出时,通过上面的 MethodChannel 调用 moveTaskToBack。
*/
}

View File

@@ -5,6 +5,12 @@
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
<!-- 沉浸式:状态栏与导航栏透明,内容延伸到安全区(edge-to-edge) -->
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<!-- 刘海屏:允许内容绘制到刘海区域 -->
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
@@ -14,5 +20,11 @@
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
<!-- 沉浸式:状态栏与导航栏透明,内容延伸到安全区(edge-to-edge) -->
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<!-- 刘海屏:允许内容绘制到刘海区域 -->
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
</resources>

View File

@@ -5,6 +5,12 @@
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
<!-- 沉浸式:状态栏与导航栏透明,内容延伸到安全区(edge-to-edge) -->
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<!-- 刘海屏:允许内容绘制到刘海区域 -->
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
@@ -14,5 +20,11 @@
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
<!-- 沉浸式:状态栏与导航栏透明,内容延伸到安全区(edge-to-edge) -->
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<!-- 刘海屏:允许内容绘制到刘海区域 -->
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
</resources>