FoodCookingApp.kt 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. package com.develop.foodcooking
  2. import android.annotation.SuppressLint
  3. import android.content.Context
  4. import android.content.Intent
  5. import android.content.res.Configuration
  6. import android.net.Uri
  7. import android.os.Build
  8. import android.os.Environment
  9. import android.os.PowerManager
  10. import android.provider.Settings
  11. import android.util.Log
  12. import com.blankj.utilcode.util.AppUtils
  13. import com.blankj.utilcode.util.FileUtils
  14. import com.blankj.utilcode.util.PathUtils
  15. import com.blankj.utilcode.util.ResourceUtils
  16. import com.blankj.utilcode.util.Utils
  17. import com.develop.base.app.BaseApp
  18. import com.develop.base.ext.getBrandNum
  19. import com.develop.base.ext.getOtaFileMd5
  20. import com.develop.base.ext.getSN
  21. import com.develop.base.ext.setAppCode
  22. import com.develop.base.ext.setIsBrand011A
  23. import com.develop.base.ext.setIsBrand036I
  24. import com.develop.base.ext.setIsBrand054A
  25. import com.develop.base.ext.setIsBrand062
  26. import com.develop.base.ext.setNightTheme
  27. import com.develop.base.ext.setOtaFileMd5
  28. import com.develop.base.util.MMkvUtils
  29. import com.develop.common.bean.TuyaEvent
  30. import com.develop.common.data_repo.FoodDataProvider
  31. import com.develop.common.data_repo.net.Api
  32. import com.develop.common.data_repo.net.converter.SerializationConverter
  33. import com.develop.common.data_repo.net.interceptor.FoodRequestInterceptor
  34. import com.develop.common.food_sdk.GlobalDevEvent
  35. import com.develop.common.food_sdk.SerialPortUtils
  36. import com.develop.common.tag.MODEL
  37. import com.develop.common.utils.StringUtils
  38. import com.develop.common.utils.TuyaUtils
  39. import com.develop.common.utils.compat.RecyclerViewCompat
  40. import com.develop.common.utils.compat.ShapeableImageViewCompat
  41. import com.develop.common.utils.compat.SmartRefreshLayoutCompat
  42. import com.develop.common.utils.compat.StartViewCompat
  43. import com.drake.net.convert.NetConverter
  44. import com.drake.net.interceptor.RequestInterceptor
  45. import com.drake.net.interfaces.NetErrorHandler
  46. import com.drake.net.time.Interval
  47. import com.kuyuntech.cofarcooking.device.sdk.constant.core.DevStatus
  48. import com.kuyuntech.cofarcooking.device.sdk.eventbus.event.DevPromptEvent
  49. import com.kuyuntech.cofarcooking.device.sdk.eventbus.event.DevStatusEvent
  50. import com.kuyuntech.cofarcooking.device.sdk.util.core.CofarSDK
  51. import org.alee.component.skin.compat.ConstraintLayoutCompat
  52. import org.alee.component.skin.page.WindowManager
  53. import org.alee.component.skin.service.Config
  54. import org.alee.component.skin.service.IOptionFactory
  55. import org.alee.component.skin.service.IThemeSkinOption
  56. import org.alee.component.skin.service.ThemeSkinService
  57. import org.greenrobot.eventbus.EventBus
  58. import org.greenrobot.eventbus.Subscribe
  59. import java.io.File
  60. import java.lang.reflect.Method
  61. import java.security.cert.X509Certificate
  62. import java.util.Locale
  63. import java.util.concurrent.TimeUnit
  64. import javax.net.ssl.TrustManager
  65. class FoodCookingApp : BaseApp() {
  66. companion object {
  67. init {
  68. Config.getInstance().skinMode = Config.SkinMode.REPLACE_ALL
  69. Config.getInstance().performanceMode = Config.PerformanceMode.EXPERIENCE_FIRST
  70. ConstraintLayoutCompat.init()
  71. RecyclerViewCompat.init()
  72. SmartRefreshLayoutCompat.init()
  73. ShapeableImageViewCompat.init()
  74. StartViewCompat.init()
  75. }
  76. }
  77. var mWakeLock: PowerManager.WakeLock? = null
  78. private lateinit var pm: PowerManager
  79. var minute = 0
  80. private var heartBeatInterval: Interval? = null
  81. var ledLock = false
  82. override fun onCreate() {
  83. hookWebView()
  84. super.onCreate()
  85. //处理崩溃问题
  86. // CrashHandler.getInstance().init(this);
  87. //FoodDataProvider.initFoodDataBase()
  88. WindowManager.getInstance().init(this, OptionFactory())
  89. setAppCode(BuildConfig.appCode)
  90. val isNight = BuildConfig.UpdatePlatform.equals("night")
  91. val is062 = BuildConfig.UpdatePlatform.equals("062A")
  92. val is011 = BuildConfig.UpdatePlatform.equals("011A")
  93. setIsBrand036I(BuildConfig.UpdatePlatform.equals("036I"))
  94. setIsBrand054A(BuildConfig.UpdatePlatform.equals("054A"))
  95. setIsBrand011A(is011)
  96. setIsBrand062(is062)
  97. if (BuildConfig.brandCode.startsWith("010")){
  98. MMkvUtils.save("appTime", BuildConfig.time)
  99. }
  100. if (is062) {
  101. ResourceUtils.copyFileFromAssets(
  102. ASSETS_BLUE_SKIN_PACK,
  103. SKIN_PACK_PATH + BLUE_SKIN_PACK_NAME
  104. )
  105. }
  106. if (is011) {
  107. ResourceUtils.copyFileFromAssets(
  108. ASSETS_ZERO_ONE_ONE_SKIN_PACK,
  109. SKIN_PACK_PATH + ZERO_ONE_ONE_SKIN_PACK_NAME
  110. )
  111. }
  112. if (isNight) {
  113. ResourceUtils.copyFileFromAssets(
  114. ASSETS_NIGHT_SKIN_PACK,
  115. SKIN_PACK_PATH + NIGHT_SKIN_PACK_NAME
  116. )
  117. }
  118. //切换主题,theme=0 night= false 是0000的主题,而且需要AndroidManifest.xml主题设置为 android:theme="@style/SplashTheme"
  119. ThemeSkinService.getInstance()
  120. .switchThemeSkin(if (isNight) 1 else if (is062) 2 else if (is011) 3 else 0)
  121. setNightTheme(isNight)
  122. CofarSDK.init(getBrandNum())
  123. SerialPortUtils.init()
  124. CofarSDK.register(this)
  125. CofarSDK.stopNative()
  126. // val powerManager = getSystemService(POWER_SERVICE) as PowerManager
  127. // val wakeLock: PowerManager.WakeLock =
  128. // powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "motionDetection:keepAwake")
  129. // wakeLock.acquire()
  130. pm = getSystemService(POWER_SERVICE) as PowerManager
  131. minute = MMkvUtils.getInt("ScreenSaver")
  132. if (minute == 0) {
  133. minute = 5
  134. }
  135. Settings.System.putInt(
  136. contentResolver,
  137. Settings.System.SCREEN_OFF_TIMEOUT,
  138. (1000 * 60 * minute).toInt()
  139. )
  140. Settings.Secure.putInt(contentResolver, Settings.Secure.INSTALL_NON_MARKET_APPS, 1)
  141. val uri: Uri = Settings.System
  142. .getUriFor(Settings.System.SCREEN_OFF_TIMEOUT)
  143. contentResolver.notifyChange(uri, null)
  144. heartBeatInterval = Interval(1, 1, TimeUnit.SECONDS, 5).finish {
  145. //设备不通讯异常
  146. EventBus.getDefault().post(
  147. DevPromptEvent.builder()
  148. .showCancelBtn(false)
  149. .msg("dev_error")
  150. .focus(true)
  151. .build()
  152. )
  153. }.start()
  154. var md5 = getOtaFileMd5()
  155. var sn = getSN()
  156. //处理ota食谱更新问题
  157. // if (sn.startsWith("010")&& getOtaFileMd5().isNotEmpty()
  158. // && md5 != StringUtils.getFileMD5("system/media/cofa_cooking.zip")){
  159. // //先删除sd卡目录下的cofa文件
  160. // FileUtils.delete(File(Environment.getExternalStorageDirectory(),"cofa_cooking"))
  161. //
  162. // FoodDataProvider.prepareData(this)
  163. // }else{
  164. // FoodDataProvider.prepareData(this)
  165. // }
  166. // //010 每一次都把md5的值set进去
  167. // if (sn.startsWith("010")){
  168. // setOtaFileMd5(StringUtils.getFileMD5("system/media/cofa_cooking.zip"))
  169. //
  170. // }
  171. }
  172. fun hookWebView() {
  173. val TAG = "ASDD"
  174. val sdkInt = Build.VERSION.SDK_INT
  175. try {
  176. val factoryClass = Class.forName("android.webkit.WebViewFactory")
  177. val field = factoryClass.getDeclaredField("sProviderInstance")
  178. field.isAccessible = true
  179. var sProviderInstance = field[null]
  180. if (sProviderInstance != null) {
  181. Log.d(TAG, "sProviderInstance isn't null")
  182. return
  183. }
  184. val getProviderClassMethod: Method
  185. getProviderClassMethod = if (sdkInt > 22) {
  186. factoryClass.getDeclaredMethod("getProviderClass")
  187. } else if (sdkInt == 22) {
  188. factoryClass.getDeclaredMethod("getFactoryClass")
  189. } else {
  190. Log.d(TAG, "Don't need to Hook WebView")
  191. return
  192. }
  193. getProviderClassMethod.isAccessible = true
  194. val providerClass = getProviderClassMethod.invoke(factoryClass) as Class<*>
  195. val delegateClass = Class.forName("android.webkit.WebViewDelegate")
  196. val providerConstructor = providerClass.getConstructor(delegateClass)
  197. if (providerConstructor != null) {
  198. providerConstructor.isAccessible = true
  199. val declaredConstructor = delegateClass.getDeclaredConstructor()
  200. declaredConstructor.isAccessible = true
  201. sProviderInstance =
  202. providerConstructor.newInstance(declaredConstructor.newInstance())
  203. field["sProviderInstance"] = sProviderInstance
  204. }
  205. Log.d(TAG, "Hook done!")
  206. } catch (e: Throwable) {
  207. }
  208. }
  209. override fun createHostUrl(): String {
  210. return Api.HOST
  211. }
  212. override fun createRequestInterceptor(): RequestInterceptor {
  213. return FoodRequestInterceptor()
  214. }
  215. override fun createConverter(): NetConverter {
  216. return SerializationConverter()
  217. }
  218. override fun createErrorHandle(): NetErrorHandler {
  219. return NetErrorHandler.DEFAULT
  220. }
  221. override fun attachBaseContext(base: Context?) {
  222. super.attachBaseContext(base)
  223. //把这个方法放到onCreate 处理ota问题
  224. FoodDataProvider.prepareData(this)
  225. }
  226. override fun onTerminate() {
  227. super.onTerminate()
  228. SerialPortUtils.destroy()
  229. CofarSDK.unregister(this)
  230. }
  231. @SuppressLint("InvalidWakeLockTag")
  232. @Subscribe
  233. fun onTuyaEvent(event: TuyaEvent) {
  234. TuyaUtils.uploadData()
  235. heartBeatInterval?.cancel()
  236. val pm = getSystemService(POWER_SERVICE) as PowerManager
  237. if (mWakeLock == null) {
  238. mWakeLock = pm.newWakeLock(
  239. PowerManager.SCREEN_BRIGHT_WAKE_LOCK or PowerManager.ON_AFTER_RELEASE or PowerManager.ACQUIRE_CAUSES_WAKEUP,
  240. "tag"
  241. );
  242. mWakeLock?.setReferenceCounted(false);
  243. mWakeLock?.acquire()
  244. }
  245. mWakeLock?.release()
  246. mWakeLock = null
  247. val intent = Intent()
  248. intent.action = "android.intent.action.SS_DEVICE_TOUCH"
  249. sendBroadcast(intent)
  250. }
  251. // @Subscribe
  252. // fun onCookDevMsgEvent(event: DevPromptEvent) {
  253. //
  254. //
  255. // }
  256. @SuppressLint("InvalidWakeLockTag")
  257. @Subscribe
  258. @Synchronized
  259. fun globalCoverEvent(event: DevStatusEvent) {
  260. TuyaUtils.uploadData()
  261. heartBeatInterval?.cancel()
  262. val devInfo = event.devInfo;
  263. val pm = getSystemService(POWER_SERVICE) as PowerManager
  264. if (devInfo.status == DevStatus.RUNNING.toInt() || devInfo.isWeightStatus) {
  265. if (mWakeLock == null) {
  266. mWakeLock = pm.newWakeLock(
  267. PowerManager.SCREEN_BRIGHT_WAKE_LOCK or PowerManager.ON_AFTER_RELEASE or PowerManager.ACQUIRE_CAUSES_WAKEUP,
  268. "tag"
  269. );
  270. mWakeLock?.setReferenceCounted(false);
  271. mWakeLock?.acquire()
  272. }
  273. } else if (devInfo.status != DevStatus.RUNNING.toInt()) {
  274. if (mWakeLock != null) {
  275. mWakeLock?.release()
  276. mWakeLock = null
  277. val intent = Intent()
  278. intent.action = "android.intent.action.SS_DEVICE_TOUCH"
  279. sendBroadcast(intent)
  280. }
  281. }
  282. // if (!ledLock) {
  283. // //devInfo.potStatus 0是有锅 1是没锅
  284. // //devInfo.potCloverStatus 0是合盖,1是没盒盖
  285. // ledLock = true;
  286. // //屏幕暗
  287. // if (!pm.isScreenOn) {
  288. //
  289. // //合盖
  290. // if (devInfo.potCloverStatus.toInt() == 0) {
  291. // CofarSDK.flashWhiteRedLed()
  292. // } else {
  293. // CofarSDK.switchWhiteLed('0');
  294. // CofarSDK.flashRedLed()
  295. // }
  296. //
  297. // } else {
  298. // //屏幕亮
  299. // if (devInfo.status == DevStatus.STOP.toInt()) {
  300. //
  301. // if (devInfo.potStatus.toInt() == 0) {
  302. // if (devInfo.potCloverStatus.toInt() == 0) {
  303. // CofarSDK.flashWhiteRedLed()
  304. // } else {
  305. // CofarSDK.switchWhiteLed('0');
  306. // CofarSDK.flashRedLed()
  307. // }
  308. // } else {
  309. // CofarSDK.switchWhiteLed('0');
  310. // CofarSDK.flashRedLed();
  311. // }
  312. //
  313. // }
  314. //
  315. // if (devInfo.status == DevStatus.RUNNING.toInt()) {
  316. //
  317. // if (devInfo.temp < 60) {
  318. // CofarSDK.switchRedLed('0');
  319. // CofarSDK.switchWhiteLed('1');
  320. // } else {
  321. // CofarSDK.switchRedLed('1');
  322. // CofarSDK.switchWhiteLed('0');
  323. // }
  324. //
  325. // }
  326. //
  327. // if (devInfo.status == DevStatus.PAUSE.toInt()) {
  328. //
  329. // //判断盖子是否打开
  330. // //合盖
  331. // if (devInfo.potCloverStatus.toInt() == 1) {
  332. // CofarSDK.switchWhiteLed('0');
  333. // CofarSDK.flashRedLed()
  334. // } else {
  335. // CofarSDK.flashWhiteRedLed()
  336. // }
  337. //
  338. //
  339. // }
  340. // }
  341. // ledLock = false;
  342. // }
  343. GlobalDevEvent.globalCoverEvent(event, pm)
  344. }
  345. }
  346. class OptionFactory : IOptionFactory {
  347. override fun defaultTheme(): Int {
  348. return 0
  349. }
  350. override fun requireOption(theme: Int): IThemeSkinOption? {
  351. return when (theme) {
  352. 1 -> NightOption()
  353. 2 -> BlueOption()
  354. 3 -> ZeroOneOneOption()
  355. else -> null
  356. }
  357. }
  358. }
  359. class NightOption : IThemeSkinOption {
  360. override fun getStandardSkinPackPath(): LinkedHashSet<String> {
  361. val pathSet = LinkedHashSet<String>()
  362. pathSet.add(SKIN_PACK_PATH + NIGHT_SKIN_PACK_NAME)
  363. return pathSet
  364. }
  365. }
  366. class BlueOption : IThemeSkinOption {
  367. override fun getStandardSkinPackPath(): LinkedHashSet<String> {
  368. val pathSet = LinkedHashSet<String>()
  369. pathSet.add(SKIN_PACK_PATH + BLUE_SKIN_PACK_NAME)
  370. return pathSet
  371. }
  372. }
  373. class ZeroOneOneOption : IThemeSkinOption {
  374. override fun getStandardSkinPackPath(): LinkedHashSet<String> {
  375. val pathSet = LinkedHashSet<String>()
  376. pathSet.add(SKIN_PACK_PATH + ZERO_ONE_ONE_SKIN_PACK_NAME)
  377. return pathSet
  378. }
  379. }
  380. const val NIGHT_SKIN_PACK_NAME = "night.skin"
  381. const val ASSETS_NIGHT_SKIN_PACK = "skins/night.skin"
  382. const val BLUE_SKIN_PACK_NAME = "blue.skin"
  383. const val ASSETS_BLUE_SKIN_PACK = "skins/blue.skin"
  384. const val ZERO_ONE_ONE_SKIN_PACK_NAME = "zeroOneOne.skin"
  385. const val ASSETS_ZERO_ONE_ONE_SKIN_PACK = "skins/zeroOneOne.skin"
  386. /**
  387. * 应用存储空间根路径
  388. */
  389. private val ROOT_PATH =
  390. Utils.getApp().getExternalFilesDir(null)?.absolutePath?.run { this + File.separator }
  391. ?: (PathUtils.getExternalAppDataPath() + "." + AppUtils.getAppPackageName() + File.separator)
  392. /**
  393. * 皮肤包根路径
  394. */
  395. val SKIN_PACK_PATH = ROOT_PATH + ".SkinPack" + File.separator