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

Android Studio开发应用商店:WebView下载APK完成后打开及找不到文件问题咨询

问题修复方案

无法找到下载文件的原因

  • 未动态申请存储权限,Android 6.0及以上系统默认拒绝存储写入权限,导致文件写入公共下载目录失败
  • 代码中写死了文件名为示例文本,没有提取下载链接对应的真实APK文件名,即使下载成功也无法对应到实际文件
  • 未适配高版本Android的存储权限规则

修复步骤

1. 补全AndroidManifest.xml配置

添加所需权限和FileProvider配置(Android 7.0+打开APK需要FileProvider适配):

<!-- 基础权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 存储权限,Android 13及以上无需申请 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- 安装APK所需权限 -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

<application ...>
    <!-- 配置FileProvider -->
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
</application>

在res/xml目录下新建file_paths.xml文件,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="download" path="Download/" />
</paths>

2. 动态申请存储权限

在Activity的onCreate方法中先检查并申请权限:

// 权限申请请求码
private static final int PERMISSION_REQUEST_CODE = 1001;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // 检查权限
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
        }
    }

    // 后续WebView初始化逻辑
}

3. 修正下载逻辑,解析真实文件名

修改DownloadListener中的代码,从contentDisposition中提取真实文件名,避免写死:

// 存储下载ID,后续接收广播时用
private long downloadId;

// WebView的DownloadListener实现
webview.setDownloadListener(new DownloadListener() {
    @Override
    public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
        // 解析文件名
        String fileName = URLUtil.guessFileName(url, contentDisposition, mimetype);
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
        request.allowScanningByMediaScanner();
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        // 传入解析得到的真实文件名
        request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
        DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
        // 保存下载ID
        downloadId = dm.enqueue(request);
        Toast.makeText(getApplicationContext(), "正在下载文件", Toast.LENGTH_LONG).show();
    }
});

4. 注册广播接收器,实现下载完成自动打开APK

在Activity中注册广播,监听下载完成事件:

private BroadcastReceiver downloadCompleteReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
        // 判断是不是我们发起的下载
        if (id == downloadId) {
            DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
            Uri downloadUri = dm.getUriForDownloadedFile(downloadId);
            if (downloadUri != null) {
                openApkFile(downloadUri);
            }
        }
    }
};

// 打开APK文件的方法
private void openApkFile(Uri apkUri) {
    Intent installIntent = new Intent(Intent.ACTION_VIEW);
    installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        // Android 7.0+使用FileProvider获取Uri
        String packageName = getPackageName();
        Uri contentUri = FileProvider.getUriForFile(this, packageName + ".fileprovider", new File(apkUri.getPath()));
        installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        installIntent.setDataAndType(contentUri, "application/vnd.android.package-archive");
    } else {
        installIntent.setDataAndType(apkUri, "application/vnd.android.package-archive");
    }
    startActivity(installIntent);
}

@Override
protected void onResume() {
    super.onResume();
    // 注册广播
    IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
    registerReceiver(downloadCompleteReceiver, filter);
}

@Override
protected void onPause() {
    super.onPause();
    // 注销广播
    unregisterReceiver(downloadCompleteReceiver);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 12:45:05