You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用NanoHTTPD实现已安装应用的APK提取与下载功能

实现APK下载功能的修改方案

你需要调整两部分逻辑:一是修改下载链接的规则,二是新增下载请求的处理逻辑。

1. 修正应用列表的链接格式

原来的href直接使用应用名作为路径,无法匹配到对应APK,调整为带包名参数的下载路径:

// 原列表生成代码替换为以下逻辑
answer += "<a href=\"/download?pkg=" + file.getPackageName() + "\" alt = \"\">" + file.getAppName() + "</a><br>";

2. 新增下载请求处理逻辑

在NanoHTTPD的GET请求判断分支中,先匹配下载请求路径,读取对应APK文件返回,完整的请求处理逻辑如下:

if (method.equals(Method.GET)) {
    String uri = session.getUri();
    // 处理下载请求
    if (uri.startsWith("/download")) {
        String pkgName = session.getParms().get("pkg");
        if (pkgName == null || pkgName.isEmpty()) {
            return newFixedLengthResponse(Response.Status.BAD_REQUEST, "text/plain", "无效请求参数");
        }
        // 匹配对应应用的APK路径
        App targetApp = null;
        for (App app : apps) {
            if (app.getPackageName().equals(pkgName)) {
                targetApp = app;
                break;
            }
        }
        if (targetApp == null) {
            return newFixedLengthResponse(Response.Status.NOT_FOUND, "text/plain", "未找到对应应用");
        }
        File apkFile = new File(targetApp.getApkPath());
        if (!apkFile.exists()) {
            return newFixedLengthResponse(Response.Status.NOT_FOUND, "text/plain", "APK文件不存在");
        }
        // 返回APK文件流触发下载
        try {
            FileInputStream fis = new FileInputStream(apkFile);
            Response response = newFixedLengthResponse(Response.Status.OK, "application/vnd.android.package-archive", fis, apkFile.length());
            // 处理中文文件名乱码问题
            String fileName = URLEncoder.encode(targetApp.getAppName() + ".apk", "UTF-8").replaceAll("\\+", "%20");
            response.addHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName);
            return response;
        } catch (Exception e) {
            e.printStackTrace();
            return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, "text/plain", "文件读取失败");
        }
    }
    // 原有应用列表返回逻辑
    StringBuilder answer = new StringBuilder("<html><body><h3>已安装应用列表</h3>");
    for (App file : apps) {
        answer.append("<a href=\"/download?pkg=")
              .append(file.getPackageName())
              .append("\">")
              .append(file.getAppName())
              .append("</a><br>");
    }
    answer.append("</body></html>");
    return newFixedLengthResponse(Response.Status.OK, "text/html", answer.toString());
}

注意事项

  • 你原有代码中packageManager.getInstalledApplications(PackageManager.GET_META_DATA;缺少右括号,修正为packageManager.getInstalledApplications(PackageManager.GET_META_DATA);
  • 不需要额外申请存储权限,系统默认允许应用读取已安装应用的APK源文件路径
  • 文件名编码处理已适配中文场景,避免下载时文件名乱码

内容的提问来源于stack exchange,提问作者jcooli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 16:57:02