在Android Studio中使用Kotlin开发音乐播放器如何添加在线歌曲下载功能
Kotlin 实现Android音乐文件下载功能指导
前置配置:添加必要权限
首先在AndroidManifest.xml中添加下载需要的基础权限:
<!-- 网络访问权限 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- 网络状态监测权限 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- Android 13及以上读取音频文件权限 --> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> <!-- Android 12及以上前台服务权限(如果需要后台下载保活) --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" /> <!-- Android 9及以下存储写入权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
实现方案选择
方案1:系统DownloadManager实现(新手首选)
系统原生提供的下载服务,自动处理断点续传、网络切换、下载通知,不需要手动处理线程逻辑,代码量极小。
Kotlin示例代码:
fun downloadMusic(context: Context, musicUrl: String, musicName: String) { val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager val uri = Uri.parse(musicUrl) val request = DownloadManager.Request(uri).apply { // 设置下载后文件存储到公共Music目录 setDestinationInExternalPublicDir(Environment.DIRECTORY_MUSIC, "$musicName.mp3") // 设置通知栏显示内容 setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) setTitle("正在下载:$musicName") // 允许移动网络下载,不需要的话可以改成NETWORK_WIFI setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE) } // 保存下载id,后续可以用来查询下载状态 val downloadId = downloadManager.enqueue(request) }
如果需要监听下载完成,注册广播接收器即可:
val downloadReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1) // 匹配你之前保存的downloadId,确认是目标歌曲下载完成 if (id == yourSavedDownloadId) { // 处理下载完成逻辑,比如更新本地歌曲列表 } } } // 注册广播 registerReceiver(downloadReceiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
方案2:OkHttp自定义下载(适合需要自定义逻辑/进度监听的场景)
如果需要自己控制下载流程、实时获取下载进度,可以用OkHttp配合Kotlin协程实现。
首先在Module级build.gradle中添加依赖:
dependencies { implementation 'com.squareup.okhttp3:okhttp:4.11.0' // 协程相关依赖 implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3' }
Kotlin协程下载示例代码:
suspend fun downloadMusicWithProgress(musicUrl: String, savePath: String, onProgress: (Int) -> Unit): Boolean { return withContext(Dispatchers.IO) { val request = okhttp3.Request.Builder().url(musicUrl).build() val response = OkHttpClient().newCall(request).execute() if (!response.isSuccessful) return@withContext false val totalSize = response.body?.contentLength() ?: 0L val inputStream = response.body?.byteStream() ?: return@withContext false val outputStream = FileOutputStream(savePath) val buffer = ByteArray(8192) var downloadedSize = 0L var len: Int while (inputStream.read(buffer).also { len = it } != -1) { outputStream.write(buffer, 0, len) downloadedSize += len // 计算进度回调 val progress = (downloadedSize * 100 / totalSize).toInt() withContext(Dispatchers.Main) { onProgress(progress) } } outputStream.flush() inputStream.close() outputStream.close() return@withContext true } }
调用示例:
// 启动协程执行下载 lifecycleScope.launch { val savePath = getExternalFilesDir(Environment.DIRECTORY_MUSIC)?.absolutePath + "/test.mp3" val success = downloadMusicWithProgress("你的歌曲下载链接", savePath) { progress -> // 更新UI显示下载进度 progressBar.progress = progress } if (success) { // 下载成功处理 } }
关键注意事项
- 分区存储适配:Android 10及以上建议将下载的音乐存到公共
Music目录,不需要额外申请存储权限,系统媒体库可以直接扫描到文件。 - 异步处理:所有下载逻辑必须放在异步线程/协程中执行,禁止在主线程做网络和文件IO操作,避免触发ANR。
- 下载完成后需要通知媒体库更新,调用以下代码即可让系统扫描到你下载的歌曲:
MediaScannerConnection.scanFile(context, arrayOf(saveFilePath), null, null)
内容的提问来源于stack exchange,提问作者Perseus
相关产品推荐
相关产品推荐

