mirror of https://github.com/lizongying/my-tv.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
248 lines
9.2 KiB
248 lines
9.2 KiB
package com.lizongying.mytv
|
|
|
|
import android.app.DownloadManager
|
|
import android.app.DownloadManager.Request
|
|
import android.content.BroadcastReceiver
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.content.IntentFilter
|
|
import android.database.Cursor
|
|
import android.net.Uri
|
|
import android.os.Build
|
|
import android.os.Environment
|
|
import android.os.Handler
|
|
import android.os.Looper
|
|
import android.util.Log
|
|
import androidx.fragment.app.FragmentActivity
|
|
import com.lizongying.mytv.api.ApiClient
|
|
import com.lizongying.mytv.requests.ReleaseRequest
|
|
import com.lizongying.mytv.requests.ReleaseResponse
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.launch
|
|
import java.io.File
|
|
|
|
|
|
class UpdateManager(
|
|
private var context: Context,
|
|
private var versionCode: Long
|
|
) :
|
|
ConfirmationFragment.ConfirmationListener {
|
|
|
|
private var releaseRequest = ReleaseRequest()
|
|
private var release: ReleaseResponse? = null
|
|
|
|
private var downloadReceiver: DownloadReceiver? = null
|
|
|
|
fun checkAndUpdate() {
|
|
CoroutineScope(Dispatchers.Main).launch {
|
|
var text = "版本获取失败"
|
|
var update = false
|
|
try {
|
|
release = releaseRequest.getRelease()
|
|
Log.i(TAG, "versionCode $versionCode ${release?.version_code}")
|
|
if (release?.version_code != null) {
|
|
if (release?.version_code!! > versionCode) {
|
|
text = "最新版本:${release?.version_name}"
|
|
update = true
|
|
} else {
|
|
text = "已是最新版本,不需要更新"
|
|
}
|
|
}
|
|
} catch (e: Exception) {
|
|
Log.e(TAG, "Error occurred: ${e.message}", e)
|
|
}
|
|
updateUI(text, update)
|
|
}
|
|
}
|
|
|
|
private fun updateUI(text: String, update: Boolean) {
|
|
val dialog = ConfirmationFragment(this@UpdateManager, text, update)
|
|
dialog.show((context as FragmentActivity).supportFragmentManager, TAG)
|
|
}
|
|
|
|
private fun startDownload(release: ReleaseResponse) {
|
|
val apkName = "my-tv"
|
|
val apkFileName = "$apkName-${release.version_name}.apk"
|
|
val downloadManager =
|
|
context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
|
val request =
|
|
Request(Uri.parse("${ApiClient.DOWNLOAD_HOST}${release.version_name}/$apkName-${release.version_name}.apk"))
|
|
Log.i(
|
|
TAG,
|
|
"url ${Uri.parse("${ApiClient.DOWNLOAD_HOST}${release.version_name}/$apkName-${release.version_name}.apk")}"
|
|
)
|
|
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)?.mkdirs()
|
|
Log.i(TAG, "save dir ${Environment.DIRECTORY_DOWNLOADS}")
|
|
request.setDestinationInExternalFilesDir(
|
|
context,
|
|
Environment.DIRECTORY_DOWNLOADS,
|
|
apkFileName
|
|
)
|
|
request.setTitle("${context.resources.getString(R.string.app_name)} ${release.version_name}")
|
|
request.setNotificationVisibility(Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
|
request.setAllowedOverRoaming(false)
|
|
request.setMimeType("application/vnd.android.package-archive")
|
|
|
|
// 获取下载任务的引用
|
|
val downloadReference = downloadManager.enqueue(request)
|
|
|
|
downloadReceiver = DownloadReceiver(context, apkFileName, downloadReference)
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
context.registerReceiver(
|
|
downloadReceiver,
|
|
IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE),
|
|
Context.RECEIVER_NOT_EXPORTED,
|
|
)
|
|
} else {
|
|
context.registerReceiver(
|
|
downloadReceiver,
|
|
IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
|
|
)
|
|
}
|
|
|
|
getDownloadProgress(context, downloadReference) { progress ->
|
|
println("Download progress: $progress%")
|
|
}
|
|
}
|
|
|
|
private fun getDownloadProgress(
|
|
context: Context,
|
|
downloadId: Long,
|
|
progressListener: (Int) -> Unit
|
|
) {
|
|
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
|
val handler = Handler(Looper.getMainLooper())
|
|
val intervalMillis: Long = 1000
|
|
|
|
handler.post(object : Runnable {
|
|
override fun run() {
|
|
Log.i(TAG, "search")
|
|
val query = DownloadManager.Query().setFilterById(downloadId)
|
|
val cursor: Cursor = downloadManager.query(query)
|
|
cursor.use {
|
|
if (it.moveToFirst()) {
|
|
val bytesDownloadedIndex =
|
|
it.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)
|
|
val bytesTotalIndex =
|
|
it.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)
|
|
|
|
// 检查列名是否存在
|
|
if (bytesDownloadedIndex != -1 && bytesTotalIndex != -1) {
|
|
val bytesDownloaded = it.getInt(bytesDownloadedIndex)
|
|
val bytesTotal = it.getInt(bytesTotalIndex)
|
|
|
|
if (bytesTotal != -1) {
|
|
val progress = (bytesDownloaded * 100L / bytesTotal).toInt()
|
|
progressListener(progress)
|
|
if (progress == 100) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// handler.postDelayed(this, intervalMillis)
|
|
}
|
|
})
|
|
}
|
|
|
|
private class DownloadReceiver(
|
|
private val context: Context,
|
|
private val apkFileName: String,
|
|
private val downloadReference: Long
|
|
) : BroadcastReceiver() {
|
|
override fun onReceive(context: Context, intent: Intent) {
|
|
val reference = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
|
|
Log.i(TAG, "reference $reference")
|
|
|
|
if (reference == downloadReference) {
|
|
val downloadManager =
|
|
context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
|
val query = DownloadManager.Query().setFilterById(downloadReference)
|
|
val cursor = downloadManager.query(query)
|
|
if (cursor != null && cursor.moveToFirst()) {
|
|
val statusIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)
|
|
if (statusIndex < 0) {
|
|
Log.i(TAG, "Download failure")
|
|
return
|
|
}
|
|
val status = cursor.getInt(statusIndex)
|
|
|
|
val progressIndex =
|
|
cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)
|
|
if (progressIndex < 0) {
|
|
Log.i(TAG, "Download failure")
|
|
return
|
|
}
|
|
val progress = cursor.getInt(progressIndex)
|
|
|
|
val totalSizeIndex =
|
|
cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)
|
|
val totalSize = cursor.getInt(totalSizeIndex)
|
|
|
|
cursor.close()
|
|
|
|
when (status) {
|
|
DownloadManager.STATUS_SUCCESSFUL -> {
|
|
installNewVersion()
|
|
}
|
|
|
|
DownloadManager.STATUS_FAILED -> {
|
|
// Handle download failure
|
|
Log.i(TAG, "Download failure")
|
|
}
|
|
|
|
else -> {
|
|
// Update UI with download progress
|
|
val percentage = progress * 100 / totalSize
|
|
Log.i(TAG, "Download progress: $percentage%")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun installNewVersion() {
|
|
val apkFile = File(
|
|
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
|
apkFileName
|
|
)
|
|
Log.i(TAG, "apkFile $apkFile")
|
|
|
|
if (apkFile.exists()) {
|
|
val apkUri = Uri.parse("file://$apkFile")
|
|
Log.i(TAG, "apkUri $apkUri")
|
|
val installIntent = Intent(Intent.ACTION_VIEW).apply {
|
|
setDataAndType(apkUri, "application/vnd.android.package-archive")
|
|
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
}
|
|
|
|
context.startActivity(installIntent)
|
|
} else {
|
|
Log.e(TAG, "APK file does not exist!")
|
|
}
|
|
}
|
|
}
|
|
|
|
companion object {
|
|
private const val TAG = "UpdateManager"
|
|
}
|
|
|
|
override fun onConfirm() {
|
|
Log.i(TAG, "onConfirm $release")
|
|
release?.let { startDownload(it) }
|
|
}
|
|
|
|
override fun onCancel() {
|
|
}
|
|
|
|
fun destroy() {
|
|
if (downloadReceiver != null) {
|
|
context.unregisterReceiver(downloadReceiver)
|
|
Log.i(TAG, "destroy downloadReceiver")
|
|
}
|
|
}
|
|
} |