From 44c020c7c2f3d13974c7ad2a486b43782e5d909f Mon Sep 17 00:00:00 2001 From: MNCHL <152583790+MNCHL@users.noreply.github.com> Date: Wed, 27 Dec 2023 20:45:40 +0800 Subject: [PATCH] Update UpdateManager.kt --- .../java/org/yuzu/yuzu_emu/UpdateManager.kt | 191 ++++++++---------- 1 file changed, 83 insertions(+), 108 deletions(-) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/UpdateManager.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/UpdateManager.kt index 66e3642a2..80786606f 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/UpdateManager.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/UpdateManager.kt @@ -1,148 +1,123 @@ package org.yuzu.yuzu_emu -import android.app.AlertDialog -import android.app.DownloadManager import android.content.Context import android.content.Intent -import android.content.pm.PackageManager import android.net.Uri -import android.os.Environment +import android.os.Build +import android.util.Log import android.widget.Toast -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch +import androidx.appcompat.app.AlertDialog +import androidx.core.content.FileProvider +import kotlinx.coroutines.* +import okhttp3.* import org.json.JSONObject -import java.io.BufferedReader -import java.io.InputStreamReader -import java.net.HttpURLConnection +import java.io.* import java.net.URL -class UpdateManager(private val context: Context) { +object UpdateManager { - private companion object { - private const val CONFIG_URL = "https://your-server.com/api/config" - } + private val client = OkHttpClient() - fun checkForUpdates() { + fun checkAndInstallUpdate(context: Context) { GlobalScope.launch(Dispatchers.IO) { - try { - val configJson = fetchConfigFromServer(CONFIG_URL) - if (configJson != null) { - val jsonObject = JSONObject(configJson) - val updateDialogTitle = jsonObject.optString("updateDialogTitle") - val updateDialogMessage = jsonObject.optString("updateDialogMessage") - val versionName = jsonObject.optString("versionName") - val downloadUrl = jsonObject.optString("downloadUrl") + val currentVersion = context.packageManager + .getPackageInfo(context.packageName, 0).versionName + val latestVersion = getLatestVersionFromServer() - if (isNewVersionAvailable(versionName)) { - showUpdateDialog(updateDialogTitle, updateDialogMessage, downloadUrl) - } else { - showNoUpdateAvailableMessage() - } + withContext(Dispatchers.Main) { + if (isUpdateAvailable(currentVersion, latestVersion)) { + showUpdateDialog(context) } else { - showErrorToast() + showNoUpdateMessage(context) } - } catch (e: Exception) { - showErrorToast() } } } - private fun fetchConfigFromServer(urlString: String): String? { - var connection: HttpURLConnection? = null - var reader: BufferedReader? = null + private suspend fun getLatestVersionFromServer(): String { + val request = Request.Builder() + .url("http://mkoc.cn/aip/version.php") + .build() return try { - val url = URL(urlString) - connection = url.openConnection() as HttpURLConnection - connection.requestMethod = "GET" - connection.connect() - - if (connection.responseCode == HttpURLConnection.HTTP_OK) { - reader = BufferedReader(InputStreamReader(connection.inputStream)) - val stringBuilder = StringBuilder() - var line: String? - while (reader.readLine().also { line = it } != null) { - stringBuilder.append(line).append("\n") - } - stringBuilder.toString() - } else { - null - } - } finally { - reader?.close() - connection?.disconnect() + val response = client.newCall(request).execute() + val responseBody = response.body?.string() ?: "" + JSONObject(responseBody).getString("versionName") + } catch (e: IOException) { + Log.e("UpdateManager", "检查更新时出错: ${e.message}") + "" } } - private fun isNewVersionAvailable(serverVersionName: String): Boolean { - try { - val currentVersionName = context.packageManager - .getPackageInfo(context.packageName, 0).versionName - return serverVersionName.compareTo(currentVersionName) > 0 - } catch (e: PackageManager.NameNotFoundException) { - return false - } + private fun isUpdateAvailable(currentVersion: String, latestVersion: String): Boolean { + return latestVersion > currentVersion } - private fun showUpdateDialog(title: String, message: String, downloadUrl: String) { + private fun showUpdateDialog(context: Context) { AlertDialog.Builder(context) - .setTitle(title) - .setMessage(message) + .setTitle("有新版本可用") + .setMessage("有新版本可用。现在更新吗?") .setPositiveButton("更新") { dialog, which -> - downloadLatestVersion(downloadUrl) + downloadAndInstallUpdate(context) + } + .setNegativeButton("稍后") { dialog, which -> + // 处理稍后更新的逻辑 } - .setNegativeButton("稍后", null) .show() } - private fun showNoUpdateAvailableMessage() { + private fun showNoUpdateMessage(context: Context) { Toast.makeText(context, "您的应用已经是最新版本。", Toast.LENGTH_SHORT).show() } - private fun showErrorToast() { - Toast.makeText(context, "无法获取配置信息", Toast.LENGTH_SHORT).show() - } + private fun downloadAndInstallUpdate(context: Context) { + val downloadUrl = "http://mkoc.cn/app/yuzu.apk" + val request = Request.Builder() + .url(downloadUrl) + .build() - private fun downloadLatestVersion(downloadUrl: String) { - val request = DownloadManager.Request(Uri.parse(downloadUrl)) - .setTitle("应用更新") - .setDescription("正在下载新版本") - .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) - .setDestinationInExternalPublicDir( - Environment.DIRECTORY_DOWNLOADS, - "app-update.apk" - ) - - val downloadManager = - context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager - downloadManager.enqueue(request) - } - - fun installLatestVersion(downloadId: Long) { - val downloadManager = - context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager - - val query = DownloadManager.Query().apply { - setFilterById(downloadId) - } - - val cursor = downloadManager.query(query) - if (cursor.moveToFirst()) { - val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) - if (status == DownloadManager.STATUS_SUCCESSFUL) { - val uri = Uri.parse( - cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)) - ) - val intent = Intent(Intent.ACTION_VIEW).apply { - setDataAndType(uri, "application/vnd.android.package-archive") - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - } - context.startActivity(intent) - } else if (status == DownloadManager.STATUS_FAILED) { - showErrorToast() + client.newCall(request).enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + Log.e("UpdateManager", "下载失败: ${e.message}") + // 处理下载失败 } + + override fun onResponse(call: Call, response: Response) { + if (response.isSuccessful) { + val apkFile = File(context.getExternalFilesDir(null), "update.apk") + val inputStream = response.body?.byteStream() + + try { + inputStream?.use { input -> + apkFile.outputStream().use { output -> + input.copyTo(output) + } + } + installUpdate(context, apkFile) + } catch (e: IOException) { + Log.e("UpdateManager", "复制文件时出错: ${e.message}") + // 处理文件复制错误 + } + } else { + Log.e("UpdateManager", "下载失败: HTTP ${response.code()}") + // 处理下载失败 + } + } + }) + } + + private fun installUpdate(context: Context, apkFile: File) { + val uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + FileProvider.getUriForFile(context, context.packageName + ".provider", apkFile) + } else { + Uri.fromFile(apkFile) } + + val installIntent = Intent(Intent.ACTION_INSTALL_PACKAGE) + installIntent.data = uri + installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + + context.startActivity(installIntent) } }