Bladeren bron

1.app版本自升级功能:下载前判断文件管理中的的apk包是否匹配,不匹配的话先删除再开始下载
2.app版本自升级功能:修复下载完成时应用收不到广播的问题(应用在后台时收不到)

songchengcheng 2 weken geleden
bovenliggende
commit
aa0d1de50e

+ 12 - 278
app/src/main/java/com/sikey/interconnect/component/network/http/UpdateManager.kt

@@ -1,169 +1,4 @@
 package com.sikey.interconnect.component.network.http
-/*
-
-import android.app.AlertDialog
-import android.app.DownloadManager
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.content.IntentFilter
-import android.net.Uri
-import android.os.Build
-import android.os.Environment
-import android.provider.Settings
-import androidx.activity.ComponentActivity
-import androidx.core.content.FileProvider
-import com.sikey.interconnect.component.log.Logger
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import java.io.File
-
-object UpdateManager {
-    private val TAG = UpdateManager::class.java.simpleName
-    private var downloadId: Long = -1L
-    private lateinit var downloadManager: DownloadManager
-    private var isReceiverRegistered = false
-
-    // 初始化 DownloadManager 和广播接收器
-    fun initialize(context: Context) {
-        downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
-        if (!isReceiverRegistered) {
-            registerDownloadReceiver(context)
-        }
-    }
-
-    // 检查更新
-*/
-/*    fun checkForUpdate(context: Context, onUpdateAvailable: (UpdateInfo) -> Unit) {
-        CoroutineScope(Dispatchers.IO).launch {
-            try {
-                val response = RetrofitClient.apiService.getUpdateInfo()
-                if (response.isSuccessful) {
-                    val updateInfo = response.body()
-                    updateInfo?.let {
-                        val currentVersion = getCurrentVersionCode(context)
-                        if (it.versionCode > currentVersion) {
-                            withContext(Dispatchers.Main) {
-                                onUpdateAvailable(it)
-                            }
-                        }
-                    }
-                }
-            } catch (e: Exception) {
-                withContext(Dispatchers.Main) {
-                    showToast(context, "检查更新失败: ${e.message}")
-                }
-            }
-        }
-    }*//*
-
-
-    // 显示更新对话框
-*/
-/*    fun showUpdateDialog(context: Context, updateInfo: UpdateInfo) {
-        val builder = AlertDialog.Builder(context)
-        builder.setTitle("发现新版本 ${updateInfo.versionName}")
-        builder.setMessage(updateInfo.updateLog)
-        builder.setPositiveButton("立即更新") { _, _ ->
-            downloadAndInstall(context, updateInfo.downloadUrl)
-        }
-        if (!updateInfo.forceUpdate) {
-            builder.setNegativeButton("稍后") { dialog, _ -> dialog.dismiss() }
-        }
-        val dialog = builder.create()
-        dialog.setCancelable(!updateInfo.forceUpdate)
-        dialog.show()
-    }*//*
-
-
-    // 获取当前版本号
-    private fun getCurrentVersionCode(context: Context): Int {
-        return try {
-            context.packageManager.getPackageInfo(context.packageName, 0).versionCode
-        } catch (e: Exception) {
-            0
-        }
-    }
-
-    // 下载 APK
-    fun downloadAndInstall(context: Context, downloadUrl: String) {
-        Logger.d(TAG, "downloadAndInstall")
-        val request = DownloadManager.Request(Uri.parse(downloadUrl)).apply {
-            Logger.d(TAG, "downloadAndInstall 2")
-            setTitle("正在下载更新")
-            setDescription("下载 ${context.packageName} 新版本")
-            setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
-                setDestinationInExternalFilesDir(context, Environment.DIRECTORY_DOWNLOADS, "update.apk")
-            } else {
-                setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "update.apk")
-            }
-            setMimeType("application/vnd.android.package-archive")
-            setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
-            Logger.d(TAG, "downloadAndInstall 3")
-        }
-        downloadId = downloadManager.enqueue(request)
-    }
-
-    // 安装 APK
-    fun installApk(context: Context, apkFile: File) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-            if (!context.packageManager.canRequestPackageInstalls()) {
-                val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES)
-                    .setData(Uri.parse("package:${context.packageName}"))
-                if (context is ComponentActivity) {
-                    context.startActivity(intent)
-                }
-                return
-            }
-        }
-
-        val uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-            FileProvider.getUriForFile(context, "com.sikey.interconnect.download", apkFile)
-        } else {
-            Uri.fromFile(apkFile)
-        }
-
-        val intent = Intent(Intent.ACTION_VIEW)
-            .setDataAndType(uri, "application/vnd.android.package-archive")
-            .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
-            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-        context.startActivity(intent)
-    }
-
-    // 注册下载完成广播
-    private fun registerDownloadReceiver(context: Context) {
-        val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
-        context.registerReceiver(object : BroadcastReceiver() {
-            override fun onReceive(context: Context, intent: Intent) {
-                val id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
-                if (id == downloadId) {
-                    val query = DownloadManager.Query().setFilterById(id)
-                    downloadManager.query(query).use { cursor ->
-                        if (cursor.moveToFirst()) {
-                            val status = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS))
-                            if (status == DownloadManager.STATUS_SUCCESSFUL) {
-                                val uriString = cursor.getString(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_URI))
-                                val fileUri = Uri.parse(uriString)
-                                val file = File(fileUri.path ?: return)
-                                installApk(context, file)
-                            } else {
-                                showToast(context, "下载失败")
-                            }
-                        }
-                    }
-                }
-            }
-        }, filter, Context.RECEIVER_NOT_EXPORTED)
-        isReceiverRegistered = true
-    }
-
-    private fun showToast(context: Context, message: String) {
-        android.widget.Toast.makeText(context, message, android.widget.Toast.LENGTH_SHORT).show()
-    }
-}*/
 
 import android.Manifest
 import android.app.DownloadManager
@@ -186,7 +21,6 @@ import com.sikey.interconnect.component.network.http.model.UpdateAppRepo
 import com.sikey.interconnect.constant.UrlConstants.SK_TOOL_URL
 import com.sikey.interconnect.ui.avtivity.base.BaseNoActionBarActivity
 import com.sikey.interconnect.utils.ToastUtils
-import com.sikey.interconnect.utils.VersionUtils
 import kotlinx.coroutines.launch
 import retrofit2.Call
 import retrofit2.Callback
@@ -220,37 +54,11 @@ class UpdateManager {
         updateAppService = retrofit.create(UpdateAppService::class.java)
     }
 
-    // Check for new version
-/*    suspend fun checkForUpdate(currentVersion: String, updateUrl: String): UpdateInfo? {
-        return try {
-            withContext(Dispatchers.IO) {
-                val latestVersionInfo = URL(updateUrl).readText()
-                // Assuming updateUrl returns JSON with version and apkUrl
-                // Parse JSON to get version and download URL (simplified example)
-                val latestVersion = parseVersionFromJson(latestVersionInfo)
-                val apkUrl = parseApkUrlFromJson(latestVersionInfo)
-
-                if (isNewerVersion(currentVersion, latestVersion)) {
-                    UpdateInfo(latestVersion, apkUrl)
-                } else {
-                    null
-                }
-            }
-        } catch (e: Exception) {
-            null
-        }
-    }*/
-
-    // Start APK download and show notification
     fun startDownload(updateInfo: UpdateInfo) {
         val request = DownloadManager.Request(Uri.parse(updateInfo.apkUrl)).apply {
             setTitle("${mContext?.packageName}")
             setDescription("Downloading new version...")
-            //if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
-                setDestinationInExternalFilesDir(mContext, Environment.DIRECTORY_DOWNLOADS, DOWNLOADED_APK_FILENAME)
-/*            } else {
-                setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "app-update.apk")
-            }*/
+            setDestinationInExternalFilesDir(mContext, Environment.DIRECTORY_DOWNLOADS, DOWNLOADED_APK_FILENAME)
             setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
         }
 
@@ -266,19 +74,22 @@ class UpdateManager {
         if (file.exists()) {
             md5 = calculateMD5(file)
             Logger.d(TAG, "======== handleManualUpdate updateInfo.md5:${updateInfo.md5}, md5:$md5")
-        }
-        if (file.exists() && updateInfo.md5.equals(md5, ignoreCase = true)) {
-            Logger.d(TAG, "====== app-update.apk already exists")
-            showInstallDialog()
+            if (updateInfo.md5.equals(md5, ignoreCase = true)) {
+                Logger.d(TAG, "====== app-update.apk already exists")
+                showInstallDialog()
+            } else {
+                file.delete()
+                Logger.d(TAG, "====== app-update.apk not match, start downloading")
+                startDownload(updateInfo)
+                ToastUtils.showLongToast(R.string.update_app_start_downloading)
+            }
         } else {
             Logger.d(TAG, "====== no app-update.apk, start downloading")
-            //showInstallDialog()
             startDownload(updateInfo)
             ToastUtils.showLongToast(R.string.update_app_start_downloading)
         }
     }
 
-    // Notification with progress bar
     private fun showDownloadNotification(progress: Int) {
         val builder = mContext?.let {
             NotificationCompat.Builder(it, "update_channel").apply {
@@ -300,11 +111,6 @@ class UpdateManager {
         ) {
             // TODO: Consider calling
             //    ActivityCompat#requestPermissions
-            // here to request the missing permissions, and then overriding
-            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
-            //                                          int[] grantResults)
-            // to handle the case where the user grants the permission. See the documentation
-            // for ActivityCompat#requestPermissions for more details.
             return
         }
         if (builder != null) {
@@ -312,7 +118,6 @@ class UpdateManager {
         }
     }
 
-    // Register receiver to monitor download progress and completion
     private fun registerDownloadReceiver(context: Context) {
         val receiver = object : BroadcastReceiver() {
             override fun onReceive(context: Context, intent: Intent) {
@@ -364,61 +169,12 @@ class UpdateManager {
         }
 
         context.registerReceiver(receiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE),
-            Context.RECEIVER_NOT_EXPORTED)
+            Context.RECEIVER_EXPORTED)
         context.registerReceiver(receiver, IntentFilter(DownloadManager.ACTION_NOTIFICATION_CLICKED),
-            Context.RECEIVER_NOT_EXPORTED)
+            Context.RECEIVER_EXPORTED)
         isReceiverRegistered = true
     }
 
-    // Show install dialog
-/*    private fun showInstallDialog() {
-        val file = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "app-update.apk")
-        val uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-            mContext?.let { FileProvider.getUriForFile(it, "com.sikey.interconnect.download", file) }
-        } else {
-            Uri.fromFile(file)
-        }
-
-        val intent = Intent(Intent.ACTION_VIEW).apply {
-            setDataAndType(uri, "application/vnd.android.package-archive")
-            flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
-        }
-
-        val pendingIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
-        val builder = mContext?.let {
-            NotificationCompat.Builder(it, "update_channel").apply {
-                setSmallIcon(android.R.drawable.stat_sys_download_done)
-                setContentTitle("Update Downloaded")
-                setContentText("Tap to install the new version")
-                setPriority(NotificationCompat.PRIORITY_HIGH)
-                setContentIntent(pendingIntent)
-                setAutoCancel(true)
-            }
-        }
-
-        if (mContext?.let {
-                ActivityCompat.checkSelfPermission(
-                    it,
-                    Manifest.permission.POST_NOTIFICATIONS
-                )
-            } != PackageManager.PERMISSION_GRANTED
-        ) {
-            // TODO: Consider calling
-            //    ActivityCompat#requestPermissions
-            // here to request the missing permissions, and then overriding
-            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
-            //                                          int[] grantResults)
-            // to handle the case where the user grants the permission. See the documentation
-            // for ActivityCompat#requestPermissions for more details.
-            return
-        }
-        mContext?.let {
-            if (builder != null) {
-                NotificationManagerCompat.from(it).notify(notificationId, builder.build())
-            }
-        }
-    } */
-
     fun showInstallDialog() {
         Logger.d(TAG, "installApk")
         try {
@@ -453,28 +209,6 @@ class UpdateManager {
         }
     }
 
-    // Helper functions (implement these based on your needs)
-    private fun parseVersionFromJson(json: String): String {
-        // Parse JSON to extract version (e.g., "1.2.3")
-        return "1.2.3" // Placeholder
-    }
-
-    private fun parseApkUrlFromJson(json: String): String {
-        // Parse JSON to extract APK URL
-        return "https://example.com/app-update.apk" // Placeholder
-    }
-
-    private fun isNewerVersion(currentVersion: String, latestVersion: String): Boolean {
-        // Compare versions (e.g., "1.2.3" vs "1.2.4")
-        val currentParts = currentVersion.split(".").map { it.toInt() }
-        val latestParts = latestVersion.split(".").map { it.toInt() }
-        for (i in currentParts.indices) {
-            if (latestParts[i] > currentParts[i]) return true
-            if (latestParts[i] < currentParts[i]) return false
-        }
-        return false
-    }
-
     fun calculateMD5(file: File): String {
         val md = MessageDigest.getInstance("MD5")
 

+ 1 - 1
app/src/main/res/values-zh-rCN/strings.xml

@@ -1080,6 +1080,6 @@
     <string name="update_app_version">版本号</string>
     <string name="update_app_detail">优化相关功能,修复了若干问题</string>
     <string name="update_app_already_latest_ver">已是最新版本</string>
-    <string name="update_app_start_downloading">开始下载,请在通知栏查看进度</string>
+    <string name="update_app_start_downloading">开始下载,请在通知栏查看进度。下载完成前请勿退出应用</string>
 </resources>