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

Android 11中用Java下载NASA图片遇问题,寻求技术解决方案

问题解决指南

一、DownloadManager无响应问题

你的DownloadManager代码没反应,核心原因是指定的目标是目录而非具体文件,DownloadManager需要明确的文件路径才能完成下载。结合Android 11特性,调整代码如下:

private void download(String url) {
    DownloadManager manager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
    
    // 从URL提取文件名
    String fileName = url.substring(url.lastIndexOf("/") + 1);
    // 生成应用私有外部存储下的具体文件路径
    File targetFile = new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), fileName);
        
    DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
    request.setDestinationUri(Uri.fromFile(targetFile));
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
    // 添加网络类型限制(可选,确保在合适网络下下载)
    request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
    
    // 入队并记录下载ID(可选,用于后续查询状态)
    long downloadId = manager.enqueue(request);
}

补充检查点:

  • Android 11及以上访问应用私有外部存储无需WRITE_EXTERNAL_STORAGE权限,你的Manifest配置没问题;如果要下载到系统公共Downloads目录,需要申请MANAGE_EXTERNAL_STORAGE权限(需引导用户手动授权),建议优先用应用私有存储避免权限流程繁琐。

二、流下载路径不符合预期问题

你当前代码把文件存在应用私有外部存储的DCIM目录(/data/com.example.myapp/DCIM/),如果想存到系统公共DCIM目录(相册可识别的位置),由于Android 11启用Scoped Storage,不能直接用File对象写入公共目录,需通过MediaStore实现:

private void downloadToPublicDCIM(String title, String url) throws IOException {
    URL u = new URL(url);
    HttpURLConnection connect = (HttpURLConnection) u.openConnection();

    if (connect.getResponseCode() != HttpURLConnection.HTTP_OK) {
        Log.w("ERROR", "服务器返回HTTP状态码:" + connect.getResponseCode());
        return;
    }

    // 准备MediaStore插入信息
    ContentValues values = new ContentValues();
    values.put(MediaStore.Images.Media.DISPLAY_NAME, title);
    values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
    // Android Q及以上设置相对路径到公共DCIM
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM + "/NASA_APOD");
        values.put(MediaStore.Images.Media.IS_PENDING, 1);
    }

    // 获取ContentResolver插入Uri
    ContentResolver resolver = getContentResolver();
    Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
    if (imageUri == null) {
        Log.e("ERROR", "无法获取公共目录写入Uri");
        return;
    }

    // 写入文件
    try (InputStream is = connect.getInputStream();
         OutputStream os = resolver.openOutputStream(imageUri)) {
        byte[] bytes = new byte[1024];
        int b;
        while ((b = is.read(bytes)) != -1) {
            os.write(bytes, 0, b);
        }

        // Android Q及以上标记文件为已完成
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            values.clear();
            values.put(MediaStore.Images.Media.IS_PENDING, 0);
            resolver.update(imageUri, values, null, null);
        }
    } catch (IOException e) {
        // 写入失败时删除插入的记录
        resolver.delete(imageUri, null, null);
        throw e;
    } finally {
        connect.disconnect();
    }
}

注意事项:

  • Android 10及以上版本无需申请WRITE_EXTERNAL_STORAGE权限,系统自动处理权限逻辑。
  • 写入的文件会出现在系统相册的DCIM/NASA_APOD文件夹下,符合公共存储的预期位置。

额外建议

  • 流下载必须放在子线程执行,避免阻塞主线程(可使用Coroutine、ExecutorService或AsyncTask),否则会触发NetworkOnMainThreadException。
  • 可添加下载进度监听逻辑,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 07:56:25