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

Jetpack Compose中使用DownloadManager下载图片无响应问题排查

Jetpack Compose中DownloadManager下载图片无响应的修复方案

问题背景

在基于Jetpack Compose的Kotlin应用中,使用AsyncImage加载图片后,实现了下载按钮期望通过DownloadManager将图片保存到外部存储。但点击按钮无任何反应,权限已在AndroidManifest.xml配置,权限申请流程正常,无报错信息但图片未成功下载。

代码中的核心错误

  • 下载函数仅定义未调用:在按钮点击逻辑中,只是重新定义了downloading函数签名,并未实际调用已实现的下载逻辑,导致下载代码根本没执行。
  • 权限判断逻辑重复且冗余:Android 10(API 29)及以上版本无需WRITE_EXTERNAL_STORAGE权限(Manifest中已设置maxSdkVersion="28"),但代码中仍做了不必要的权限检查;且两个else if的判断条件完全一致,永远不会触发权限申请流程。
  • 权限授权后未触发下载:权限申请成功的回调中仅打印日志,未调用下载函数,用户授权后仍无法执行下载。
  • 文件名缺失图片后缀:下载时设置的文件名仅用时间戳,无图片后缀(如.png、.jpg),可能导致系统无法识别文件类型。

修复后的完整代码

1. 权限申请Launcher与按钮逻辑

val requestPermissionLauncher = rememberLauncherForActivityResult(
    ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
    if (isGranted) {
        Log.i("Permission: ", "Granted")
        // 权限授权成功后立即执行下载
        downloading(link, title, context)
        Toast.makeText(context, "开始下载", Toast.LENGTH_SHORT).show()
    } else {
        Log.i("Permission: ", "Denied")
        Toast.makeText(context, "权限被拒绝,无法下载", Toast.LENGTH_SHORT).show()
    }
}

IconButton(
    onClick = {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            // Android 10及以上无需WRITE_EXTERNAL_STORAGE权限,直接下载
            downloading(link, title, context)
            Toast.makeText(context, "开始下载", Toast.LENGTH_SHORT).show()
        } else {
            // Android 9及以下,检查WRITE_EXTERNAL_STORAGE权限
            if (ContextCompat.checkSelfPermission(
                    context,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
                ) == PackageManager.PERMISSION_GRANTED
            ) {
                downloading(link, title, context)
                Toast.makeText(context, "开始下载", Toast.LENGTH_SHORT).show()
            } else {
                // 申请权限
                requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
            }
        }
    }
) {
    Icon(
        Icons.Outlined.ArrowDropDown,
        contentDescription = "下载按钮",
    )
}

2. 修复后的下载函数

fun downloading(imageLink: String, title: String, context: Context) {
    // 从图片链接提取后缀,若链接无后缀可手动指定(如".jpg")
    val fileExtension = imageLink.substringAfterLast(".", fallback = ".jpg")
    val request = DownloadManager.Request(Uri.parse(imageLink))
        .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
        .setTitle(title)
        .setDescription("正在下载图片")
        .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
        .setDestinationInExternalPublicDir(
            Environment.DIRECTORY_DOWNLOADS,
            "${System.currentTimeMillis()}$fileExtension"
        )

    val manager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
    manager.enqueue(request)
}

3. AndroidManifest.xml权限配置(保持原配置即可)

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER" />

额外说明

  • 若图片链接无明确后缀,可根据AsyncImage加载的图片类型手动指定后缀,或通过网络请求获取文件MIME类型后转换为对应后缀。
  • 下载完成后,系统会发送通知,用户可直接从通知跳转到下载目录查看图片。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 21:15:33