1.Flet版本
https://pypi.org/project/flet/#history
Flet 0.28.3(2025.05版本)和版本 0.21.2 (2024.09)比较:
- 很多属性名、方法名与新版 Flet 不兼容,例如:
- colors 改为 Colors
- page.dialog = dialog
dialog.open = True
page.update()
改为page.open(dialog) - PopupMenuButton 部分参数不同
- ListView、Row、Column 的 expand 行为有差异
- 在 Flet 0.21.0 版本中,page.window_width = 420 和 page.window_height = 340 是直接支持的快捷属性(shortcut properties),设置后调用 page.update() 就能生效(桌面平台)。
- 在 0.28.3(以及从 0.23.0 开始的更高版本)中,这些 page.window_* 属性(如 window_width、window_height)已被弃用(deprecated)并移动到 page.window 对象下。
- 旧版完全不能打包 Android APK
-
PIP会自动尝试安装 flet-desktop 0.28.3
-
旧版运行方式:python main.py,新版运行方式:flet run main.py
2.如何卸载旧版本
2.1.完全卸载旧版 Flet
请依次执行:
pip uninstall -y flet-cli
pip uninstall -y flet
pip uninstall -y flet-desktop
pip uninstall -y flet-core
pip uninstall -y flet-runtime
重复执行直到全部提示:
WARNING: Skipping ... as it is not installed.
2.2.手动安装新版
pip install flet
pip install flet==0.28.3
2.3.新版flet不需要安装 flet-cli
验证:
pip list
你应该看到:
flet 0.28.3
flet-cli 0.28.3
flet-core 0.24.1
flet-desktop 0.28.3
flet-runtime 0.24.1
并且没有 flet-cli / flet-desktop。
3.使用新版 Flet 打包 Android APK 的流程
新版 Flet 不再使用 flet-cli 来打包,而是使用:
flet-py-mobile
它会自动生成一个 Flutter + Python 的混合工程,然后构建成 APK。
第 1 步:安装 Android SDK + Java
下载地址:(务必使用 Temurin JDK 17)
https://adoptium.net/temurin/releases/?version=17
注意:
OpenJDK25U-jdk_x64_windows_hotspot_25.0.1_8.msi
这是 Eclipse Adoptium(Temurin)JDK 8 的安装文件(不是 JDK 17)。Android 构建不能使用 JDK 8!JDK 8 在 2024 以后已不兼容现代 Android Gradle Plugin。下载的 JDK 8(版本号 1.8.x 或 8.x,或者 25.0.1 是内部格式)不能用于 Android APK 构建。
应该下载这样的文件名:
OpenJDK17U-jdk_x64_windows_hotspot_17.0.13_11.msi
安装步骤:
– 双击 .msi
– 一路 Next → Next → Install
– 完成即可
安装后设置:
C:\Windows\System32>setx JAVA_HOME "C:\Program Files\Eclipse Adoptium\jdk-17.0.17.10-hotspot"
SUCCESS: Specified value was saved.
C:\Windows\System32>java -version
openjdk version "17.0.17" 2025-10-21
OpenJDK Runtime Environment Temurin-17.0.17+10 (build 17.0.17+10)
OpenJDK 64-Bit Server VM Temurin-17.0.17+10 (build 17.0.17+10, mixed mode, sharing)
C:\Windows\System32>
Android SDK(Command Line Tools)
下载地址:
https://developer.android.com/studio#cmdline-tools-only
下载后得到一个 zip,例如:
commandlinetools-win-11076708_latest.zip
手动解压到:
C:\Android\Sdk\cmdline-tools\latest\
目录结构应该是:
C:\Android\Sdk\
cmdline-tools\
latest\
bin\
sdkmanager.bat
配置 ANDROID_SDK_ROOT 环境变量
C:\Windows\System32>setx ANDROID_SDK_ROOT "C:\Android\Sdk"
SUCCESS: Specified value was saved.
C:\Windows\System32>%ANDROID_SDK_ROOT%\cmdline-tools\latest\bin\sdkmanager --version
19.0
第 2 步:安装 Android 必要构建组件
%ANDROID_SDK_ROOT%\cmdline-tools\latest\bin\sdkmanager "platform-tools" "platforms;android-33" "build-tools;33.0.2"
如果你想避免重复输入路径,可以 temporarily 添加 PATH:
set PATH=%PATH%;%ANDROID_SDK_ROOT%\cmdline-tools\latest\bin
然后:
sdkmanager "platform-tools" "platforms;android-33" "build-tools;33.0.2"
第 3 步:安装 Flutter SDK
请打开 Flutter 官方下载地址:
👉 https://docs.flutter.dev/get-started/install/windows
在页面中找到:
✔ Download Flutter SDK
下载下来得到的文件名通常是类似:
flutter_windows_3.19.6-stable.zip
把 zip 解压到:
C:\Flutter
之后你的目录应该是:
C:\Flutter\bin\flutter.bat
设置 PATH
setx PATH "%PATH%;C:\Flutter\bin"
第 4 步:构建 APK
flet-py-mobile 是“未来版本的设计草案”,目前尚未发布,当前(Flet 0.21.2)官方唯一支持的 Android 打包方式是:
flet build apk --project AuthVault --output auth_vault.apk --android-package com.auth.vault --app-icon assets/password-100.png
Creating Flutter bootstrap project...OK
Customizing app icons and splash images...OK
Generating app icons...OK
Generating splash screens...OK
Packaging Python app...OK
Building .apk for Android...OK
Copying build to build\apk directory...OK
Success!
它会创建一个文件夹结构:
build/
apk/
app-release.apk
app-release.apk.sh1
目录里出现两个文件:
app-release.apk ← 你的正式安装包
app-release.apk.sha1 ← 哈希校验文件(可忽略)
第 5 步:安装 APK 到 Android
直接复制到手机并点击安装
把:
build/apk/app-release.apk
复制到手机 → 点击安装。
⚠️ 安卓可能提示:
来自未知来源的应用
你需要在手机设置里允许安装:
来自此来源的应用(例如:文件管理器)
4.打包命令优化
第 1 步:创建 assets/ 目录
就在项目的根目录,和你的 main Python 文件在一起
第 2 步:将你的图片放进去
放文件:
template/icon.png ← app 图标(普通 1024×1024)
template/adaptive_foreground.png ← Android adaptive 前景
template/adaptive_background.png ← Android adaptive 背景
template/splash.png ← 你刚生成的 1080×1920 splash
第 3 步:创建 pyproject.toml
在项目的根目录,至少需要这些内容, 你可以增加项目的依赖文件:
内容如下:
[project]
name = "AuthVault"
version = "0.1.0"
description = "Your app description"
dependencies = [
"flet",
# add other dependencies here
]
[tool.flet]
# Optional: Set package name (Android bundle ID)
# If omitted, defaults to something like com.company.app
org = "com.auth"
product = "vault" # Combines with org to form com.auth.vault
[tool.flet.splash]
color = "#FFFFFF" # Splash background color (light mode)
# dark_color = "#000000" # Optional: for dark mode
第 4 步:使用toml文件进行构建
flet build apk --project AuthVault --output build
也可以构建 AAB:
flet build aab --project AuthVault --output build
Requirements for images
All should be high-resolution PNG (at least 1024×1024 recommended for best results).
icon.png: Square, with transparent background if desired.
Adaptive icons (adaptive_?.png): Foreground should be opaque in the center, transparent edges; background can be solid color.
splash.png: Transparent background preferred; it will be centered on the colored background.
If you need more advanced customization
For things beyond icons/splash (e.g., custom AndroidManifest.xml, extra Flutter dependencies, permissions): Clone the official template and use –template ./template (but ensure it has cookiecutter.json if local).
Most users don’t need this—assets + pyproject.toml handles 99% of icon/splash/package needs.
5.应用描述
🟦【完整版应用描述(适合 Google Play 上架)】
AuthVault 是一款专为个人账号管理打造的安全轻量级工具,让你轻松管理多个平台的登录信息。无广告、不联网、数据仅存储在本地设备,为你带来真正安全、无干扰的使用体验。
应用支持:
🔐 本地数据存储,不上传云端,账号更安全
🗂️ 账号列表管理,分类清晰、一眼就能找到
➕ 快速新增账号(名称 + 详细信息)
✏️ 编辑现有账号,随时保持同步更新
🗑️ 安全删除不再使用的账号
🔍 搜索功能快速定位目标账号
📱 支持 Android 底部菜单(BottomAppBar + FAB)操作更便捷
💻 同时支持 Windows 桌面运行(跨平台)
AuthVault 专注于本地隐私保护,不需要登录、不需要网络权限,让你完全掌控自己的敏感数据。
🟦【一句话简介(Short Description)】
本地安全的账号管理工具,轻松添加、修改、搜索和管理你的各类登录信息。
🟦【专业版描述(适合网站、文档、商业环境)】
AuthVault 是一款跨平台的本地账号管理器,采用 Flet 框架构建,同时支持 Android 与 Windows。应用所有数据均保存在用户本地设备,无需服务器、无需网络权限,确保账号信息始终受用户掌控。通过直观的界面与底部操作栏(BottomAppBar + FAB),用户可以快速添加、查看、编辑与删除账号记录。应用还支持自适应布局系统,在不同平台呈现最佳 UI 体验。
6.问题
6.1.为什么要下载Eclipse Adoptium JDK? Oracle 没有Java JDK 吗?
我推荐 Eclipse Adoptium(原 AdoptOpenJDK)只是因为它在 构建 Android 时更稳定、安装最方便、许可证无脑可用。
Oracle 官方依然提供 JDK 下载:
🔗 https://www.oracle.com/java/technologies/downloads/
如果你愿意,你可以直接安装:
Oracle JDK 17(LTS)
Oracle JDK 21(LTS)
安装后设置:
setx JAVA_HOME "C:\Program Files\Java\jdk-17"
Android 构建工具(Gradle + AGP)可以使用 Oracle JDK 完全正常工作。
👉 所以:Oracle JDK 是可用的!不是必须用 Adoptium。
那为什么大多数教程推荐 Eclipse Adoptium(Temurin)?
1. 许可证最宽松,无需担心商用使用
Oracle JDK 现在免费 → 但有使用条款,不算阻碍,但有时会令人犹豫。
Adoptium(Temurin)来自 Eclipse 基金会,完全自由、无任何商业限制。
- Android Gradle Plugin 官方测试最多的 JDK
Google 官方推荐:
Use Temurin JDK 17
(Android Studio Electric Eel 之后)
这是因为许多 CI/CD、自动构建平台(GitHub Actions、Azure Pipelines)都默认用 Temurin。
- 安装更简单,路径更干净
Oracle JDK 安装路径有时包含空格:
C:\Program Files\Java\jdk-17
Gradle/SDKMAN 有时候在 Windows 下对空格处理不好。
Temurin 安装路径简单:
C:\Users\name.jdks\jdk-17
对构建工具更友好。
- 不会自动更新破坏构建环境
Oracle JDK(尤其是 Installer 版)可能会自动更新/替换目录。
Temurin(zip 版)完全手动,构建环境极其稳定。
- 最佳实践(Android 官方)
使用 JDK 17(Temurin)构建 Android APK
这是 Google、Flutter、Gradle 都官方推荐的组合。
6.2.为什么必须使用 JDK 17?
因为 Android Gradle Plugin(AGP)8.x 之后不再支持:
JDK 8
JDK 9
JDK 10
JDK 12,13,14,15,16
Google 官方文档明确要求:
“AGP 8.x requires JDK 17 to run.”
flet-py-mobile 就是基于 Flutter + AGP 新体系构建 APK,因此必须满足要求。
6.3.Windows 没开启开发者模式
Package file_picker:windows references file_picker:windows as the default plugin, but it does not provide an inline
implementation.
Ask the maintainers of file_picker to either avoid referencing a default implementation via platforms: windows:
default_package: file_picker or add an inline implementation to file_picker via platforms: windows: pluginClass or
dartPluginClass.
Building with plugins requires symlink support.
Please enable Developer Mode in your system settings. Run
start ms-settings:developers
to open settings.
Error building Flet app - see the log of failed command above.
这是 Windows 系统 在创建 Flutter 插件(例如 file_picker、window_manager)时需要创建 符号链接(symlinks),但你的 Windows 没开启开发者模式,导致构建失败。
这是 Flutter 在 Windows 的一个非常常见要求。
解决方法:
开启 Windows Developer Mode(开发者模式)
start ms-settings:developers
或者手动操作:
- 打开 设置
- 打开 隐私和安全性
- 找到 开发者选项 或 开发人员模式 (Developer Mode)
- 开启 “开发人员模式”
系统可能会提示确认「开启开发人员模式」,点 是。
6.4.安装的 Flutter 版本太新
Flet 0.21.2 官方兼容的 Flutter 版本
Flet 官方当前(2024)稳定支持:
✔ Flutter 3.19.x
✔ Flutter 3.16.x
而你下载的 Flutter(因为最新版本)可能是:
❌ Flutter 3.24.x
❌ Flutter 3.27.x
❌ Flutter master / beta
这些版本改动过多,导致 serious_python + FlutterPlugin.java/kotlin 编译失败。
6.4.Flutter
Flutter 是 Google 推出的一个跨平台 UI 开发框架,用一套代码就可以同时开发 Android、iOS、Web、桌面等多端应用。
核心特点
- 使用 Dart 语言 编写代码,通过 AOT/JIT 编译获得较高的运行性能。
-
内置自绘引擎(如 Skia / Impeller),不用系统原生控件,而是自己渲染界面,因此不同平台上的界面外观高度一致。
-
采用 响应式 / 声明式 UI 模型,界面由一棵嵌套的 Widget 树组成,状态变化时重新构建对应部分的 UI。
-
和 Flet 的关系
Flet 可以理解为:用 Python 写 Flutter UI 的一层封装,底层其实还是 Flutter 在渲染界面。 -
Python 代码(Flet 控件),Flet 会把它映射成 Flutter 的 Widget 并在 Flutter 引擎里显示出来,因此既有 Flutter 的跨平台能力,又能用熟悉的 Python 开发。
6.5.Flet APK 构建失败 – cryptography
使用了 cryptography 这个二进制依赖(它包含 Rust/C 扩展,需要针对 Android 的预编译 wheel)。
cryptography 是一个二进制包(包含 Rust/C 扩展),在 Flet 的 Android 构建过程中(serious_python + pip),如果没有针对 Android 的预编译 wheel,它会尝试从源代码(tar.gz)构建。
构建需要 Rust 编译器、OpenSSL headers 等工具链,但 Flet 的移动构建环境(Windows 上运行)不支持从源编译这些复杂包——它会卡住或直接报错
Flet 是否支持 cryptography?
- cryptography 是典型的 binary 包(非纯 Python),官方文档明确列为例子:必须有针对 Android 的预编译 wheel,否则 pip 会尝试从源编译,导致构建卡住或失败。
-
Flet 提供自己的 PyPI 镜像 https://pypi.flet.dev ,托管了一些常见 binary 包的 Android/iOS wheel(如 numpy、pillow 等)。
-
当前(2025 年底)cryptography 不在 Flet 的支持列表中(查看 https://flet.dev/docs/reference/binary-packages-android-ios/ 或 https://pypi.flet.dev)
解决方案
替换为纯 Python 替代库
常见加密需求如 AES、Fernet、PBKDF2 等,Python 标准库 + pycryptodome 完全够用。
删除 pip 缓存(防止使用旧的 tar.gz):
路径:C:\Users\szdav\AppData\Local\pip\cache
删除整个 cache 文件夹,或里面所有 cryptography 文件。
6.6.Flet APK 构建失败 – Data Frame
- pandas 是一个复杂的二进制依赖包(包含 C 扩展、依赖 numpy 等),Flet 的 Android 打包环境(serious_python)不支持从源代码编译这种大型包(会缺少编译工具链、时间过长或直接失败)。
-
pandas 是 “native” 包(非纯 Python),在移动端 Python runtime(CPython for Android)下支持不完善。
-
Flet 官方文档和 GitHub discussions 明确指出:pandas 等 native 包的自动化支持尚未完全实现,需要手动构建或额外配置(参考官方指南:https://flet.dev/docs/guides/python/packaging-app-for-distribution#native-python-packages-for-android-and-ios)
-
Flet 的私有 PyPI 提供了 pandas 2.2.3 的预编译 Android wheel
-
虽然 Flet 官方文档(截至 2025 年 12 月)声称支持 pandas 2.2.2,并提供预编译 Android wheel(在 https://pypi.flet.dev) ,但 pip 优先下载了源代码 tar.gz,而不是 wheel。原因:pip 缓存问题、版本匹配不精确、或当前 Flet 版本的 extra-index-url 未正确优先 wheel。
-
GitHub 上多个类似 issue 确认:pandas 属于 “native” 包,自动化支持不完善,许多用户遇到编译失败或运行时错误(如 dtype mismatch)。许多用户报告类似问题:构建时安装成功,但运行时 ModuleNotFoundError 或 ImportError(尤其是 numpy/pandas 组合)。
-
pandas 是重型二进制依赖(APK 会增大几十 MB),且在移动端性能开销大。对于本地凭证管理器,用 list[dict] + json 完全替代(简单、安全、构建无问题)。
7.Reference
7.1.Flet 内置的 ft.Icons 图标
Flet 内置的 ft.Icons 图标非常多,和 Material Icons 基本一致。
Flet 官方给了一个专门的“Icons 浏览器”示例,可以搜索和拷贝所有图标名称;另外文档里也有完整索引。
https://gallery.flet.dev/icons-browser/
ft.Icons.SEARCH
ft.Icons.ADD
ft.Icons.REMOVE
ft.Icons.EDIT
ft.Icons.DELETE
ft.Icons.CLOSE
ft.Icons.CHECK
ft.Icons.CANCEL
ft.Icons.SAVE
ft.Icons.OPEN_IN_NEW
ft.Icons.HOME
ft.Icons.MENU
ft.Icons.SETTINGS
ft.Icons.PERSON
ft.Icons.LOCK
ft.Icons.LOGOUT
ft.Icons.REFRESH
ft.Icons.RESTART_ALT
ft.Icons.ARROW_BACK
ft.Icons.ARROW_FORWARD
ft.Icons.LIST
ft.Icons.FILTER_LIST
ft.Icons.SORT
ft.Icons.SEARCH_OFF
ft.Icons.INFO
ft.Icons.WARNING
ft.Icons.ERROR
ft.Icons.NOTIFICATIONS
ft.Icons.NOTIFICATIONS_OFF
ft.Icons.CLOUD
ft.Icons.CLOUD_DOWNLOAD
ft.Icons.CLOUD_UPLOAD
ft.Icons.FILE_OPEN
ft.Icons.FOLDER
ft.Icons.FOLDER_OPEN
ft.Icons.EMAIL
ft.Icons.PHONE
ft.Icons.SHARE
ft.Icons.LINK
7.2.list数组 vs list元组
# list[dict] —— 推荐写法
credentials = [
{"id": 1, "site": "github.com", "username": "alice", "password": "xxx", "note": ""},
{"id": 2, "site": "bank.com", "username": "alice123", "password": "yyy", "note": "主账户"},
]
# 搜索、修改、打印都超级清晰
for c in credentials:
if "alice" in c["username"]:
print(c["site"], c["username"])
c["note"] = "已标记" # 直接改
# list[tuple] —— 必须记住索引顺序,极其痛苦
# (id, site, username, password, note)
credentials = [
(1, "github.com", "alice", "xxx", ""),
(2, "bank.com", "alice123", "yyy", "主账户"),
]
# 写代码时永远在数 0,1,2,3,4…… 改一个字段顺序就全崩
for c in credentials:
if "alice" in c[2]: # c[2] 是 username?谁知道!
print(c[1], c[2]) # c[1] 是 site?又要数……
# c[4] = "已标记" # tuple 不可变,根本改不了!
特殊情况才用 tuple
- 数据永不改变且追求极致性能(百万级以上)。
- 用作字典 key(tuple 可 hash,dict 不行)。
- 返回多个值时 return name, password(函数级,不是存储)。
self.conn.row_factory = sqlite3.Row 是 Python sqlite3 模块里最强最好用的隐藏神技,加了这一行之后,你的所有查询结果就从“只能按数字索引取值”变成“既能按数字索引,又能按列名取值”。
默认情况:
self.cur.execute("SELECT id, site, username, password, note FROM users")
row = self.cur.fetchone()
print(row[0]) # 必须记:0 是 id
print(row[2]) # 必须记:2 是 username
# 一旦改了字段顺序,或者字段多了,全乱套!
使用factory:
self.conn.row_factory = sqlite3.Row !
self.cur.execute("SELECT id, site, username, password, note FROM users")
row = self.cur.fetchone()
# 两种方式都能用,随你喜欢!
print(row[0]) # 老方式仍然有效
print(row["username"]) # 新方式!直接用列名,像字典一样!
print(row.username) # 甚至可以这样点出来!
7.3.获取系统的语言
1.flet.PagePlatform
根据 Flet 官方文档(版本 0.28.3),Page 对象中的 locale 相关功能主要通过 page.locale_configuration 属性实现,它用于配置应用的本地化支持(包括支持的语言列表、回退语言等)。这个属性会自动从系统/设备/浏览器中获取首选语言,并匹配你的配置。
官方文档链接如下:
Page 控件的完整文档(包含 locale_configuration 的详细说明):https://flet.dev/docs/controls/page/
LocaleConfiguration 类型文档(locale 配置类的属性和用法):https://flet.dev/docs/reference/types/localeconfiguration/
Locale 类型文档(用于构建语言对象的类,如 ft.Locale(“zh”, “CN”)):https://flet.dev/docs/reference/types/locale/
Flet ft.PagePlatform 的官方文档
https://flet.dev/docs/reference/types/pageplatform/
– ANDROID
– ANDROID_TV
– IOS
– LINUX
– MACOS
– WINDOWS
import flet as ft
def main(page: ft.Page):
# 打印当前平台
print(f"当前平台: {page.platform} ({page.platform.value})")
# 根据平台显示不同 UI
if page.platform == ft.PagePlatform.MACOS:
page.add(ft.Text("macOS OS"))
elif page.platform == ft.PagePlatform.ANDROID:
page.add(ft.Text("Android OS"))
elif page.platform == ft.PagePlatform.WINDOWS:
page.add(ft.Text("Windows OS"))
else:
page.add(ft.Text(f"通用平台: {page.platform.name}"))
# 测试手动设置(仅开发时用)
def set_android(e):
page.platform = ft.PagePlatform.ANDROID
page.update()
print(f"新平台: {page.platform}")
page.add(ft.ElevatedButton(" Android", on_click=set_android))
ft.app(target=main)
2.Python Locale
import locale
language = locale.getdefaultlocale()[0] # → 'zh_CN'、'en_US'、'fr_FR' 等
Windows 把「语言」拆成了两套设置:
- 显示语言(决定界面文字) → 中文(中华人民共和国)
- 区域格式(决定日期、数字、货币格式) → 英语(加拿大)
- 键盘语言
- 语音语言
Python 的 locale.getlocale(locale.LC_CTYPE) 默认读取的是「区域格式」的语言,所以返回了 English_Canada。
而大多数程序(包括 Flet、Chrome、Android)真正关心的其实是第 1 项:显示语言(Display Language)。
import os
import locale
def get_real_windows_display_language() -> str:
"""
在 Windows 上准确获取「显示语言」(就是设置里最上面的那个)
完全不受「区域格式」影响
"""
try:
import winreg
# Windows 10/11 注册表路径
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
r"Control Panel\International\User Profile")
lang_list, _ = winreg.QueryValueEx(key, "Languages")
winreg.CloseKey(key)
# lang_list 是列表,例如 ['zh-CN', 'en-CA']
preferred = lang_list[0] # 第一个就是显示语言
return preferred.replace("-", "_") # 转成 zh_CN 格式
except Exception:
pass
try:
locale.setlocale(locale.LC_CTYPE, "")
lang = locale.getlocale(locale.LC_CTYPE)[0]
return lang.replace("-", "_") if lang else "en_US"
except Exception:
return "en_US"
def get_real_language() -> str:
lang = get_real_windows_display_language() or "en_US"
print("真实显示语言(Windows 设置最上面那个):", lang)
return lang
# 测试一下
print("注册表真实显示语言 →", get_real_windows_display_language()) # → zh_CN
print("locale.getlocale() →", locale.getlocale(locale.LC_CTYPE)[0]) # → English_Canada
print("真实显示语言 →", get_real_language()) # → zh_CN
3.os.environ.get(‘LANG’)
lang = os.environ.get('LANG')
print(f"os.environ['LANG'] → {lang2}")
4.Android 原生命令
try:
lang = subprocess.check_output(
["getprop", "persist.sys.locale"],
text=True
).strip()
print(f"getprop persist.sys.locale → {lang}") # 格式: zh-CN, en-US
except Exception as e:
print(f"getprop 失败: {e}")
5.Java 接口 – Android
try:
from java.android.content.res import Configuration
from java.util import Locale
config = Configuration()
java_locale = Locale.getDefault()
lang = f"{java_locale.getLanguage()}_{java_locale.getCountry()}"
if java_locale.getScript():
lang += f"_{java_locale.getScript()}"
print(f"Java Locale.getDefault() → {lang}")
except Exception:
print("Java 接口不可用(非 Android 或未启用 Java 桥接)")


