From 16d3543696aef9fb6d7e8a872feb21f948927f6b Mon Sep 17 00:00:00 2001 From: fankesyooni Date: Wed, 1 Jun 2022 00:33:10 +0800 Subject: [PATCH] Merge module and host receiver to new api --- .../fankes/apperrorstracking/const/Const.kt | 78 -------- .../hook/entity/FrameworkHooker.kt | 117 +++--------- .../ui/activity/base/BaseActivity.kt | 9 - .../errors/AppErrorsDetailActivity.kt | 10 +- .../errors/AppErrorsRecordActivity.kt | 2 +- .../ui/activity/main/MainActivity.kt | 8 +- .../utils/factory/FunctionFactory.kt | 10 +- .../utils/tool/FrameworkTool.kt | 168 ++++++++---------- 8 files changed, 119 insertions(+), 283 deletions(-) delete mode 100644 app/src/main/java/com/fankes/apperrorstracking/const/Const.kt diff --git a/app/src/main/java/com/fankes/apperrorstracking/const/Const.kt b/app/src/main/java/com/fankes/apperrorstracking/const/Const.kt deleted file mode 100644 index c041dc2..0000000 --- a/app/src/main/java/com/fankes/apperrorstracking/const/Const.kt +++ /dev/null @@ -1,78 +0,0 @@ -/* - * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. - * Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com) - * https://github.com/KitsunePie/AppErrorsTracking - * - * This software is non-free but opensource software: you can redistribute it - * and/or modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * and eula along with this software. If not, see - * - * - * This file is Created by fankes on 2022/5/12. - */ -@file:Suppress("MemberVisibilityCanBePrivate") - -package com.fankes.apperrorstracking.const - -import com.fankes.apperrorstracking.BuildConfig -import com.fankes.apperrorstracking.bean.AppErrorsInfoBean - -/** - * 全局常量 - */ -object Const { - - /** 当前模块的包名 */ - const val MODULE_PACKAGE_NAME = BuildConfig.APPLICATION_ID - - /** 当前模块的版本名称 */ - const val MODULE_VERSION_NAME = BuildConfig.VERSION_NAME - - /** 当前模块的版本号 */ - const val MODULE_VERSION_CODE = BuildConfig.VERSION_CODE - - /** 当前模块的版本校验 */ - const val MODULE_VERSION_VERIFY = "${MODULE_VERSION_NAME}_${MODULE_VERSION_CODE}_202205141842" - - /** [AppErrorsInfoBean] 传值 */ - const val EXTRA_APP_ERRORS_INFO = "app_errors_info_extra" - - /** 模块接收广播 */ - const val ACTION_MODULE_HANDLER_RECEIVER = "module_handler_action" - - /** 宿主接收广播 */ - const val ACTION_HOST_HANDLER_RECEIVER = "host_handler_action" - - /** 模块与宿主交互数据 */ - const val KEY_MODULE_HOST_FETCH = "module_host_data_fetch_key" - - /** 校验模块宿主版本一致性 */ - const val TYPE_MODULE_VERSION_VERIFY = "module_version_verify_type" - - /** 获取 [AppErrorsInfoBean] 数据 */ - const val TYPE_APP_ERRORS_DATA_GET = "app_errors_data_get_type" - - /** 清空 [AppErrorsInfoBean] 数据 */ - const val TYPE_APP_ERRORS_DATA_CLEAR = "app_errors_data_clear_type" - - /** 删除指定 [AppErrorsInfoBean] 数据 */ - const val TYPE_APP_ERRORS_DATA_REMOVE = "app_errors_data_remove_type" - - /** 当前模块的版本校验标签 */ - const val TAG_MODULE_VERSION_VERIFY = "module_version_verify_tag" - - /** 获取到的 [AppErrorsInfoBean] 数据内容 */ - const val TAG_APP_ERRORS_DATA_GET_CONTENT = "app_errors_data_get_content_tag" - - /** 指定删除的 [AppErrorsInfoBean] 数据内容 */ - const val TAG_APP_ERRORS_DATA_REMOVE_CONTENT = "app_errors_data_remove_content_tag" -} \ No newline at end of file diff --git a/app/src/main/java/com/fankes/apperrorstracking/hook/entity/FrameworkHooker.kt b/app/src/main/java/com/fankes/apperrorstracking/hook/entity/FrameworkHooker.kt index 89c99a2..3be0652 100644 --- a/app/src/main/java/com/fankes/apperrorstracking/hook/entity/FrameworkHooker.kt +++ b/app/src/main/java/com/fankes/apperrorstracking/hook/entity/FrameworkHooker.kt @@ -24,10 +24,8 @@ package com.fankes.apperrorstracking.hook.entity import android.app.ApplicationErrorReport -import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import android.content.IntentFilter import android.content.pm.ApplicationInfo import android.graphics.Color import android.os.Message @@ -41,18 +39,17 @@ import android.widget.TextView import androidx.core.content.res.ResourcesCompat import com.fankes.apperrorstracking.R import com.fankes.apperrorstracking.bean.AppErrorsInfoBean -import com.fankes.apperrorstracking.const.Const import com.fankes.apperrorstracking.locale.LocaleString import com.fankes.apperrorstracking.ui.activity.errors.AppErrorsDetailActivity import com.fankes.apperrorstracking.utils.drawable.drawabletoolbox.DrawableBuilder import com.fankes.apperrorstracking.utils.factory.* +import com.fankes.apperrorstracking.utils.tool.FrameworkTool import com.highcapable.yukihookapi.hook.bean.VariousClass import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker import com.highcapable.yukihookapi.hook.factory.field import com.highcapable.yukihookapi.hook.factory.hasMethod import com.highcapable.yukihookapi.hook.factory.method import com.highcapable.yukihookapi.hook.log.loggerE -import com.highcapable.yukihookapi.hook.type.android.ActivityThreadClass import com.highcapable.yukihookapi.hook.type.android.MessageClass object FrameworkHooker : YukiBaseHooker() { @@ -87,75 +84,6 @@ object FrameworkHooker : YukiBaseHooker() { /** 已记录的 APP 异常信息数组 - 直到重新启动 */ private val appErrorsRecords = arrayListOf() - /** 是否已经注册广播 */ - private var isRegisterReceiver = false - - /** 用户解锁屏幕广播接收器 */ - private val userPresentReceiver by lazy { - object : BroadcastReceiver() { - override fun onReceive(context: Context?, intent: Intent?) { - /** 解锁后清空已记录的忽略错误 APP */ - ignoredErrorsIfUnlockApps.clear() - } - } - } - - /** 语言区域改变广播接收器 */ - private val localeChangedReceiver by lazy { - object : BroadcastReceiver() { - override fun onReceive(context: Context?, intent: Intent?) { - /** 刷新模块 Resources 缓存 */ - refreshModuleAppResources() - } - } - } - - /** 宿主广播接收器 */ - private val hostHandlerReceiver by lazy { - object : BroadcastReceiver() { - override fun onReceive(context: Context?, intent: Intent?) { - if (intent == null) return - intent.getStringExtra(Const.KEY_MODULE_HOST_FETCH)?.also { - if (it.isNotBlank()) context?.sendBroadcast(Intent().apply { - action = Const.ACTION_MODULE_HANDLER_RECEIVER - when (it) { - Const.TYPE_MODULE_VERSION_VERIFY -> { - putExtra(Const.TAG_MODULE_VERSION_VERIFY, Const.MODULE_VERSION_VERIFY) - putExtra(Const.KEY_MODULE_HOST_FETCH, Const.TYPE_MODULE_VERSION_VERIFY) - } - Const.TYPE_APP_ERRORS_DATA_GET -> { - putExtra(Const.TAG_APP_ERRORS_DATA_GET_CONTENT, appErrorsRecords) - putExtra(Const.KEY_MODULE_HOST_FETCH, Const.TYPE_APP_ERRORS_DATA_GET) - } - Const.TYPE_APP_ERRORS_DATA_REMOVE -> { - runCatching { intent.getSerializableExtra(Const.TAG_APP_ERRORS_DATA_REMOVE_CONTENT) as? AppErrorsInfoBean? } - .getOrNull()?.also { e -> appErrorsRecords.remove(e) } - putExtra(Const.KEY_MODULE_HOST_FETCH, Const.TYPE_APP_ERRORS_DATA_REMOVE) - } - Const.TYPE_APP_ERRORS_DATA_CLEAR -> { - appErrorsRecords.clear() - putExtra(Const.KEY_MODULE_HOST_FETCH, Const.TYPE_APP_ERRORS_DATA_CLEAR) - } - else -> {} - } - }) - } - } - } - } - - /** - * 注册广播接收器 - * @param context 实例 - */ - private fun registerReceiver(context: Context) { - if (isRegisterReceiver) return - context.registerReceiver(userPresentReceiver, IntentFilter().apply { addAction(Intent.ACTION_USER_PRESENT) }) - context.registerReceiver(localeChangedReceiver, IntentFilter().apply { addAction(Intent.ACTION_LOCALE_CHANGED) }) - context.registerReceiver(hostHandlerReceiver, IntentFilter().apply { addAction(Const.ACTION_HOST_HANDLER_RECEIVER) }) - isRegisterReceiver = true - } - /** * 获取最新的 APP 错误信息 * @param packageName 包名 @@ -195,17 +123,24 @@ object FrameworkHooker : YukiBaseHooker() { setOnClickListener { it() } } - override fun onHook() { - /** 注入全局监听 */ - ActivityThreadClass.hook { - injectMember { - method { - name = "currentApplication" - emptyParam() - } - afterHook { result()?.let { registerReceiver(it) } } - } + /** 注册 */ + private fun register() { + onAppLifecycle { + /** 解锁后清空已记录的忽略错误 APP */ + registerReceiver(Intent.ACTION_USER_PRESENT) { _, _ -> ignoredErrorsIfUnlockApps.clear() } + /** 刷新模块 Resources 缓存 */ + registerReceiver(Intent.ACTION_LOCALE_CHANGED) { _, _ -> refreshModuleAppResources() } } + FrameworkTool.Host.with(instance = this) { + onPushAppErrorsInfoData { appErrorsRecords } + onRemoveAppErrorsInfoData { appErrorsRecords.remove(it) } + onClearAppErrorsInfoData { appErrorsRecords.clear() } + } + } + + override fun onHook() { + /** 注册 */ + register() /** 干掉原生错误对话框 - 如果有 */ ErrorDialogControllerClass.hook { injectMember { @@ -363,19 +298,19 @@ object FrameworkHooker : YukiBaseHooker() { (crashInfo.exceptionClassName.lowercase() == "native crash").also { isNativeCrash -> appErrorsRecords.add( 0, AppErrorsInfoBean( - packageName = appInfo?.packageName ?: "", + packageName = appInfo?.packageName ?: "null", isNativeCrash = isNativeCrash, - exceptionClassName = crashInfo.exceptionClassName ?: "", + exceptionClassName = crashInfo.exceptionClassName ?: "null", exceptionMessage = if (isNativeCrash) crashInfo.stackTrace.let { if (it.contains(other = "Abort message: '")) runCatching { it.split("Abort message: '")[1].split("'")[0] }.getOrNull() - ?: crashInfo.exceptionMessage ?: "" else crashInfo.exceptionMessage ?: "" - } else crashInfo.exceptionMessage ?: "", - throwFileName = crashInfo.throwFileName ?: "", - throwClassName = crashInfo.throwClassName ?: "", - throwMethodName = crashInfo.throwMethodName ?: "", + ?: crashInfo.exceptionMessage ?: "" else crashInfo.exceptionMessage ?: "null" + } else crashInfo.exceptionMessage ?: "null", + throwFileName = crashInfo.throwFileName ?: "null", + throwClassName = crashInfo.throwClassName ?: "null", + throwMethodName = crashInfo.throwMethodName ?: "null", throwLineNumber = crashInfo.throwLineNumber, - stackTrace = crashInfo.stackTrace?.trim() ?: "", + stackTrace = crashInfo.stackTrace?.trim() ?: "null", timestamp = System.currentTimeMillis() ) ) diff --git a/app/src/main/java/com/fankes/apperrorstracking/ui/activity/base/BaseActivity.kt b/app/src/main/java/com/fankes/apperrorstracking/ui/activity/base/BaseActivity.kt index c9b6adc..057f40c 100644 --- a/app/src/main/java/com/fankes/apperrorstracking/ui/activity/base/BaseActivity.kt +++ b/app/src/main/java/com/fankes/apperrorstracking/ui/activity/base/BaseActivity.kt @@ -31,7 +31,6 @@ import androidx.core.view.ViewCompat import androidx.viewbinding.ViewBinding import com.fankes.apperrorstracking.R import com.fankes.apperrorstracking.utils.factory.isNotSystemInDarkMode -import com.fankes.apperrorstracking.utils.tool.FrameworkTool import com.highcapable.yukihookapi.hook.factory.method import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass import java.lang.reflect.ParameterizedType @@ -64,18 +63,10 @@ abstract class BaseActivity : AppCompatActivity() { window?.navigationBarColor = it if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) window?.navigationBarDividerColor = it } - /** 注册 */ - FrameworkTool.registerReceiver(context = this) /** 装载子类 */ onCreate() } /** 回调 [onCreate] 方法 */ abstract fun onCreate() - - override fun onDestroy() { - super.onDestroy() - /** 取消 */ - FrameworkTool.unregisterReceiver(context = this) - } } \ No newline at end of file diff --git a/app/src/main/java/com/fankes/apperrorstracking/ui/activity/errors/AppErrorsDetailActivity.kt b/app/src/main/java/com/fankes/apperrorstracking/ui/activity/errors/AppErrorsDetailActivity.kt index 03aae2a..d80ad03 100644 --- a/app/src/main/java/com/fankes/apperrorstracking/ui/activity/errors/AppErrorsDetailActivity.kt +++ b/app/src/main/java/com/fankes/apperrorstracking/ui/activity/errors/AppErrorsDetailActivity.kt @@ -34,7 +34,6 @@ import android.view.WindowManager import androidx.core.view.isGone import com.fankes.apperrorstracking.R import com.fankes.apperrorstracking.bean.AppErrorsInfoBean -import com.fankes.apperrorstracking.const.Const import com.fankes.apperrorstracking.databinding.ActivityAppErrorsDetailBinding import com.fankes.apperrorstracking.locale.LocaleString import com.fankes.apperrorstracking.ui.activity.base.BaseActivity @@ -48,6 +47,9 @@ class AppErrorsDetailActivity : BaseActivity() { /** 请求保存文件回调标识 */ private const val WRITE_REQUEST_CODE = 0 + /** [AppErrorsInfoBean] 传值 */ + private const val EXTRA_APP_ERRORS_INFO = "app_errors_info_extra" + /** * 启动 [AppErrorsDetailActivity] * @param context 实例 @@ -55,7 +57,7 @@ class AppErrorsDetailActivity : BaseActivity() { * @param isOutSide 是否从外部启动 */ fun start(context: Context, appErrorsInfo: AppErrorsInfoBean, isOutSide: Boolean = false) = - context.navigate(isOutSide) { putExtra(Const.EXTRA_APP_ERRORS_INFO, appErrorsInfo) } + context.navigate(isOutSide) { putExtra(EXTRA_APP_ERRORS_INFO, appErrorsInfo) } } /** 预导出的异常堆栈 */ @@ -86,7 +88,7 @@ class AppErrorsDetailActivity : BaseActivity() { } override fun onCreate() { - val appErrorsInfo = runCatching { intent?.getSerializableExtra(Const.EXTRA_APP_ERRORS_INFO) as? AppErrorsInfoBean }.getOrNull() + val appErrorsInfo = runCatching { intent?.getSerializableExtra(EXTRA_APP_ERRORS_INFO) as? AppErrorsInfoBean }.getOrNull() ?: return toastAndFinish() binding.appInfoItem.setOnClickListener { openSelfSetting(appErrorsInfo.packageName) } binding.titleBackIcon.setOnClickListener { onBackPressed() } @@ -144,7 +146,7 @@ class AppErrorsDetailActivity : BaseActivity() { } override fun onBackPressed() { - intent?.removeExtra(Const.EXTRA_APP_ERRORS_INFO) + intent?.removeExtra(EXTRA_APP_ERRORS_INFO) finish() } diff --git a/app/src/main/java/com/fankes/apperrorstracking/ui/activity/errors/AppErrorsRecordActivity.kt b/app/src/main/java/com/fankes/apperrorstracking/ui/activity/errors/AppErrorsRecordActivity.kt index d5f0f31..5f5784d 100644 --- a/app/src/main/java/com/fankes/apperrorstracking/ui/activity/errors/AppErrorsRecordActivity.kt +++ b/app/src/main/java/com/fankes/apperrorstracking/ui/activity/errors/AppErrorsRecordActivity.kt @@ -82,7 +82,7 @@ class AppErrorsRecordActivity : BaseActivity() { } } /** 设置列表元素和 Adapter */ - binding.listView.apply { + binding.listView.apply { // 改成 recycleview? adapter = object : BaseAdapter() { override fun getCount() = listData.size diff --git a/app/src/main/java/com/fankes/apperrorstracking/ui/activity/main/MainActivity.kt b/app/src/main/java/com/fankes/apperrorstracking/ui/activity/main/MainActivity.kt index 9f11f30..f071eb1 100644 --- a/app/src/main/java/com/fankes/apperrorstracking/ui/activity/main/MainActivity.kt +++ b/app/src/main/java/com/fankes/apperrorstracking/ui/activity/main/MainActivity.kt @@ -27,8 +27,8 @@ import android.content.ComponentName import android.content.pm.PackageManager import android.os.Build import androidx.core.view.isVisible +import com.fankes.apperrorstracking.BuildConfig import com.fankes.apperrorstracking.R -import com.fankes.apperrorstracking.const.Const import com.fankes.apperrorstracking.data.DataConst import com.fankes.apperrorstracking.databinding.ActivityMainBinding import com.fankes.apperrorstracking.locale.LocaleString @@ -44,7 +44,7 @@ class MainActivity : BaseActivity() { private var isModuleValied = false override fun onCreate() { - binding.mainTextVersion.text = LocaleString.moduleVersion(Const.MODULE_VERSION_NAME) + binding.mainTextVersion.text = LocaleString.moduleVersion(BuildConfig.VERSION_NAME) binding.mainTextSystemVersion.text = LocaleString.systemVersion("${Build.VERSION.RELEASE} (API ${Build.VERSION.SDK_INT}) ${Build.DISPLAY}") binding.hideIconInLauncherSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_HIDE_ICON) @@ -52,7 +52,7 @@ class MainActivity : BaseActivity() { if (btn.isPressed.not()) return@setOnCheckedChangeListener modulePrefs.put(DataConst.ENABLE_HIDE_ICON, b) packageManager.setComponentEnabledSetting( - ComponentName(packageName, "${Const.MODULE_PACKAGE_NAME}.Home"), + ComponentName(packageName, "${BuildConfig.APPLICATION_ID}.Home"), if (b) PackageManager.COMPONENT_ENABLED_STATE_DISABLED else PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP ) @@ -92,7 +92,7 @@ class MainActivity : BaseActivity() { super.onResume() /** 刷新模块状态 */ refreshModuleStatus() - /** 发送广播检查模块激活状态 */ + /** 检查模块激活状态 */ FrameworkTool.checkingActivated(context = this) { isValied -> isModuleValied = isValied refreshModuleStatus() diff --git a/app/src/main/java/com/fankes/apperrorstracking/utils/factory/FunctionFactory.kt b/app/src/main/java/com/fankes/apperrorstracking/utils/factory/FunctionFactory.kt index c2945c4..fd48c8d 100644 --- a/app/src/main/java/com/fankes/apperrorstracking/utils/factory/FunctionFactory.kt +++ b/app/src/main/java/com/fankes/apperrorstracking/utils/factory/FunctionFactory.kt @@ -34,8 +34,8 @@ import android.net.Uri import android.provider.Settings import android.widget.Toast import androidx.core.content.res.ResourcesCompat +import com.fankes.apperrorstracking.BuildConfig import com.fankes.apperrorstracking.R -import com.fankes.apperrorstracking.const.Const import com.fankes.apperrorstracking.locale.LocaleString import com.google.android.material.snackbar.Snackbar import com.highcapable.yukihookapi.hook.factory.field @@ -135,14 +135,14 @@ fun Context.snake(msg: String, actionText: String = "", callback: () -> Unit = { * * [T] 为指定的 [Activity] * @param isOutSide 是否从外部启动 - * @param callback 回调 [Intent] 方法体 + * @param initiate [Intent] 方法体 */ -inline fun Context.navigate(isOutSide: Boolean = false, callback: Intent.() -> Unit = {}) = runCatching { +inline fun Context.navigate(isOutSide: Boolean = false, initiate: Intent.() -> Unit = {}) = runCatching { startActivity((if (isOutSide) Intent() else Intent(if (this is Service) applicationContext else this, T::class.java)).apply { flags = if (this@navigate !is Activity) Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK else Intent.FLAG_ACTIVITY_NEW_TASK - if (isOutSide) component = ComponentName(Const.MODULE_PACKAGE_NAME, T::class.java.name) - callback(this) + if (isOutSide) component = ComponentName(BuildConfig.APPLICATION_ID, T::class.java.name) + initiate(this) }) }.onFailure { toast(msg = "Start ${T::class.java.name} failed") } diff --git a/app/src/main/java/com/fankes/apperrorstracking/utils/tool/FrameworkTool.kt b/app/src/main/java/com/fankes/apperrorstracking/utils/tool/FrameworkTool.kt index 0888e7e..a1fdfa6 100644 --- a/app/src/main/java/com/fankes/apperrorstracking/utils/tool/FrameworkTool.kt +++ b/app/src/main/java/com/fankes/apperrorstracking/utils/tool/FrameworkTool.kt @@ -23,58 +23,80 @@ package com.fankes.apperrorstracking.utils.tool -import android.content.BroadcastReceiver import android.content.Context -import android.content.Intent -import android.content.IntentFilter import com.fankes.apperrorstracking.bean.AppErrorsInfoBean -import com.fankes.apperrorstracking.const.Const import com.fankes.apperrorstracking.locale.LocaleString import com.fankes.apperrorstracking.utils.factory.execShell import com.fankes.apperrorstracking.utils.factory.isRootAccess import com.fankes.apperrorstracking.utils.factory.showDialog import com.fankes.apperrorstracking.utils.factory.snake -import com.highcapable.yukihookapi.hook.log.loggerE -import java.io.Serializable +import com.highcapable.yukihookapi.hook.factory.dataChannel +import com.highcapable.yukihookapi.hook.param.PackageParam +import com.highcapable.yukihookapi.hook.xposed.channel.data.ChannelData /** * 系统框架控制工具 */ object FrameworkTool { - /** 回调模块激活状态 */ - private var onModuleActiveStatusCallback: ((Boolean) -> Unit)? = null + /** 系统框架包名 */ + private const val SYSTEM_FRAMEWORK_NAME = "android" - /** 回调获取的 APP 异常信息 */ - private var onAppErrorsInfoDataCallback: ((ArrayList) -> Unit)? = null + private const val CALL_APP_ERRORS_DATA_GET = "call_app_errors_data_get" + private const val CALL_APP_ERRORS_DATA_REMOVE_RESULT = "call_app_errors_data_remove_result" + private const val CALL_APP_ERRORS_DATA_CLEAR = "call_app_errors_data_clear" + private const val CALL_APP_ERRORS_DATA_CLEAR_RESULT = "call_app_errors_data_clear_result" - /** 回调 APP 异常信息是否移除 */ - private var onRemoveAppErrorsInfoDataCallback: (() -> Unit)? = null + private val CALL_APP_ERRORS_DATA_REMOVE = ChannelData("call_app_errors_data_remove") + private val CALL_APP_ERRORS_DATA_GET_RESULT = ChannelData>("call_app_errors_data_get_result") - /** 回调 APP 异常信息是否清空 */ - private var onClearAppErrorsInfoDataCallback: (() -> Unit)? = null + /** + * 宿主注册监听 + */ + object Host { - /** 模块广播接收器 */ - private val moduleHandlerReceiver by lazy { - object : BroadcastReceiver() { - override fun onReceive(context: Context?, intent: Intent?) { - if (intent == null) return - runCatching { - intent.getStringExtra(Const.KEY_MODULE_HOST_FETCH)?.also { - if (it.isNotBlank()) when (it) { - Const.TYPE_MODULE_VERSION_VERIFY -> - onModuleActiveStatusCallback?.invoke(intent.getStringExtra(Const.TAG_MODULE_VERSION_VERIFY) == Const.MODULE_VERSION_VERIFY) - Const.TYPE_APP_ERRORS_DATA_GET -> runCatching { - onAppErrorsInfoDataCallback?.invoke( - intent.getSerializableExtra(Const.TAG_APP_ERRORS_DATA_GET_CONTENT) as ArrayList - ) - }.onFailure { onAppErrorsInfoDataCallback?.invoke(arrayListOf()) } - Const.TYPE_APP_ERRORS_DATA_REMOVE -> onRemoveAppErrorsInfoDataCallback?.invoke() - Const.TYPE_APP_ERRORS_DATA_CLEAR -> onClearAppErrorsInfoDataCallback?.invoke() - else -> {} - } - } - }.onFailure { loggerE(msg = "Cannot receiver message, please restart system", e = it) } + /** [PackageParam] 实例 */ + private var instance: PackageParam? = null + + /** + * 注册监听 + * @param instance 实例 + * @param initiate 实例方法体 + * @return [Host] + */ + fun with(instance: PackageParam, initiate: Host.() -> Unit) = apply { this.instance = instance }.apply(initiate) + + /** + * 监听发送 APP 异常信息数组 + * @param result 回调数据 + */ + fun onPushAppErrorsInfoData(result: () -> ArrayList) { + instance?.dataChannel?.with { wait(CALL_APP_ERRORS_DATA_GET) { put(CALL_APP_ERRORS_DATA_GET_RESULT, result()) } } + } + + /** + * 监听移除指定 APP 异常信息 + * @param result 回调数据 + */ + fun onRemoveAppErrorsInfoData(result: (AppErrorsInfoBean) -> Unit) { + instance?.dataChannel?.with { + wait(CALL_APP_ERRORS_DATA_REMOVE) { + result(it) + put(CALL_APP_ERRORS_DATA_REMOVE_RESULT) + } + } + } + + /** + * 监听清空 APP 异常信息数组 + * @param callback 回调 + */ + fun onClearAppErrorsInfoData(callback: () -> Unit) { + instance?.dataChannel?.with { + wait(CALL_APP_ERRORS_DATA_CLEAR) { + callback() + put(CALL_APP_ERRORS_DATA_CLEAR_RESULT) + } } } } @@ -100,83 +122,47 @@ object FrameworkTool { cancelButton() } - /** - * 发送广播 - * @param context 实例 - * @param type 类型 - * @param key 可选传值 - * @param value 可选传值 - */ - private fun pushReceiver(context: Context, type: String, key: String = "", value: Any = "") { - context.sendBroadcast(Intent().apply { - action = Const.ACTION_HOST_HANDLER_RECEIVER - putExtra(Const.KEY_MODULE_HOST_FETCH, type) - if (key.isNotBlank()) putExtra( - key, when (value) { - is String -> value - is Int -> value - is Boolean -> value - is Serializable -> value - else -> error("value is not allowed") - } - ) - }) - } - /** * 检查模块是否激活 * @param context 实例 - * @param it 成功后回调 - ([Boolean] 是否激活) + * @param result 成功后回调 */ - fun checkingActivated(context: Context, it: (Boolean) -> Unit) { - onModuleActiveStatusCallback = it - pushReceiver(context, Const.TYPE_MODULE_VERSION_VERIFY) - } + fun checkingActivated(context: Context, result: (Boolean) -> Unit) = context.dataChannel(SYSTEM_FRAMEWORK_NAME).checkingVersionEquals(result) /** * 获取 APP 异常信息数组 * @param context 实例 - * @param it 回调数据 + * @param result 回调数据 */ - fun fetchAppErrorsInfoData(context: Context, it: (ArrayList) -> Unit) { - onAppErrorsInfoDataCallback = it - pushReceiver(context, Const.TYPE_APP_ERRORS_DATA_GET) + fun fetchAppErrorsInfoData(context: Context, result: (ArrayList) -> Unit) { + context.dataChannel(SYSTEM_FRAMEWORK_NAME).with { + wait(CALL_APP_ERRORS_DATA_GET_RESULT) { result(it) } + put(CALL_APP_ERRORS_DATA_GET) + } } /** * 移除指定 APP 异常信息 * @param context 实例 * @param appErrorsInfo 指定 APP 异常信息 - * @param it 成功后回调 + * @param callback 成功后回调 */ - fun removeAppErrorsInfoData(context: Context, appErrorsInfo: AppErrorsInfoBean, it: () -> Unit) { - onRemoveAppErrorsInfoDataCallback = it - pushReceiver(context, Const.TYPE_APP_ERRORS_DATA_REMOVE, Const.TAG_APP_ERRORS_DATA_REMOVE_CONTENT, appErrorsInfo) + fun removeAppErrorsInfoData(context: Context, appErrorsInfo: AppErrorsInfoBean, callback: () -> Unit) { + context.dataChannel(SYSTEM_FRAMEWORK_NAME).with { + wait(CALL_APP_ERRORS_DATA_REMOVE_RESULT) { callback() } + put(CALL_APP_ERRORS_DATA_REMOVE, appErrorsInfo) + } } /** * 清空 APP 异常信息数组 * @param context 实例 - * @param it 成功后回调 + * @param callback 成功后回调 */ - fun clearAppErrorsInfoData(context: Context, it: () -> Unit) { - onClearAppErrorsInfoDataCallback = it - pushReceiver(context, Const.TYPE_APP_ERRORS_DATA_CLEAR) - } - - /** - * 注册广播 - * @param context 实例 - */ - fun registerReceiver(context: Context) = runCatching { - context.registerReceiver(moduleHandlerReceiver, IntentFilter().apply { addAction(Const.ACTION_MODULE_HANDLER_RECEIVER) }) - } - - /** - * 取消注册 - * @param context 实例 - */ - fun unregisterReceiver(context: Context) = runCatching { - context.unregisterReceiver(moduleHandlerReceiver) + fun clearAppErrorsInfoData(context: Context, callback: () -> Unit) { + context.dataChannel(SYSTEM_FRAMEWORK_NAME).with { + wait(CALL_APP_ERRORS_DATA_CLEAR_RESULT) { callback() } + put(CALL_APP_ERRORS_DATA_CLEAR) + } } } \ No newline at end of file