QPython 权限不足问题排查——弹窗不弹、API 调用静默失败
现象
调用 QSL4A 的 API 时什么都没发生:
droid.makeToast("test")不弹 Toastdroid.takePicture()不拉起相机droid.scanBarcode()不打开扫码界面droid.startSensingTimed()调了但没数据返回
脚本本身不报错(因为 QSL4A 的 RPC 层对权限问题做了静默处理),但就是没效果。
排查步骤
步骤 1:确认是 QPython 的问题还是脚本写法问题
先在 REPL 里直接调最简单的 API:
from androidhelper import Android
droid = Android()
droid.makeToast("测试")
如果这都不弹 Toast,基本确定是环境问题(权限或 QPython 本身),不是你脚本的问题。
步骤 2:检查悬浮窗权限
Toast / Dialog / FSW2 弹窗 / Notification 都依赖悬浮窗权限。
检查路径:
系统设置 → 应用管理 → QPython → 权限 → 显示在其他应用上方 → 允许
部分 ROM 的名字不同:
- MIUI:设置 → 应用管理 → QPython → 显示在其他应用的上层
- ColorOS:设置 → 应用管理 → QPython → 悬浮窗权限
- OneUI:设置 → 应用 → QPython → 显示在其他应用上方
步骤 3:检查相机权限
takePicture 和 scanBarcode 需要相机权限:
系统设置 → 应用管理 → QPython → 相机 → 允许
步骤 4:检查位置权限
startLocating(GPS)需要精确 + 粗略位置权限bluetoothStartDiscovery(蓝牙扫描)在 Android 12+ 需要粗略位置权限
步骤 5:检查存储权限
- 拍照后保存到文件需要存储写入权限
- 打开已有的
.py文件需要存储读取权限
步骤 6:检查电池优化
某些 ROM 把 QPython 加入了电池优化白名单的反方向——限制它后台运行。如果脚本一会儿能用一会儿不能用,可能是 QPython 被后台杀掉了。
系统设置 → 应用管理 → QPython → 电池 → 无限制(或不优化)
权限问题的特殊情况
Android 13+ POST_NOTIFICATIONS
Android 13(API 33)新增了 POST_NOTIFICATIONS 运行时权限。如果 QPython 的状态栏通知不显示,检查这条权限是否授予。
Android 12+ 蓝牙权限拆分
Android 12 把原来一条 BLUETOOTH 权限拆成了:
BLUETOOTH_CONNECTBLUETOOTH_SCANBLUETOOTH_ADVERTISE
蓝牙扫描静默失败时,检查 BLUETOOTH_SCAN 和位置权限(Android 12+ 蓝牙扫描必须同时要位置)。
特殊 ROM 的限制
- MIUI / HyperOS:对第三方 App 的 WiFi 控制和蓝牙扫描有额外限制
- ColorOS:限制后台弹窗频率
- OneUI:电池优化非常激进,容易杀后台
遇到这些情况时,除了授予权限,可能还需要:
- 在 QPython 内部设置里找到「后台保护」选项并打开
- 把 QPython 加入「自启动」列表
- 开发者选项里关闭「MIUI 优化」或类似选项
自动检测权限缺失
写一个权限自检脚本,帮你快速定位哪条权限缺失:
# 在 QPython 终端里运行
from androidhelper import Android
import subprocess
# 检查 QPython 版本
droid = Android()
# 测试 Toast(悬浮窗权限)
try:
droid.makeToast("权限自检中...")
print("[OK] Toast 可用(悬浮窗权限已授予)")
except Exception as e:
print(f"[FAIL] Toast 失败:{e}")
# 测试 GPS(位置权限)
try:
droid.startLocating()
import time; time.sleep(2)
loc = droid.getLastKnownLocation().result
print(f"[OK] GPS 可用,最后位置: {loc}")
except Exception as e:
print(f"[FAIL] GPS 失败:{e}")
finally:
droid.stopLocating()
# 测试传感器(应该总可用)
try:
droid.startSensingTimed(1, 100)
import time; time.sleep(0.5)
events = droid.sensorsGetEventBuffered().result
print(f"[OK] 传感器可用,数据点: {len(events)}")
except Exception as e:
print(f"[FAIL] 传感器失败:{e}")
finally:
droid.stopSensing()
print("自检完成。")
小结
QSL4A API 调用静默失败,99% 是权限问题,不是 API 写错或 QPython 坏了。最常缺的三条权限是:悬浮窗(Toast/Dialog)、相机(拍照/扫码)、位置(GPS/蓝牙扫描)。排查顺序就是:REPL 直接调 → 逐条权限检查 → 电池优化检查。上面的自检脚本可以帮你快速定位。
继续看包安装失败和电池优化问题。