diff --git a/HISTORY.md b/HISTORY.md index b8e4ea6..8f947e1 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,261 +1,265 @@ -## 更新日志 +## 更新日誌 -### v2.0.9 +### v2.1.0 -* 修复部分设备闪退的问题 -* 修复设置页可能显示不全的问题 - -### v2.0.5 - -* 设置页增加恢复默认按钮,目前只用于同步系统时间 - -### v2.0.4 - -* 修复不能播放的问题 -* 包含国际频道 - -### v2.0.3 - -* 修复不能播放的问题 -* 不包含国际频道 - -### v2.0.0 - -* 解决卡顿问题 -* 解决网格样式时,点击空白处不退出的问题 -* 解决频道列表样式切换可能不生效的问题 - -### v1.9.8(通用) - -* 优化在线升级 -* 优化可能状态错误的问题 - -### v1.9.6(通用) - -* 优化在线升级 -* 优化可能状态错误的问题 - -### v1.9.4(通用) - -* 修复默认时间不显示问题 -* 设置页居中 -* 频道号和时间对齐 - -### v1.9.2(通用) - -* 修复一个重试的错误 - -### v1.9.0(通用) - -* 减少视频播放失败情况 -* 全面屏手机居中显示 - -### v1.8.8(通用) - -* 样式优化 - -### v1.8.6(通用) - -* 增加错误显示 -* 节目预告优化 -* 频道列表页单击切换频道 - -### v1.8.4(通用) - -* 解決部分情況下打開後黑屏问题 -* 延长频道信息显示时间,增加信息显示长度 -* 调整频道列表间距 -* 其他样式优化 - -### v1.8.2(通用) - -* 修复无法播放问题 +* 恢復播放 ### 以下已不可用 +### v2.0.9 + +* 修復部分設備閃退的問題 +* 修復設置頁可能顯示不全的問題 + +### v2.0.5 + +* 設置頁增加恢復默認按鈕,目前只用於同步系統時間 + +### v2.0.4 + +* 修復不能播放的問題 +* 包含國際頻道 + +### v2.0.3 + +* 修復不能播放的問題 +* 不包含國際頻道 + +### v2.0.0 + +* 解決卡頓問題 +* 解決網格樣式時,點擊空白處不退出的問題 +* 解決頻道列表樣式切換可能不生效的問題 + +### v1.9.8(通用) + +* 優化在線升級 +* 優化可能狀態錯誤的問題 + +### v1.9.6(通用) + +* 優化在線升級 +* 優化可能狀態錯誤的問題 + +### v1.9.4(通用) + +* 修復默認時間不顯示問題 +* 設置頁居中 +* 頻道號和時間對齊 + +### v1.9.2(通用) + +* 修復一個重試的錯誤 + +### v1.9.0(通用) + +* 減少視頻播放失敗情況 +* 全面屏手機居中顯示 + +### v1.8.8(通用) + +* 樣式優化 + +### v1.8.6(通用) + +* 增加錯誤顯示 +* 節目預告優化 +* 頻道列表頁單擊切換頻道 + +### v1.8.4(通用) + +* 解決部分情況下打開後黑屏問題 +* 延長頻道信息顯示時間,增加信息顯示長度 +* 調整頻道列表間距 +* 其他樣式優化 + +### v1.8.2(通用) + +* 修復無法播放問題 + ### v1.8.0(通用) -* 修复返回键无法退出问题 -* 设置中增加退出按钮 -* 修改非电视上的样式 -* 修复低版本闪退问题 +* 修復返回鍵無法退出問題 +* 設置中增加退出按鈕 +* 修改非電視上的樣式 +* 修復低版本閃退問題 ### v1.7.8(通用) -* 修复播放过程中的卡顿问题 -* 增加时间显示 -* 频道号优化 -* 遥控器左键打开频道列表 -* 遥控器右键打开设置菜单 -* 频道列表空白处点击隐藏频道列表 +* 修復播放過程中的卡頓問題 +* 增加時間顯示 +* 頻道號優化 +* 遙控器左鍵打開頻道列表 +* 遙控器右鍵打開設置菜單 +* 頻道列表空白處點擊隱藏頻道列表 ### v1.7.6(通用) -* 临时去掉部分频道,提高频道的可用性 -* 部分频道增加节目单 +* 臨時去掉部分頻道,提高頻道的可用性 +* 部分頻道增加節目單 -### v1.7.5(安卓5及以上专用) +### v1.7.5(安卓5及以上專用) -* 修复播放过程中的卡顿问题 -* 增加时间显示 -* 频道号优化 -* 设置中增加退出按钮 +* 修復播放過程中的卡頓問題 +* 增加時間顯示 +* 頻道號優化 +* 設置中增加退出按鈕 ### v1.7.4(通用) -* 修复368 +* 修復368 -### v1.7.3(安卓5及以上专用) +### v1.7.3(安卓5及以上專用) -* 临时去掉部分频道,提高频道的可用性 -* 部分频道增加节目单 -* 遥控器左键进入节目列表 -* 遥控器右键进入菜单 +* 臨時去掉部分頻道,提高頻道的可用性 +* 部分頻道增加節目單 +* 遙控器左鍵進入節目列表 +* 遙控器右鍵進入菜單 ### v1.7.2(通用) -* 支持节目列表网格样式和行样式切换,软件重启后生效 -* 节目列表样式变更 +* 支持節目列表網格樣式和行樣式切換,軟件重啟後生效 +* 節目列表樣式變更 -### v1.7.1(安卓5及以上专用) +### v1.7.1(安卓5及以上專用) -* 解决设置页更新闪退的问题 -* 凤凰卫视回归 -* 解决368问题 +* 解決設置頁更新閃退的問題 +* 鳳凰衛視回歸 +* 解決368問題 ### v1.7.0(通用) -* 网络请求优化 +* 網絡請求優化 -### v1.6.9(安卓5及以上专用) +### v1.6.9(安卓5及以上專用) -* 去掉港澳台和国际频道 -* 解决部分情况下3、6、8等频道无法播放的问题 -* 解决部分情况下启动后黑屏问题 +* 去掉港澳台和國際頻道 +* 解決部分情況下3、6、8等頻道無法播放的問題 +* 解決部分情況下啟動後黑屏問題 ### v1.6.8(通用) -* 修复部分设备崩溃的问题 -* 修复部分设备凤凰卫视无法播放的问题 +* 修復部分設備崩潰的問題 +* 修復部分設備鳳凰衛視無法播放的問題 -### v1.6.7(安卓5及以上专用) +### v1.6.7(安卓5及以上專用) -* 手机双击打开配置 -* 自动更新 +* 手機雙擊打開配置 +* 自動更新 ### v1.6.6(通用) -* 更新重庆卫视图标 -* 凤凰卫视增强画质 -* 凤凰卫视增加EPG +* 更新重慶衛視圖標 +* 鳳凰衛視增強畫質 +* 鳳凰衛視增加EPG -### v1.6.5(安卓5及以上专用) +### v1.6.5(安卓5及以上專用) -* 增加CETV1图标 -* 稳定性提升 +* 增加CETV1圖標 +* 穩定性提升 ### v1.6.4(通用) * 增加CETV1 -* 增加凤凰卫视 -* 默认关闭开机启动 +* 增加鳳凰衛視 +* 默認關閉開機啟動 -### v1.6.3(安卓5及以上专用) +### v1.6.3(安卓5及以上專用) * 增加CETV1 -* 凤凰卫视增强画质 -* 默认关闭开机启动 -* 延迟菜单自动关闭时间 -* 解决一些可能导致首次打开时黑屏的问题 +* 鳳凰衛視增強畫質 +* 默認關閉開機啟動 +* 延遲菜單自動關閉時間 +* 解決一些可能導致首次打開時黑屏的問題 ### v1.6.2(通用) -* 修复按键无效的问题 -* 新的频道列表样式 +* 修復按鍵無效的問題 +* 新的頻道列表樣式 -### v1.6.1(安卓5及以上专用) +### v1.6.1(安卓5及以上專用) -* 增加凤凰卫视 +* 增加鳳凰衛視 ### v1.6.0(通用) * 通用(春晚緊急修復) -### v1.5.9(安卓5及以上专用) +### v1.5.9(安卓5及以上專用) -* 解决天猫魔盒闪退问题 +* 解決天貓魔盒閃退問題 ### v1.5.8(通用) -* 修复央视6画质差的问题 -* 增加兵团卫视 -* 播放失败重试 +* 修復央視6畫質差的問題 +* 增加兵團衛視 +* 播放失敗重試 -### v1.5.7(安卓5及以上专用) +### v1.5.7(安卓5及以上專用) -* 修复播放失败的问题 +* 修復播放失敗的問題 ### v1.5.6(通用) -* 解决部分设备系统时间不对导致播放失败的问题 +* 解決部分設備系統時間不對導致播放失敗的問題 -### v1.5.5(安卓5及以上专用) +### v1.5.5(安卓5及以上專用) -* 修复播放失败的问题 -* 修复APP恢复后频道号、频道列表不自动消失的问题 +* 修復播放失敗的問題 +* 修復APP恢復後頻道號、頻道列表不自動消失的問題 ### v1.5.4(通用) -* 修复播放失败的问题 +* 修復播放失敗的問題 -### v1.5.3(安卓5及以上专用) +### v1.5.3(安卓5及以上專用) -* 修复部分情况下APP切换后无法继续播放的问题 -* 优化重试逻辑 +* 修復部分情況下APP切換後無法繼續播放的問題 +* 優化重試邏輯 ### v1.5.2(通用) -* 修复APP恢复后频道号、频道列表不自动消失的问题 +* 修復APP恢復後頻道號、頻道列表不自動消失的問題 -### v1.5.1(安卓5及以上专用) +### v1.5.1(安卓5及以上專用) -* 性能优化 +* 性能優化 ### v1.5.0(通用) -* 修复部分情况下APP切换后无法继续播放的问题 +* 修復部分情況下APP切換後無法繼續播放的問題 -### v1.4.9(安卓5及以上专用) +### v1.4.9(安卓5及以上專用) * 同步v1.4.8 ### v1.4.8(通用) -* 频道号从1开始,CCTV5+为18 +* 頻道號從1開始,CCTV5+為18 * 提高CCTV6清晰度 -* 增加天津卫视、新疆卫视 +* 增加天津衛視、新疆衛視 -### v1.4.7(安卓5及以上专用) +### v1.4.7(安卓5及以上專用) -* 修复部分用户CCTV13播放过程中卡住的问题 -* 调整CCTV的频道顺序 +* 修復部分用戶CCTV13播放過程中卡住的問題 +* 調整CCTV的頻道順序 ### v1.4.6(通用) -* 10以下频道不再需要先按0 +* 10以下頻道不再需要先按0 -### v1.4.5(安卓5及以上专用) +### v1.4.5(安卓5及以上專用) -* 数字选台配置 +* 數字選台配置 ### v1.4.4(通用) -* 优化图标显示 -* 增加换台反转 +* 優化圖標顯示 +* 增加換台反轉 -### v1.4.3(安卓5及以上专用) +### v1.4.3(安卓5及以上專用) -* 支持频道反转配置 +* 支持頻道反轉配置 ### v1.4.2(通用) @@ -263,40 +267,40 @@ ### v1.4.1 -* 解决部分用户无法打开菜单的问题 +* 解決部分用戶無法打開菜單的問題 ### v1.4.0 -* 解决极个别高版本机型黑屏问题 +* 解決極個別高版本機型黑屏問題 ### v1.3.9 -* 提高稳定性 -* 提高连接速度 +* 提高穩定性 +* 提高連接速度 ### v1.3.4 -* 部分错误会提示用户 -* 菜单3秒钟后自动关闭 +* 部分錯誤會提示用戶 +* 菜單3秒鐘後自動關閉 ### v1.3.3 -* 部分错误会提示用户 -* 菜单3秒钟后自动关闭 +* 部分錯誤會提示用戶 +* 菜單3秒鐘後自動關閉 ### v1.3.2 -* 增加重试,减少因网络问题导致的播放失败 -* 优化横幅banner +* 增加重試,減少因網絡問題導致的播放失敗 +* 優化橫幅banner ### v1.3.1 -* 增加CCTV 8K 超高清频道 -* 增加国际频道栏目 +* 增加CCTV 8K 超高清頻道 +* 增加國際頻道欄目 ### v1.3.0 -* 处理368可能失败的情形 +* 處理368可能失敗的情形 ### v1.2.9 @@ -308,32 +312,32 @@ ### v1.2.7 -* 此版本是为了测试安卓6.0以下版本,如之前可以正常运行,请勿安装。 +* 此版本是為了測試安卓6.0以下版本,如之前可以正常運行,請勿安裝。 ### v1.2.6 * 支持安卓4.2 -* 解决部分频道无法播放的问题 -* 修复切换时有时没有恢复播放的问题 -* 左右键不再切换源 -* 增大频道信息标题尺寸,缩小与节目信息的间隔 +* 解決部分頻道無法播放的問題 +* 修復切換時有時沒有恢復播放的問題 +* 左右鍵不再切換源 +* 增大頻道信息標題尺寸,縮小與節目信息的間隔 ### v1.2.5 -* 美化频道信息显示 -* 优化节目单获取 +* 美化頻道信息顯示 +* 優化節目單獲取 ### v1.2.4 -* 改变换台滑动方向,上一个频道下滑,下一个频道上滑 -* 软件退出时,退出播放器 -* 播放相同的频道,不再重复加载 -* 暂时移除部分频道 +* 改變換台滑動方向,上一個頻道下滑,下一個頻道上滑 +* 軟件退出時,退出播放器 +* 播放相同的頻道,不再重複加載 +* 暫時移除部分頻道 ### v1.2.3 -* 固定视频比列为16:9 -* 隐藏全面屏底部的小横条 -* 移除移动专区 -* 修复一个闪退问题 -* 更换图标和应用名 \ No newline at end of file +* 固定視頻比例為16:9 +* 隱藏全面屏底部的小橫條 +* 移除移動專區 +* 修復一個閃退問題 +* 更換圖標和應用名 \ No newline at end of file diff --git a/README.md b/README.md index bab6570..d63c5f7 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,6 @@ * 亮度调节 * 音量调节 * 軟解 -* 网格空白处退出 ## 版权说明 diff --git a/app/build.gradle b/app/build.gradle index 7166c44..b0d116a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,6 +26,7 @@ android { cmake { arguments "-DIS_SO_BUILD=${project.hasProperty('IS_SO_BUILD') ? project.IS_SO_BUILD : true}" +// abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64" abiFilters "armeabi-v7a", "arm64-v8a" } } @@ -128,6 +129,7 @@ dependencies { implementation 'com.github.bumptech.glide:glide:4.11.0' + implementation("androidx.work:work-runtime-ktx:2.9.0") implementation 'androidx.core:core-ktx:1.11.0-beta02' implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.leanback:leanback:1.2.0-alpha02' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2fe0464..3b862ee 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,6 +10,7 @@ + diff --git a/app/src/main/cpp/arm64-v8a/libnative.so b/app/src/main/cpp/arm64-v8a/libnative.so index 1ea0926..b1167ae 100755 Binary files a/app/src/main/cpp/arm64-v8a/libnative.so and b/app/src/main/cpp/arm64-v8a/libnative.so differ diff --git a/app/src/main/cpp/armeabi-v7a/libnative.so b/app/src/main/cpp/armeabi-v7a/libnative.so index 7b731da..a2279b1 100755 Binary files a/app/src/main/cpp/armeabi-v7a/libnative.so and b/app/src/main/cpp/armeabi-v7a/libnative.so differ diff --git a/app/src/main/cpp/x86/libcrypto.a b/app/src/main/cpp/x86/libcrypto.a new file mode 100644 index 0000000..de1a167 Binary files /dev/null and b/app/src/main/cpp/x86/libcrypto.a differ diff --git a/app/src/main/cpp/x86/libcrypto.so b/app/src/main/cpp/x86/libcrypto.so new file mode 100755 index 0000000..5fe7ad9 Binary files /dev/null and b/app/src/main/cpp/x86/libcrypto.so differ diff --git a/app/src/main/cpp/x86/libssl.a b/app/src/main/cpp/x86/libssl.a new file mode 100644 index 0000000..721c5aa Binary files /dev/null and b/app/src/main/cpp/x86/libssl.a differ diff --git a/app/src/main/cpp/x86/libssl.so b/app/src/main/cpp/x86/libssl.so new file mode 100755 index 0000000..88dab05 Binary files /dev/null and b/app/src/main/cpp/x86/libssl.so differ diff --git a/app/src/main/cpp/x86_64/libcrypto.a b/app/src/main/cpp/x86_64/libcrypto.a new file mode 100644 index 0000000..f0fa687 Binary files /dev/null and b/app/src/main/cpp/x86_64/libcrypto.a differ diff --git a/app/src/main/cpp/x86_64/libcrypto.so b/app/src/main/cpp/x86_64/libcrypto.so new file mode 100755 index 0000000..136532d Binary files /dev/null and b/app/src/main/cpp/x86_64/libcrypto.so differ diff --git a/app/src/main/cpp/x86_64/libssl.a b/app/src/main/cpp/x86_64/libssl.a new file mode 100644 index 0000000..e8e43d3 Binary files /dev/null and b/app/src/main/cpp/x86_64/libssl.a differ diff --git a/app/src/main/cpp/x86_64/libssl.so b/app/src/main/cpp/x86_64/libssl.so new file mode 100755 index 0000000..be24c79 Binary files /dev/null and b/app/src/main/cpp/x86_64/libssl.so differ diff --git a/app/src/main/java/com/lizongying/mytv/UpdateManager.kt b/app/src/main/java/com/lizongying/mytv/UpdateManager.kt index 6d5ecc0..77f3ede 100644 --- a/app/src/main/java/com/lizongying/mytv/UpdateManager.kt +++ b/app/src/main/java/com/lizongying/mytv/UpdateManager.kt @@ -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() + .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") - } - } } \ No newline at end of file diff --git a/app/src/main/java/com/lizongying/mytv/UpdateWorker.kt b/app/src/main/java/com/lizongying/mytv/UpdateWorker.kt new file mode 100644 index 0000000..72221ad --- /dev/null +++ b/app/src/main/java/com/lizongying/mytv/UpdateWorker.kt @@ -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" + } +} diff --git a/version.json b/version.json index cf2d8e8..8aa064e 100644 --- a/version.json +++ b/version.json @@ -1 +1 @@ -{"version_code": 33556736, "version_name": "v2.0.9"} +{"version_code": 33619968, "version_name": "v2.1.0"}