- 버전 1.2.5 → 1.3.0 (versionCode 1130) - AppUpdateManager: versionCode로 업데이트 비교 - versionName 비교 로직 제거 - 더 정확한 업데이트 감지 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
172 lines
6.8 KiB
Kotlin
172 lines
6.8 KiB
Kotlin
package com.example.shiftalarm
|
|
|
|
import android.app.Activity
|
|
import android.app.ProgressDialog
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.net.Uri
|
|
import android.os.Build
|
|
import android.widget.Toast
|
|
import androidx.appcompat.app.AlertDialog
|
|
import androidx.core.content.FileProvider
|
|
import org.json.JSONObject
|
|
import java.io.BufferedInputStream
|
|
import java.io.File
|
|
import java.io.FileOutputStream
|
|
import java.net.HttpURLConnection
|
|
import java.net.URL
|
|
|
|
object AppUpdateManager {
|
|
|
|
private const val VERSION_URL = "https://git.webpluss.net/sanjeok77/ShiftRing/raw/branch/main/version.json"
|
|
|
|
fun checkUpdate(activity: Activity, silent: Boolean = false) {
|
|
val ctx = activity.applicationContext
|
|
val versionCheckUrl = "$VERSION_URL?t=${System.currentTimeMillis()}"
|
|
|
|
Thread {
|
|
try {
|
|
val url = URL(versionCheckUrl)
|
|
val connection = url.openConnection() as HttpURLConnection
|
|
connection.connectTimeout = 5000
|
|
connection.readTimeout = 5000
|
|
connection.requestMethod = "GET"
|
|
connection.useCaches = false
|
|
|
|
if (connection.responseCode == 200) {
|
|
val reader = connection.inputStream.bufferedReader()
|
|
val result = reader.readText()
|
|
reader.close()
|
|
|
|
val json = JSONObject(result)
|
|
val serverVersionCode = json.getInt("versionCode")
|
|
val serverVersionName = json.getString("versionName")
|
|
val apkUrl = json.getString("apkUrl")
|
|
val changelog = json.optString("changelog", "버그 수정 및 성능 향상")
|
|
|
|
val pInfo = ctx.packageManager.getPackageInfo(ctx.packageName, 0)
|
|
val currentVersionCode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
pInfo.longVersionCode.toInt()
|
|
} else {
|
|
@Suppress("DEPRECATION")
|
|
pInfo.versionCode
|
|
}
|
|
val currentVersionName = pInfo.versionName ?: "0.0.0"
|
|
|
|
if (serverVersionCode > currentVersionCode) {
|
|
activity.runOnUiThread {
|
|
showUpdateDialog(activity, serverVersionName, changelog, apkUrl)
|
|
}
|
|
} else if (!silent) {
|
|
activity.runOnUiThread {
|
|
Toast.makeText(ctx, "현재 최신 버전을 사용 중입니다. ($currentVersionName)", Toast.LENGTH_SHORT).show()
|
|
}
|
|
}
|
|
} else if (!silent) {
|
|
activity.runOnUiThread {
|
|
Toast.makeText(ctx, "서버 연결 실패", Toast.LENGTH_SHORT).show()
|
|
}
|
|
}
|
|
} catch (e: Exception) {
|
|
e.printStackTrace()
|
|
if (!silent) {
|
|
activity.runOnUiThread {
|
|
Toast.makeText(ctx, "업데이트 확인 중 오류 발생", Toast.LENGTH_SHORT).show()
|
|
}
|
|
}
|
|
}
|
|
}.start()
|
|
}
|
|
|
|
private fun showUpdateDialog(activity: Activity, version: String, changelog: String, apkUrl: String) {
|
|
com.google.android.material.dialog.MaterialAlertDialogBuilder(activity)
|
|
.setTitle("새로운 업데이트 발견 (v$version)")
|
|
.setMessage("업데이트 내용:\n$changelog\n\n지금 다운로드하시겠습니까?")
|
|
.setPositiveButton("다운로드") { _, _ ->
|
|
downloadAndInstallApk(activity, apkUrl, version)
|
|
}
|
|
.setNegativeButton("나중에", null)
|
|
.show()
|
|
}
|
|
|
|
private fun downloadAndInstallApk(activity: Activity, apkUrl: String, version: String) {
|
|
val progressDialog = ProgressDialog(activity).apply {
|
|
setTitle("업데이트 다운로드 중")
|
|
setMessage("v$version 다운로드 중...")
|
|
setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
|
|
setCancelable(false)
|
|
max = 100
|
|
show()
|
|
}
|
|
|
|
Thread {
|
|
try {
|
|
val url = URL(apkUrl)
|
|
val connection = url.openConnection() as HttpURLConnection
|
|
connection.connectTimeout = 15000
|
|
connection.readTimeout = 15000
|
|
connection.requestMethod = "GET"
|
|
connection.connect()
|
|
|
|
val fileLength = connection.contentLength
|
|
val inputStream = BufferedInputStream(connection.inputStream)
|
|
|
|
val apkFile = File(activity.cacheDir, "update.apk")
|
|
val outputStream = FileOutputStream(apkFile)
|
|
|
|
val buffer = ByteArray(8192)
|
|
var total: Long = 0
|
|
var count: Int
|
|
|
|
while (inputStream.read(buffer).also { count = it } != -1) {
|
|
total += count
|
|
outputStream.write(buffer, 0, count)
|
|
|
|
if (fileLength > 0) {
|
|
val progress = (total * 100 / fileLength).toInt()
|
|
activity.runOnUiThread {
|
|
progressDialog.progress = progress
|
|
}
|
|
}
|
|
}
|
|
|
|
outputStream.flush()
|
|
outputStream.close()
|
|
inputStream.close()
|
|
connection.disconnect()
|
|
|
|
activity.runOnUiThread {
|
|
progressDialog.dismiss()
|
|
installApk(activity, apkFile)
|
|
}
|
|
|
|
} catch (e: Exception) {
|
|
e.printStackTrace()
|
|
activity.runOnUiThread {
|
|
progressDialog.dismiss()
|
|
Toast.makeText(activity, "다운로드 실패: ${e.message}", Toast.LENGTH_LONG).show()
|
|
}
|
|
}
|
|
}.start()
|
|
}
|
|
|
|
private fun installApk(activity: Activity, apkFile: File) {
|
|
try {
|
|
val apkUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
FileProvider.getUriForFile(activity, "${activity.packageName}.provider", apkFile)
|
|
} else {
|
|
Uri.fromFile(apkFile)
|
|
}
|
|
|
|
val intent = Intent(Intent.ACTION_VIEW).apply {
|
|
setDataAndType(apkUri, "application/vnd.android.package-archive")
|
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
|
|
}
|
|
activity.startActivity(intent)
|
|
} catch (e: Exception) {
|
|
e.printStackTrace()
|
|
Toast.makeText(activity, "설치 실패: ${e.message}", Toast.LENGTH_LONG).show()
|
|
}
|
|
}
|
|
}
|