123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625 |
- package com.develop.common.utils
- import android.annotation.SuppressLint
- import android.app.Application
- import android.content.Context
- import android.net.Uri
- import android.os.PowerManager
- import android.provider.Settings
- import android.util.Log
- import com.azhon.appupdate.listener.OnDownloadListener
- import com.azhon.appupdate.util.LogUtil
- import com.blankj.utilcode.util.FileUtils
- import com.blankj.utilcode.util.ToastUtils
- import com.blankj.utilcode.util.ZipUtils
- import com.develop.base.ext.getNewTuya
- import com.develop.base.ext.getOtaFileMd5
- import com.develop.base.ext.getSN
- import com.develop.base.ext.getUpdateRecipeTime
- import com.develop.base.ext.globalApp
- import com.develop.base.ext.setOtaFileMd5
- import com.develop.base.ext.setRecipesList
- import com.develop.base.util.AppActivityManager
- import com.develop.base.util.FileKit
- import com.develop.base.util.GlobalToast
- import com.develop.base.util.MMkvUtils
- import com.develop.base.util.TopResumedAtyHolder
- import com.develop.common.R
- import com.develop.common.data_repo.FoodDataProvider
- import com.develop.common.data_repo.db.entity.DevRecipeCategory
- import com.develop.common.data_repo.db.entity.DevVersion
- import com.develop.common.data_repo.net.Api
- import com.develop.common.data_repo.net.converter.SerializationConverter.Companion.jsonDecoder
- import com.develop.common.data_repo.net.model.request.DeviceInfoBody
- import com.develop.common.data_repo.net.model.response.DevInfoResult
- import com.develop.common.data_repo.net.model.response.RecipeDataConfig
- import com.develop.common.dialog.CancelConfirmDialog
- import com.develop.common.dialog.CommonDialog
- import com.develop.common.dialog.RecipeUpdateDialog
- import com.develop.common.tag.CURRENT_USER_ID
- import com.develop.common.tag.SCREENSAVER
- import com.drake.net.Get
- import com.drake.net.Post
- import com.drake.net.component.Progress
- import com.drake.net.interfaces.ProgressListener
- import com.drake.net.utils.scopeNetLife
- import kotlinx.serialization.decodeFromString
- import org.greenrobot.eventbus.EventBus
- import java.io.File
- import java.util.*
- object AppVersionUtil {
- var numberList = mutableListOf<String>()
- var dialogRecipeUpdate = RecipeUpdateDialog()
- var sTime: Long = 0
- fun startRecord(){
- sTime = System.currentTimeMillis()
- Log.e("TAG 启动时间"," ------ startRecord :$sTime")
- }
- fun endRecord(msg :String){
- val cost = System.currentTimeMillis() - sTime
- Log.e("TAG 启动时间","msg : $msg ------ cost :$cost")
- }
- fun checkRecipeUpdate(shoNoUpdateDialog: Boolean = false) {
- if (getNewTuya()){
- //由于涂鸦云食谱,估不检测平台食谱
- return
- }
- TopResumedAtyHolder.getCurrentActivity()?.apply {
- scopeNetLife {
- try {
- val result = Post<DevInfoResult>(Api.DEV_INFO) {
- body = DeviceInfoBody.genDeviceInfoBody()
- }.await()
- if (result.apkUpdate) {
- val commonDialog = CommonDialog()
- commonDialog.msg = getString(com.develop.common.R.string.update_msg)
- commonDialog.title = getString(com.develop.common.R.string.update)
- commonDialog.hasOKBtn = false
- val cancelConfirmDialog = CancelConfirmDialog()
- cancelConfirmDialog.title =
- getString(com.develop.common.R.string.update_title)
- cancelConfirmDialog.showDialog(
- supportFragmentManager,
- "cancelConfirmDialog"
- )
- cancelConfirmDialog.onDialogClickListener =
- object : CancelConfirmDialog.OnDialogClickListener {
- override fun onConfirm() {
- commonDialog.showDialog(supportFragmentManager, "commonDialog")
- UpdateUtil.updateApp(
- this@apply,
- result.apkUrl,
- object : OnDownloadListener {
- override fun cancel() {
- runOnUiThread {
- commonDialog.removeSelf()
- }
- }
- override fun done(apk: File) {
- GlobalToast.showToast(getString(R.string.finish_download))
- UpdateUtil.installPackage(this@apply, apk)
- commonDialog.updateProgress(getString(R.string.installing))
- }
- override fun downloading(max: Int, progress: Int) {
- runOnUiThread {
- commonDialog.updateProgress(
- "${
- String.format(
- "%.0f",
- ((progress.toFloat() / max.toFloat()) * 100f)
- )
- }%"
- )
- }
- }
- override fun error(e: Throwable) {
- GlobalToast.showToast(getString(R.string.download_fail))
- runOnUiThread {
- commonDialog.removeSelf()
- }
- }
- override fun start() {
- // GlobalToast.showToast(getString(com.develop.common.R.string.start_download))
- }
- })
- }
- override fun onCancel() {
- }
- override fun onKey() {
- }
- }
- } else {
- val downloadDir = this@apply.externalCacheDir.toString()
- val downloadName = System.nanoTime().toString()
- val recipeUpdateTime = result.recipeUpdateTime
- val newRecipes = LinkedList(result.newRecipes)
- if (newRecipes.isEmpty() && shoNoUpdateDialog) {
- val dialog = RecipeUpdateDialog()
- dialog.onDialogClickListener =
- object : RecipeUpdateDialog.OnDialogClickListener {
- override fun onConfirm() {
- }
- override fun onCancel() {
- }
- }
- dialog.showNoUpdateTips(supportFragmentManager, "RECIPE_UPDATE_DIALOG")
- }
- if (newRecipes.isNotEmpty()) {
- if (dialogRecipeUpdate.isShow) {
- dialogRecipeUpdate.removeSelf()
- }
- dialogRecipeUpdate.onDialogClickListener =
- object : RecipeUpdateDialog.OnDialogClickListener {
- override fun onConfirm() {
- updateRecipe = !updateRecipe
- //清掉list的number
- numberList.clear()
- EventBus.getDefault().post(NoScreenEvent(true))
- downloadRecipes(
- newRecipes,
- dialogRecipeUpdate,
- newRecipes.size.toLong(),
- downloadDir,
- downloadName,
- recipeUpdateTime
- )
- }
- override fun onCancel() {
- }
- }
- var activityName =
- AppActivityManager.getInstance().topActivity.localClassName
- /**
- * 由于访问接口得时候处理数据,这时候切换了其他页面再切换语言导致,
- * 更新食谱的dialog的问题会空白,估做下面判断
- * */
- if (activityName.contains("ModeEntranceActivity") || activityName.contains(
- "ModeEntrance2Activity"
- ) || activityName.contains("AboutActivity")
- ) {
- dialogRecipeUpdate.showUpdateTips(
- supportFragmentManager,
- "RECIPE_UPDATE_DIALOG",
- newRecipes.size.toLong()
- )
- }
- }
- }
- } catch (e: java.lang.Exception) {
- e.printStackTrace()
- }
- }
- }
- }
- fun checkAboutRecipeUpdate(shoNoUpdateDialog: Boolean = false) {
- if (getNewTuya()){
- //由于涂鸦云食谱,估不检测平台食谱
- return
- }
- TopResumedAtyHolder.getCurrentActivity()?.apply {
- scopeNetLife {
- try {
- val result = Post<DevInfoResult>(Api.DEV_INFO) {
- body = DeviceInfoBody.genDeviceInfoBody()
- }.await()
- val downloadDir = this@apply.externalCacheDir.toString()
- val downloadName = System.nanoTime().toString()
- val recipeUpdateTime = result.recipeUpdateTime
- val newRecipes = LinkedList(result.newRecipes)
- if (newRecipes.isEmpty() && shoNoUpdateDialog) {
- val dialog = RecipeUpdateDialog()
- dialog.onDialogClickListener =
- object : RecipeUpdateDialog.OnDialogClickListener {
- override fun onConfirm() {
- }
- override fun onCancel() {
- }
- }
- dialog.showNoUpdateTips(supportFragmentManager, "RECIPE_UPDATE_DIALOG")
- }
- if (newRecipes.isNotEmpty()) {
- if (dialogRecipeUpdate.isShow) {
- dialogRecipeUpdate.removeSelf()
- }
- dialogRecipeUpdate.onDialogClickListener =
- object : RecipeUpdateDialog.OnDialogClickListener {
- override fun onConfirm() {
- updateRecipe = !updateRecipe
- //清掉list的number
- numberList.clear()
- EventBus.getDefault().post(NoScreenEvent(true))
- downloadRecipes(
- newRecipes,
- dialogRecipeUpdate,
- newRecipes.size.toLong(),
- downloadDir,
- downloadName,
- recipeUpdateTime
- )
- }
- override fun onCancel() {
- }
- }
- var activityName =
- AppActivityManager.getInstance().topActivity.localClassName
- /**
- * 由于访问接口得时候处理数据,这时候切换了其他页面再切换语言导致,
- * 更新食谱的dialog的问题会空白,估做下面判断
- * */
- if (activityName.contains("ModeEntranceActivity") || activityName.contains("ModeEntrance2Activity") || activityName.contains(
- "AboutActivity"
- )
- ) {
- dialogRecipeUpdate.showUpdateTips(
- supportFragmentManager,
- "RECIPE_UPDATE_DIALOG",
- newRecipes.size.toLong()
- )
- }
- }
- } catch (e: java.lang.Exception) {
- e.printStackTrace()
- }
- }
- }
- }
- var updateRecipe = false
- private fun saveRecipeUpdateTime(recipeUpdateTime: Long?) {
- val v =
- FoodDataProvider.getUserDatabase().devConfigDao().recipeVersion() ?: DevVersion(0, 0)
- v.recipeUpdateTime = recipeUpdateTime
- FoodDataProvider.getUserDatabase().devConfigDao().saveDevVersion(v)
- //存储下载成功食谱的编号
- var strList = GsonUtils.GsonString(numberList)
- setRecipesList(strList)
- }
- fun getRecipe(context: Context){
- Thread {
- var isUpdateFile = StringUtils.doesUpdateTxtFileExist()
- //之前根据zip包的md5 更新,现在做一个文本获取进行更新, 先判断是否存在,存在再处理,不存在就走之前的方法
- Log.d("TAG update", "isUpdateFile 文件: $isUpdateFile")
- if (isUpdateFile) {
- Log.d("TAG update", "isUpdateFile 文件存在 ")
- var fileUpdate = StringUtils.getUpdateTime()
- var roomUpdate = getUpdateRecipeTime()
- Log.d("TAG update", "fileUpdate : $fileUpdate")
- Log.d("TAG update", "roomUpdate : $roomUpdate")
- FoodDataProvider.setUpdateTime(fileUpdate)
- //当本地时间为空,或者file的文件时间比本地时间大的时候,证明食谱包更新了
- if (roomUpdate == "" || fileUpdate.toLong() > roomUpdate.toLong()) {
- Log.d("TAG update", "isUpdateFile1111111-------- 文件存在 ")
- //删除room数据库
- deleteRoomDb(context)
- //删除sd卡的东西
- FoodDataProvider.deleteAll()
- FoodDataProvider.prepareData(globalApp())
- } else {
- FoodDataProvider.prepareData(globalApp())
- }
- } else {
- val md5 = getOtaFileMd5()
- val sn = getSN()
- Log.d("TAG md5", "time :" + System.currentTimeMillis())
- //大概50秒才获取到
- // val zipMd2 = StringUtils.getFileMD5("system/media/cofa_cooking.zip")
- Log.d("TAG md5", "md5 :$md5")
- var zipMd5 = ""
- if (md5.isNotEmpty()) {
- zipMd5 = FileUtils.getFileMD5ToString("system/media/cofa_cooking.zip")
- }
- Log.d("TAG md5", "time2222 :" + System.currentTimeMillis())
- Log.d("TAG md5", "string :$zipMd5")
- //处理ota食谱更新问题
- if (sn.startsWith("010") && (md5.isEmpty() || md5 != zipMd5)) {
- /**
- * 如果MD5的值不存在,重新解压
- * 如果MD5的值不一样的,就代表食谱包已经重新更新
- * 需要先删除sd卡目录下的cofa文件,再重新解压
- * */
- deleteRoomDb(context)
- //删除sd卡的东西
- FoodDataProvider.deleteAll()
- FoodDataProvider.prepareData(globalApp())
- } else {
- FoodDataProvider.prepareData(globalApp())
- }
- //010 每一次都把md5的值set进去
- if (sn.startsWith("010")) {
- //优化启动程序
- if (zipMd5.isEmpty()) {
- zipMd5 = FileUtils.getFileMD5ToString("system/media/cofa_cooking.zip")
- }
- setOtaFileMd5(zipMd5)
- }
- }
- }.start()
- }
- fun deleteRoomDb(context: Context) {
- FoodDataProvider.getUserDatabase().userInfoDao().apply {
- removeAllOnlineRecipe(CURRENT_USER_ID)
- removeAllFavouriteRecipe(CURRENT_USER_ID)
- removeAllHistoryRecipe(CURRENT_USER_ID)
- removeAllOnUserTag(CURRENT_USER_ID)
- }
- FoodDataProvider.getUserDatabase().devConfigDao().apply {
- removeAllDevVersion()
- }
- Log.d("TAG 删除room", "删除 FoodDataProvider Dao文件")
- val applicationDirectory = context.cacheDir.parent?.let { File(it) }
- if (applicationDirectory?.exists() == true) {
- val files = applicationDirectory.listFiles() ?: emptyArray()
- for (file in files) {
- //databases目录放着room 的db文件,重新解压需要删除
- if (file.name.equals("databases")) {
- Log.d("TAG 删除room", "删除 databases的room-db文件")
- FileUtils.delete(file)
- }
- }
- }
- }
- @SuppressLint("InvalidWakeLockTag")
- private fun downloadRecipes(
- newRecipes: LinkedList<String>,
- recipeUpdateDialog: RecipeUpdateDialog,
- sum: Long,
- downloadDir: String,
- downloadName: String,
- recipeUpdateTime: Long?
- ) {
- //取消标识退出
- if (!updateRecipe) {
- return
- }
- //升级休眠
- val pm = globalApp().getSystemService(Application.POWER_SERVICE) as PowerManager
- val mWakeLock = pm.newWakeLock(
- PowerManager.SCREEN_BRIGHT_WAKE_LOCK or PowerManager.ON_AFTER_RELEASE or PowerManager.ACQUIRE_CAUSES_WAKEUP,
- "tag"
- );
- mWakeLock?.setReferenceCounted(false);
- mWakeLock?.acquire(10 * 60 * 1000L /*10 minutes*/)
- TopResumedAtyHolder.getCurrentActivity()?.apply {
- if (newRecipes.isEmpty()) {
- saveRecipeUpdateTime(recipeUpdateTime)
- scopeNetLife {
- //判断是否还有新菜谱
- val result = Post<DevInfoResult>(Api.DEV_INFO) {
- body = DeviceInfoBody.genDeviceInfoBody()
- }.await()
- val ut = result.recipeUpdateTime
- val nr = LinkedList(result.newRecipes)
- if (!nr.isEmpty()) {
- downloadRecipes(
- nr, recipeUpdateDialog,
- nr.size.toLong(), downloadDir, downloadName, ut
- )
- return@scopeNetLife
- } else {
- recipeUpdateDialog.removeSelf()
- showRecipesUpdateDialog(recipeUpdateTime)
- }
- }
- return
- }
- val recipeUrl = newRecipes.pop()
- val recipeNumber = recipeUrl.split("@")[0]
- val fileUrl = recipeUrl.split("@")[1]
- recipeUpdateDialog.showUpdating(supportFragmentManager, "", sum - newRecipes.size, sum)
- scopeNetLife {
- val result = Get<File>(fileUrl) {
- setDownloadFileName(downloadName)
- setDownloadDir(downloadDir)
- addDownloadListener(object : ProgressListener() {
- override fun onProgress(p: Progress) {
- LogUtil.d("dddddd", p.toString())
- }
- })
- }.await()
- if (!result.exists()) {
- downloadRecipes(
- newRecipes,
- recipeUpdateDialog,
- sum,
- downloadDir,
- downloadName,
- recipeUpdateTime
- )
- } else {
- prepareResource(result, recipeNumber)
- downloadRecipes(
- newRecipes,
- recipeUpdateDialog,
- sum,
- downloadDir,
- downloadName,
- recipeUpdateTime
- )
- }
- }.catch {
- Log.e("TAG 下载失败11",it.message.toString())
- it.localizedMessage?.let { it1 -> Log.e("TAG 下载失败22", it1) }
- Log.e("TAG 下载失败33",it.cause?.message.toString())
- Log.e("TAG 下载失败444",it.cause?.localizedMessage.toString())
- // ToastUtils.showShort("下载失败 :" + it.toString())
- ToastUtils.showShort("Download failed")
- }
- }
- mWakeLock.release()
- }
- private fun prepareResource(file: File, recipeNumber: String) {
- try {
- val dst = ZipUtils.unzipFile(file, FoodDataProvider.getExtRecipeResourceDir())
- FileUtils.delete(file)
- if (dst.isNullOrEmpty()) {
- return
- }
- val jsonFile = FoodDataProvider.getResourceConfigJsonPath(recipeNumber)
- if (!jsonFile.exists()) {
- return
- }
- val jsonContent = FileKit.readFileToStringB(jsonFile)
- val contentData = jsonDecoder.decodeFromString<RecipeDataConfig>(jsonContent)
- contentData.resetAllCodes()
- FoodDataProvider.getDatabase().runInTransaction {
- FoodDataProvider.getDatabase().recipeDao().apply {
- var recipeList = contentData.devRecipes
- deleteDevRecipeAccessorys(recipeNumber)
- deleteDevRecipeCookingSteps(recipeNumber)
- deleteDevRecipeFoods(recipeNumber)
- deleteDevRecipeNutritions(recipeNumber)
- deleteDevRecipeRelTags(recipeNumber)
- deleteDevRecipePortionSizes(recipeNumber)
- recipeList.forEach {
- //加此判断是因为 食谱包有可能updateTime是空或者0 ,由于食谱那边有个new的排序,是需要用到updateTime,估写入的时候做判断
- if (it.updateTime==null ||it.updateTime==0L){
- it.updateTime = System.currentTimeMillis()
- }
- deleteNumAndLangRecipe(it.number, it.lang)
- }
- insertDevAccessorys(contentData.devAccessorys)
- insertHotTags(contentData.devHotTags)
- insertDevPortraits(contentData.devPortraits)
- insertDevRecipeAccessorys(contentData.devRecipeAccessorys)
- val categorys = queryAllCategory()
- val categoryMap = HashMap<String, DevRecipeCategory>()
- for (category in categorys) {
- categoryMap[category.number + ":" + category.lang] = category
- }
- for (devRecipeCategory in contentData.devRecipeCategorys) {
- if (categoryMap.containsKey(devRecipeCategory.number + ":" + devRecipeCategory.lang)) {
- devRecipeCategory.code =
- categoryMap[devRecipeCategory.number + ":" + devRecipeCategory.lang]?.code.toString()
- }
- }
- insertDevRecipeCategorys(contentData.devRecipeCategorys)
- insertDevRecipeCookingSteps(contentData.devRecipeCookingSteps)
- insertDevRecipeFoods(contentData.devRecipeFoods)
- insertDevRecipeNutritions(contentData.devRecipeNutritions)
- insertDevRecipePortionSizes(contentData.devRecipePortionSizes)
- insertDevRecipeRelTags(contentData.devRecipeRelTags)
- insertDevRecipeTags(contentData.devRecipeTags)
- insertDevRecipes(recipeList)
- //作为下载食谱的新标
- numberList.add(recipeNumber)
- }
- }
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }
- private fun showRecipesUpdateDialog(recipeUpdateTime: Long?) {
- TopResumedAtyHolder.getCurrentActivity()?.apply {
- val minute = MMkvUtils.getInt(SCREENSAVER)
- if (minute != 0) {
- Settings.System.putInt(
- contentResolver,
- Settings.System.SCREEN_OFF_TIMEOUT,
- 1000 * 60 * minute
- )
- val uri: Uri = Settings.System
- .getUriFor(Settings.System.SCREEN_OFF_TIMEOUT)
- contentResolver.notifyChange(uri, null)
- }
- EventBus.getDefault().post(NoScreenEvent(false))
- RecipeUpdateDialog().apply {
- onDialogClickListener = object : RecipeUpdateDialog.OnDialogClickListener {
- override fun onConfirm() {
- saveRecipeUpdateTime(recipeUpdateTime)
- removeSelf()
- }
- override fun onCancel() {
- }
- }
- showSuccess(supportFragmentManager, "recipeUpdateDialog")
- }
- }
- }
- }
- class NoScreenEvent(var noScreen: Boolean)
- class TuyaSoEvent()
|