diff --git a/web/device_agent_api.py b/web/device_agent_api.py index 357ac93..82c0b0b 100644 --- a/web/device_agent_api.py +++ b/web/device_agent_api.py @@ -162,6 +162,48 @@ def api_dev_agent_apk(apk_id): mimetype="application/vnd.android.package-archive") +@bp.route("/api/device/agent/install", methods=["POST"]) +def api_dev_agent_install(): + """设备请求**平台**帮它装这个应用(平台走 adb,静默,没有系统安装框)。 + + 为什么这么设计:普通 App 自己调系统安装器,MIUI 上要过「继续 → 勾选未检测 + → 继续更新」甚至 ICP 备案检查好几步;而 `adb install` 在同一台设备上实测是 + **静默**的(升级 2.7s、全新安装 7.9s,零弹框)。 + + 所以设备端商店的「安装/更新」按钮走这里:**用户还是在手机上选**(应用商店体验), + 真正干活的是平台,几秒钟装完。万一 adb 被 MIUI 拦了,返回 ok=false, + 设备端自己退回本地安装(有弹框,但至少能装)。 + """ + deny = _deny() + if deny: + return deny + data = request.json or {} + apk_id = str(data.get("apk_id", "")) + if not apk_id: + return jsonify({"ok": False, "error": "缺少 apk_id"}), 400 + + fp, serial, name, known = _identify() + if not serial: + return jsonify({"ok": False, "error": "无法识别设备"}), 400 + if not known: + return jsonify({"ok": False, "error": "这台设备还没登记进平台设备池"}), 409 + + from core.models import ApkFile + if not ApkFile.query.get(apk_id): + return jsonify({"ok": False, "error": "apk not found"}), 404 + + from web import context + try: + ok, msg = context.apk_mgr.install(apk_id, [serial]) + except Exception as e: + _log.error("设备端请求安装失败: %s", e) + return jsonify({"ok": False, "error": "平台安装任务启动失败"}), 500 + _log.info("设备端请求安装: %s(%s) apk=%s -> %s", name or "未登记", serial, apk_id, msg) + if not ok: + return jsonify({"ok": False, "error": msg}), 400 + return jsonify({"ok": True, "msg": msg, "serial": serial}) + + @bp.route("/api/device/agent/report", methods=["POST"]) def api_dev_agent_report(): """设备上报下载/安装结果,平台侧留下记录(应用管理页可见)。