permission
统一查询权限状态,并请求位置或通知权限。
统一权限入口:查询授权状态,并在支持的模块上触发系统授权弹窗。
边界:permission只管「查状态 / 弹授权」,不替代业务模块。拍照、选图、读通讯录等具体操作仍调用photos、contacts等模块。当前运行时request()仅支持location和notifications;status()可查location、notifications、health、motion、speech。MODULES列出规划中的统一键名,其余键请先用各业务模块自带 API。
#模块概览
| 项 | 说明 |
|---|---|
| 导入 | import permission |
| 适合做什么 | 设置页展示权限、功能前置判断、批量刷新状态 |
| 调用时机 | request() 放在按钮回调;不要写在 AppUI body() 中 |
| 推荐顺序 | status(module) 判断 → 需要时 request(module) → 再 status 确认 → 调业务模块 |
| 判断授权 | 看返回字典的 authorized 字段,不要只比对 status 字符串 |
#快速开始
下面脚本查询定位与通知权限,并在未授权时发起申请:
import permission
for key in ("location", "notifications"):
entry = permission.status(key)
print(key, "→", entry)
if not entry.get("authorized"):
result = permission.request(key)
print("申请结果:", result)
entry = permission.status(key)
print("最新状态:", entry)
request("location") 只触发系统弹窗,不等待用户点选;request("notifications") 会等待用户响应并返回 granted。
#AppUI 示例
权限操作全部放进按钮回调;被拒绝后展示状态,不循环弹窗。
import appui
import permission
state = appui.State(
location_status="未查询",
notification_status="未查询",
message="点击按钮开始",
)
def format_entry(entry):
if not entry:
return "未查询"
if entry.get("error"):
return str(entry.get("error"))
mark = "已授权" if entry.get("authorized") else "未授权"
return f"{mark}({entry.get('status', 'unknown')})"
def find_entry(statuses, module_name):
for item in statuses.get("modules", []):
if item.get("module") == module_name:
return item
return {}
def refresh_all():
result = permission.status_all()
if not result.get("success", True):
state.message = str(result)
return
state.location_status = format_entry(find_entry(result, "location"))
state.notification_status = format_entry(find_entry(result, "notifications"))
state.message = "已刷新全部权限"
def request_location():
result = permission.request("location")
if result.get("error"):
state.message = result["error"]
return
state.location_status = format_entry(permission.status("location"))
state.message = "已发起定位授权,请在系统弹窗中选择"
def request_notifications():
result = permission.request("notifications")
if result.get("error"):
state.message = result["error"]
return
if "granted" in result:
mark = "已授权" if result.get("granted") else "未授权"
state.notification_status = f"{mark}({result.get('status', '—')})"
else:
state.notification_status = format_entry(permission.status("notifications"))
state.message = "通知权限已更新"
def body():
return appui.NavigationStack(
appui.Form([
appui.Section("定位", [
appui.Button("申请定位权限", action=request_location)
.button_style("bordered_prominent"),
appui.LabeledContent("状态", value=state.location_status),
]),
appui.Section("通知", [
appui.Button("申请通知权限", action=request_notifications)
.button_style("bordered_prominent"),
appui.LabeledContent("状态", value=state.notification_status),
]),
appui.Section("批量", [
appui.Button("刷新全部状态", action=refresh_all),
appui.Text(state.message).foreground_color("secondaryLabel"),
]),
]).navigation_title("权限中心")
)
appui.run(body, state=state)
#API 参考
#速查
| API | 作用 |
|---|---|
status(module) | 查询单个模块 → dict |
request(module) | 申请权限 → dict(仅 location / notifications) |
status_all() | 批量查询当前 Bridge 支持的模块 |
MODULES | 规划中的统一权限键名列表 |
#查询
status(module) — 查询单个模块,不弹窗。
entry = permission.status("location")
if entry.get("authorized"):
...
常见返回字段:
| 字段 | 说明 |
|---|---|
success | 是否查询成功 |
module | 模块键名 |
status | 状态字符串(各模块含义不同) |
authorized | 是否视为已授权 → 优先看这个 |
error | 失败时的错误信息 |
定位常见 status:authorized_when_in_use、authorized_always、denied、not_determined。通知常见:authorized、denied、provisional。
status_all() — 返回 Bridge 当前支持的模块列表:
result = permission.status_all()
for item in result.get("modules", []):
print(item["module"], item["status"], item["authorized"])
返回结构:{"success": True, "modules": [{"module": "...", "status": "...", "authorized": bool}, ...]}。按 module 字段查找,不是以模块名为 key 的扁平字典。
#申请
request(module) — 触发系统授权。目前仅支持:
| 模块键 | 行为 |
|---|---|
location | 弹出「使用期间」定位授权;立即返回 {"action": "requested"},需再查 status |
notifications | 弹出通知授权;等待用户选择,返回含 granted 的结果 |
# 定位:申请后需再查询
permission.request("location")
entry = permission.status("location")
# 通知:可直接看 granted
result = permission.request("notifications")
if result.get("granted"):
...
对其他键(如 camera、photos、contacts)调用 request() 会返回 permission_request_not_supported。请改用业务模块,例如 notification.request_permission()、location.request_access()、photos.pick_image() 首次调用时系统会自动弹窗。
#MODULES 与运行时支持
MODULES 是统一键名规划,完整列表:
import permission
print(permission.MODULES)
当前 Bridge 已接通的范围:
| 键名 | status | request | 备注 |
|---|---|---|---|
location | ✅ | ✅ | |
notifications | ✅ | ✅ | 不是 notification |
health | ✅ | ❌ | 用 health 按数据类型申请 |
motion / speech | ✅ | ❌ | 返回 available 占位状态 |
camera / photos / contacts 等 | ❌ | ❌ | 用对应业务模块 |
#常见错误
| 错误写法 | 后果 | 修正 |
|---|---|---|
permission.request("notification") | 键名错误 | 使用 notifications |
把 request() 返回值当 bool | 判断逻辑错误 | 看 authorized 或 granted 字段 |
对 camera 调 permission.request | 返回不支持 | 直接调 photos / camera 模块 |
在 body() 里请求权限 | 刷新时反复弹窗 | 放进按钮回调 |
用户拒绝后反复 request | 体验差、仍拿不到权限 | 展示状态并引导去系统设置 |
#相关文档
| 文档 | 用途 |
|---|---|
| location | 定位权限与坐标读取 |
| notification | 通知权限与本地提醒 |
| photos | 相册访问与选图 |
| health | HealthKit 按类型授权 |
| 原生能力入口 | MiniApp 场景配方 |
#预期效果
运行示例后,界面应出现文档描述的目标结果;若与预期不符,先看「失败路径」并按返回值或日志排查。