Android 使用DownloadManager进行版本更新的完整方案
2025-09-17 21:25
Android开发
153
0
0
0
标题录入
封面图
在 Android 中使用 `DownloadManager` 实现版本更新是一个常见且推荐的做法,尤其适用于需要后台下载、支持断点续传、系统管理的场景。以下是一个完整的方案,涵盖从检测新版本到下载、安装的全过程。 --- ## ✅ 一、项目结构概览 ``` - MainActivity.kt - DownloadService.kt (可选) - UpdateChecker.kt - DownloadReceiver.kt - UpdateUtils.kt ``` --- ## ✅ 二、实现步骤 ### 1. **检查新版本(UpdateChecker.kt)** ```kotlin object UpdateChecker { private const val UPDATE_URL = "https://yourdomain.com/update.json" fun checkForUpdate(context: Context, callback: (Boolean, String, String) -> Unit) { val queue = Volley.newRequestQueue(context) val request = JsonObjectRequest(Request.Method.GET, UPDATE_URL, null, { response -> try { val latestVersionCode = response.getInt("versionCode") val currentVersionCode = context.packageManager.getPackageInfo(context.packageName, 0).versionCode val downloadUrl = response.getString("downloadUrl") if (latestVersionCode > currentVersionCode) { callback(true, downloadUrl, response.getString("versionName")) } else { callback(false, "", "") } } catch (e: Exception) { e.printStackTrace() callback(false, "", "") } }, { error -> error.printStackTrace() callback(false, "", "") }) queue.add(request) } } ``` > **说明**:你需要一个 JSON 文件来返回最新版本信息,例如: ```json { "versionCode": 2, "versionName": "v2.0", "downloadUrl": "https://yourdomain.com/app-release.apk" } ``` --- ### 2. **使用 DownloadManager 下载 APK(DownloadUtils.kt)** ```kotlin object DownloadUtils { fun startDownload(context: Context, url: String, title: String, description: String) { val request = DownloadManager.Request(Uri.parse(url)) request.setTitle(title) request.setDescription(description) request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "app-update.apk") val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager downloadManager.enqueue(request) } } ``` --- ### 3. **监听下载状态(DownloadReceiver.kt)** ```kotlin class DownloadReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1) if (id == -1) return val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager val query = DownloadManager.Query().setFilterById(id) val cursor = downloadManager.query(query) if (cursor.moveToFirst()) { val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) when (status) { DownloadManager.STATUS_SUCCESSFUL -> { val uri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)) installApk(context, Uri.parse(uri)) } DownloadManager.STATUS_FAILED -> { Toast.makeText(context, "下载失败", Toast.LENGTH_SHORT).show() } } } cursor.close() } private fun installApk(context: Context, uri: Uri) { val intent = Intent(Intent.ACTION_VIEW) intent.setDataAndType(uri, "application/vnd.android.package-archive") intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) context.startActivity(intent) } } ``` > **注意**:为了接收广播,需要在 `AndroidManifest.xml` 中注册这个 Receiver: ```xml <receiver android:name=".DownloadReceiver" /> ``` --- ### 4. **在 Activity 中触发下载** ```kotlin class MainActivity : AppCompatActivity() { private val downloadReceiver = DownloadReceiver() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) UpdateChecker.checkForUpdate(this) { hasUpdate, url, versionName -> if (hasUpdate) { // 显示提示对话框或通知用户有新版本 val dialog = AlertDialog.Builder(this) .setTitle("发现新版本 $versionName") .setMessage("是否立即更新?") .setPositiveButton("更新") { _, _ -> DownloadUtils.startDownload(this, url, "App Update", "正在下载最新版本...") } .setNegativeButton("稍后") { _, _ -> } .create() dialog.show() } } } override fun onResume() { super.onResume() registerReceiver(downloadReceiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) } override fun onPause() { super.onPause() unregisterReceiver(downloadReceiver) } } ``` --- ## ✅ 三、权限声明(AndroidManifest.xml) ```xml <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> ``` > 注意:从 Android 10 开始,`WRITE_EXTERNAL_STORAGE` 权限被限制,建议使用 `Context.getExternalFilesDir()` 或 `MediaStore`。 --- ## ✅ 四、注意事项 | 事项 | 说明 | |------|------| | **APK 安装权限** | 需要添加 `MANAGE_EXTERNAL_STORAGE` 权限(如果目标 API >= 30) | | **大文件下载** | 使用 `DownloadManager` 可以处理大文件,并支持断点续传 | | **后台下载** | `DownloadManager` 在后台运行,即使应用退出也能继续下载 | | **安全性** | 建议对 APK 进行签名验证,防止下载到恶意文件 | --- ## ✅ 五、扩展功能建议 - 添加进度条显示下载进度(需监听 `DownloadManager` 的状态) - 支持多语言和国际化 - 加密下载链接,防止未授权访问 - 自定义下载路径(如内部存储) --- ## ✅ 六、完整示例代码结构(简化版) ```kotlin // UpdateChecker.kt object UpdateChecker { fun checkForUpdate(context: Context, callback: (Boolean, String, String) -> Unit) { ... } } // DownloadUtils.kt object DownloadUtils { fun startDownload(context: Context, url: String, title: String, description: String) { ... } } // DownloadReceiver.kt class DownloadReceiver : BroadcastReceiver() { ... } // MainActivity.kt class MainActivity : AppCompatActivity() { override fun onCreate(...) { UpdateChecker.checkForUpdate(this) { hasUpdate, url, name -> if (hasUpdate) { showUpdateDialog(url, name) } } } } ``` --- ## ✅ 七、参考文档 - [Android DownloadManager 官方文档](https://developer.android.com/reference/android/app/DownloadManager) - [Volley 网络请求库](https://developer.android.com/training/volley) - [Android Permissions](https://developer.android.com/guide/topics/security/permissions) --- 如果你需要我帮你生成一个完整的 Android Studio 项目模板或者打包成 Gradle 模块,也可以告诉我!
上一篇:
Android ActionBar-左上角icon设置和事件配置
下一篇:
Android 二维码 生成和识别
标题录入,一次不能超过6条
蝴蝶效应
T:0.006668s,M:123.8 KB
返回顶部
留言
留言
评论