mirror of
https://github.com/lizongying/my-tv.git
synced 2026-11-01 17:16:30 +08:00
fix ysp
This commit is contained in:
@@ -1,26 +1,17 @@
|
||||
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 androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.workDataOf
|
||||
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(
|
||||
@@ -32,17 +23,15 @@ class UpdateManager(
|
||||
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) {
|
||||
val code = release?.version_code
|
||||
if (code != null) {
|
||||
if (code.toLong() > versionCode) {
|
||||
text = "最新版本:${release?.version_name}"
|
||||
update = true
|
||||
} else {
|
||||
@@ -61,170 +50,24 @@ class UpdateManager(
|
||||
dialog.show((context as FragmentActivity).supportFragmentManager, TAG)
|
||||
}
|
||||
|
||||
private fun startDownload(release: ReleaseResponse) {
|
||||
private fun startDownload(context: Context, release: ReleaseResponse) {
|
||||
val versionName = release.version_name
|
||||
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,
|
||||
val downloadUrl =
|
||||
"${ApiClient.DOWNLOAD_HOST}${release.version_name}/$apkName-${release.version_name}.apk"
|
||||
Log.i(TAG, "downloadUrl: $downloadUrl")
|
||||
val downloadRequest = OneTimeWorkRequestBuilder<UpdateWorker>()
|
||||
.setInputData(
|
||||
workDataOf(
|
||||
"VERSION_NAME" to versionName,
|
||||
"APK_FILENAME" to apkFileName,
|
||||
"DOWNLOAD_URL" to downloadUrl
|
||||
)
|
||||
)
|
||||
} else {
|
||||
context.registerReceiver(
|
||||
downloadReceiver,
|
||||
IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
|
||||
)
|
||||
}
|
||||
.build()
|
||||
|
||||
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!")
|
||||
}
|
||||
}
|
||||
WorkManager.getInstance(context).enqueue(downloadRequest)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -233,16 +76,9 @@ class UpdateManager(
|
||||
|
||||
override fun onConfirm() {
|
||||
Log.i(TAG, "onConfirm $release")
|
||||
release?.let { startDownload(it) }
|
||||
release?.let { startDownload(context, it) }
|
||||
}
|
||||
|
||||
override fun onCancel() {
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
if (downloadReceiver != null) {
|
||||
context.unregisterReceiver(downloadReceiver)
|
||||
Log.i(TAG, "destroy downloadReceiver")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package com.lizongying.mytv
|
||||
|
||||
import android.app.DownloadManager
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.WorkerParameters
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
|
||||
class UpdateWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
|
||||
|
||||
private lateinit var notificationManager: NotificationManager
|
||||
private lateinit var notificationBuilder: NotificationCompat.Builder
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
val downloadUrl = inputData.getString("DOWNLOAD_URL") ?: return Result.failure()
|
||||
val apkFileName = inputData.getString("APK_FILENAME") ?: return Result.failure()
|
||||
val versionName = inputData.getString("VERSION_NAME") ?: return Result.failure()
|
||||
|
||||
showNotification(applicationContext)
|
||||
|
||||
return withContext(Dispatchers.IO) {
|
||||
try {
|
||||
downloadAndInstall(applicationContext, downloadUrl, apkFileName, versionName)
|
||||
Result.success()
|
||||
} catch (e: Exception) {
|
||||
Result.failure()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showNotification(context: Context) {
|
||||
notificationManager =
|
||||
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationBuilder = NotificationCompat.Builder(context, "download_channel").apply {
|
||||
setSmallIcon(android.R.drawable.stat_sys_download)
|
||||
setContentTitle("Downloading Update")
|
||||
setContentText("Download in progress")
|
||||
priority = NotificationCompat.PRIORITY_LOW
|
||||
setOngoing(true)
|
||||
setProgress(100, 0, false)
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel = NotificationChannel(
|
||||
"download_channel",
|
||||
"Download Updates",
|
||||
NotificationManager.IMPORTANCE_LOW
|
||||
)
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
|
||||
notificationManager.notify(1, notificationBuilder.build())
|
||||
}
|
||||
|
||||
private fun downloadAndInstall(
|
||||
context: Context,
|
||||
downloadUrl: String,
|
||||
apkFileName: String,
|
||||
versionName: String
|
||||
) {
|
||||
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)?.mkdirs()
|
||||
Log.i(TAG, "save dir ${Environment.DIRECTORY_DOWNLOADS}")
|
||||
val request = DownloadManager.Request(Uri.parse(downloadUrl)).apply {
|
||||
setTitle("${context.resources.getString(R.string.app_name)} $versionName Downloading")
|
||||
setDescription("Downloading the latest version of the app")
|
||||
setDestinationInExternalFilesDir(context, Environment.DIRECTORY_DOWNLOADS, apkFileName)
|
||||
|
||||
setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
||||
// setAllowedOverRoaming(false)
|
||||
setMimeType("application/vnd.android.package-archive")
|
||||
}
|
||||
|
||||
val manager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
||||
val downloadId = manager.enqueue(request)
|
||||
|
||||
var downloading = true
|
||||
while (downloading) {
|
||||
val query = DownloadManager.Query().setFilterById(downloadId)
|
||||
val cursor = manager.query(query)
|
||||
if (cursor.moveToFirst()) {
|
||||
val bytesDownloaded =
|
||||
cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
|
||||
val bytesTotal =
|
||||
cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))
|
||||
|
||||
if (bytesTotal > 0) {
|
||||
val progress = (bytesDownloaded * 100L / bytesTotal).toInt()
|
||||
notificationBuilder.setProgress(100, progress, false)
|
||||
notificationManager.notify(1, notificationBuilder.build())
|
||||
}
|
||||
|
||||
when (cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS))) {
|
||||
DownloadManager.STATUS_SUCCESSFUL -> downloading = false
|
||||
DownloadManager.STATUS_FAILED -> {
|
||||
downloading = false
|
||||
throw Exception("Download failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
cursor.close()
|
||||
}
|
||||
|
||||
notificationBuilder.setContentText("Download complete")
|
||||
.setProgress(0, 0, false)
|
||||
.setOngoing(false)
|
||||
notificationManager.notify(1, notificationBuilder.build())
|
||||
|
||||
val apkFile = File(
|
||||
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
|
||||
apkFileName
|
||||
)
|
||||
|
||||
if (apkFile.exists()) {
|
||||
val apkUri: Uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
FileProvider.getUriForFile(context, context.packageName + ".fileprovider", apkFile)
|
||||
.apply {
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
}
|
||||
} else {
|
||||
Uri.parse("file://${apkFile.absolutePath}")
|
||||
// Uri.fromFile(apkFile)
|
||||
}
|
||||
// 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 = "UpdateWorker"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user