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 androidx.core.content.ContextCompat.getSystemService import com.azhon.appupdate.listener.OnDownloadListener import com.azhon.appupdate.util.LogUtil import com.blankj.utilcode.util.FileUtils import com.blankj.utilcode.util.ZipUtils import com.develop.base.ext.fromJson import com.develop.base.ext.globalApp 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.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.* import kotlin.collections.ArrayList import kotlin.collections.HashMap object AppVersionUtil { fun checkRecipeUpdate(shoNoUpdateDialog: Boolean = false) { TopResumedAtyHolder.getCurrentActivity()?.apply { scopeNetLife { try { val result = Post(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() { } } } 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()) { val dialog = RecipeUpdateDialog() dialog.onDialogClickListener = object : RecipeUpdateDialog.OnDialogClickListener { override fun onConfirm() { updateRecipe = !updateRecipe EventBus.getDefault().post(NoScreenEvent(true)) downloadRecipes( newRecipes, dialog, newRecipes.size.toLong(), downloadDir, downloadName, recipeUpdateTime ) } override fun onCancel() { } } dialog.showUpdateTips( supportFragmentManager, "RECIPE_UPDATE_DIALOG", newRecipes.size.toLong() ) } } } catch (e: java.lang.Exception) { e.printStackTrace() } } } } var updateRecipe = false @SuppressLint("InvalidWakeLockTag") private fun downloadRecipes( newRecipes: LinkedList, 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()) { 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(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 ) } } } 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.readFileToString(jsonFile) val contentData = jsonDecoder.decodeFromString(jsonContent) contentData.resetAllCodes() FoodDataProvider.getDatabase().runInTransaction { FoodDataProvider.getDatabase().recipeDao().apply { deleteDevRecipeAccessorys(recipeNumber) deleteDevRecipeCookingSteps(recipeNumber) deleteDevRecipeFoods(recipeNumber) deleteDevRecipeNutritions(recipeNumber) deleteDevRecipeRelTags(recipeNumber) deleteDevRecipePortionSizes(recipeNumber) deleteRecipe(recipeNumber) insertDevAccessorys(contentData.devAccessorys) insertHotTags(contentData.devHotTags) insertDevPortraits(contentData.devPortraits) insertDevRecipeAccessorys(contentData.devRecipeAccessorys) val categorys = queryAllCategory() val categoryMap = HashMap() 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(contentData.devRecipes) } } } 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() { val v = FoodDataProvider.getUserDatabase().devConfigDao().recipeVersion() ?: DevVersion(0, 0) v.recipeUpdateTime = recipeUpdateTime FoodDataProvider.getUserDatabase().devConfigDao().saveDevVersion(v) removeSelf() } override fun onCancel() { } } showSuccess(supportFragmentManager, "recipeUpdateDialog") } } } } class NoScreenEvent(var noScreen: Boolean)