Skip to content

Commit

Permalink
Fixed the issue that the Android 4.4 system SSL certificate was too o…
Browse files Browse the repository at this point in the history
…ld and caused this APP to fail to update. All codes generated by claude.ai
  • Loading branch information
vrichv committed Jul 24, 2024
1 parent e8b0521 commit 8ae8ac2
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 171 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ body:
id: checklist
attributes:
label: 检查清单
description: 声明:本项目仅为自用修改,仅在android4.4的夏普电视测试,作者没有任何义务为任何人解决问题或添加功能,如果你遇到了问题,建议 1)自行修改源代码解决; 2)使用AI如claude.ai协助解决; 3)向本项目原作者@lizhongying求助
description: 声明:本项目仅为自用修改,仅在android4.4的夏普电视测试,作者没有任何义务为任何人解决问题或添加功能,如果你遇到了问题,建议 1)自行修改源代码解决; 2)使用AI如claude.ai协助解决; 3)向本项目原作者求助
options:
- label: 明白上述声明
required: true
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ body:
id: checklist
attributes:
label: 检查清单
description: 声明:本项目仅为自用修改,仅在android4.4的夏普电视测试,作者没有任何义务为任何人解决问题或添加功能,如果你遇到了问题,建议 1)自行修改源代码解决; 2)使用AI如claude.ai协助解决; 3)向本项目原作者@lizhongying求助
description: 声明:本项目仅为自用修改,仅在android4.4的夏普电视测试,作者没有任何义务为任何人解决问题或添加功能,如果你遇到了问题,建议 1)自行修改源代码解决; 2)使用AI如claude.ai协助解决; 3)向本项目原作者求助
options:
- label: 明白上述声明
required: true
Expand Down
276 changes: 108 additions & 168 deletions app/src/main/java/com/lizongying/mytv0/UpdateManager.kt
Original file line number Diff line number Diff line change
@@ -1,49 +1,45 @@
package com.lizongying.mytv0

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.mytv0.requests.HttpClient
import com.lizongying.mytv0.requests.ReleaseRequest
import com.lizongying.mytv0.requests.ReleaseResponse
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File

import java.io.IOException

class UpdateManager(
private var context: Context,
private var versionCode: Long
) :
ConfirmationFragment.ConfirmationListener {
private val context: Context,
private val versionCode: Long
) : ConfirmationFragment.ConfirmationListener {

private var releaseRequest = ReleaseRequest()
private var release: ReleaseResponse? = null

private var downloadReceiver: DownloadReceiver? = null
private val okHttpClient = HttpClient.okHttpClient
private var downloadJob: Job? = null
private var lastLoggedProgress = -1

fun checkAndUpdate() {
Log.i(TAG, "checkAndUpdate")
CoroutineScope(Dispatchers.Main).launch {
GlobalScope.launch(Dispatchers.Main) {
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) {
if (release?.version_code!! > versionCode) {
text = "最新版本:${release?.version_name}"
update = true
} else {
Expand All @@ -65,171 +61,111 @@ class UpdateManager(
private fun startDownload(release: ReleaseResponse) {
val apkName = "my-tv-0"
val apkFileName = "$apkName-${release.version_name}.apk"
val downloadManager =
context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val request =
Request(Uri.parse("${HttpClient.DOWNLOAD_HOST}${release.version_name}/$apkName-${release.version_name}.apk"))
Log.i(
TAG,
"url ${Uri.parse("${HttpClient.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)
)
}
val url =
"${HttpClient.DOWNLOAD_HOST}${release.version_name}/$apkName-${release.version_name}.apk"
val downloadDir = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)

getDownloadProgress(context, downloadReference) { progress ->
println("Download progress: $progress%")
cleanupDownloadDirectory(downloadDir, apkName)
val file = File(downloadDir, apkFileName)
file.parentFile?.mkdirs()

downloadJob = GlobalScope.launch(Dispatchers.IO) {
downloadWithRetry(url, file)
}
}

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
}
}
}
private fun cleanupDownloadDirectory(directory: File?, apkNamePrefix: String) {
directory?.let { dir ->
dir.listFiles()?.forEach { file ->
if (file.name.startsWith(apkNamePrefix) && file.name.endsWith(".apk")) {
val deleted = file.delete()
if (deleted) {
Log.i(TAG, "Deleted old APK file: ${file.name}")
} else {
Log.e(TAG, "Failed to delete old APK file: ${file.name}")
}
}

// 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
private suspend fun downloadWithRetry(url: String, file: File, maxRetries: Int = 3) {
var retries = 0
while (retries < maxRetries) {
try {
downloadFile(url, file)
// If download is successful, break the loop
break
} catch (e: IOException) {
Log.e(TAG, "Download failed: ${e.message}")
retries++
if (retries >= maxRetries) {
Log.e(TAG, "Max retries reached. Download failed.")
withContext(Dispatchers.Main) {
// Notify user about download failure
updateUI("下载失败,请检查网络连接后重试", false)
}
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 {
Log.i(TAG, "Retrying download (${retries}/${maxRetries})")
delay(30000) // Wait for 30 seconds before retrying
}
}
}
}

else -> {
// Update UI with download progress
val percentage = progress * 100 / totalSize
Log.i(TAG, "Download progress: $percentage%")
}
private suspend fun downloadFile(url: String, file: File) {
val request = okhttp3.Request.Builder().url(url).build()
val response = okHttpClient.newCall(request).execute()
if (!response.isSuccessful) throw IOException("Unexpected code $response")

val body = response.body() ?: throw IOException("Null response body")
val contentLength = body.contentLength()
var bytesRead = 0L

body.byteStream().use { inputStream ->
file.outputStream().use { outputStream ->
val buffer = ByteArray(BUFFER_SIZE)
var bytes: Int
while (inputStream.read(buffer).also { bytes = it } != -1) {
outputStream.write(buffer, 0, bytes)
bytesRead += bytes
val progress =
if (contentLength > 0) (bytesRead * 100 / contentLength).toInt() else -1
withContext(Dispatchers.Main) {
updateDownloadProgress(progress)
}
}
}
}

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)
}
withContext(Dispatchers.Main) {
installNewVersion(file)
}
}

context.startActivity(installIntent)
} else {
Log.e(TAG, "APK file does not exist!")
}
private fun updateDownloadProgress(progress: Int) {
if (progress == -1) {
// Log when progress can't be determined
Log.i(TAG, "Download in progress, size unknown")
} else if (progress % 10 == 0 && progress != lastLoggedProgress) {
// Log every 10% and avoid duplicate logs
Log.i(TAG, "Download progress: $progress%")
lastLoggedProgress = progress
"升级文件已经下载:${progress}%".showToast()
}
}

companion object {
private const val TAG = "UpdateManager"
private fun installNewVersion(apkFile: File) {
if (apkFile.exists()) {
val apkUri = Uri.fromFile(apkFile) // Use Uri.fromFile for Android 4.4
Log.i(TAG, "apkUri $apkUri")
val installIntent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(apkUri, "application/vnd.android.package-archive")
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
context.startActivity(installIntent)
} else {
Log.e(TAG, "APK file does not exist!")
}
}

override fun onConfirm() {
Expand All @@ -238,12 +174,16 @@ class UpdateManager(
}

override fun onCancel() {
// Handle cancellation if needed
}

fun destroy() {
if (downloadReceiver != null) {
context.unregisterReceiver(downloadReceiver)
Log.i(TAG, "destroy downloadReceiver")
}
downloadJob?.cancel()
// Additional cleanup if needed
}

companion object {
private const val TAG = "UpdateManager"
private const val BUFFER_SIZE = 8192
}
}
2 changes: 1 addition & 1 deletion version.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version_code": 16910340, "version_name": "v1.2.8-kk4"}
{"version_code": 16910341, "version_name": "v1.2.8-kk5"}

0 comments on commit 8ae8ac2

Please sign in to comment.