Merge module and host receiver to new api

This commit is contained in:
2022-06-01 00:33:10 +08:00
parent bc4813e106
commit 16d3543696
8 changed files with 119 additions and 283 deletions

View File

@@ -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
* <https://www.gnu.org/licenses/>
*
* 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"
}

View File

@@ -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<AppErrorsInfoBean>()
/** 是否已经注册广播 */
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<Context>()?.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()
)
)

View File

@@ -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<VB : ViewBinding> : 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)
}
}

View File

@@ -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<ActivityAppErrorsDetailBinding>() {
/** 请求保存文件回调标识 */
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<ActivityAppErrorsDetailBinding>() {
* @param isOutSide 是否从外部启动
*/
fun start(context: Context, appErrorsInfo: AppErrorsInfoBean, isOutSide: Boolean = false) =
context.navigate<AppErrorsDetailActivity>(isOutSide) { putExtra(Const.EXTRA_APP_ERRORS_INFO, appErrorsInfo) }
context.navigate<AppErrorsDetailActivity>(isOutSide) { putExtra(EXTRA_APP_ERRORS_INFO, appErrorsInfo) }
}
/** 预导出的异常堆栈 */
@@ -86,7 +88,7 @@ class AppErrorsDetailActivity : BaseActivity<ActivityAppErrorsDetailBinding>() {
}
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<ActivityAppErrorsDetailBinding>() {
}
override fun onBackPressed() {
intent?.removeExtra(Const.EXTRA_APP_ERRORS_INFO)
intent?.removeExtra(EXTRA_APP_ERRORS_INFO)
finish()
}

View File

@@ -82,7 +82,7 @@ class AppErrorsRecordActivity : BaseActivity<ActivityAppErrorsRecordBinding>() {
}
}
/** 设置列表元素和 Adapter */
binding.listView.apply {
binding.listView.apply { // 改成 recycleview?
adapter = object : BaseAdapter() {
override fun getCount() = listData.size

View File

@@ -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<ActivityMainBinding>() {
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<ActivityMainBinding>() {
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<ActivityMainBinding>() {
super.onResume()
/** 刷新模块状态 */
refreshModuleStatus()
/** 发送广播检查模块激活状态 */
/** 检查模块激活状态 */
FrameworkTool.checkingActivated(context = this) { isValied ->
isModuleValied = isValied
refreshModuleStatus()

View File

@@ -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 <reified T : Activity> Context.navigate(isOutSide: Boolean = false, callback: Intent.() -> Unit = {}) = runCatching {
inline fun <reified T : Activity> 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") }

View File

@@ -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<AppErrorsInfoBean>) -> 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<AppErrorsInfoBean>("call_app_errors_data_remove")
private val CALL_APP_ERRORS_DATA_GET_RESULT = ChannelData<ArrayList<AppErrorsInfoBean>>("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<AppErrorsInfoBean>
)
}.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<AppErrorsInfoBean>) {
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<AppErrorsInfoBean>) -> Unit) {
onAppErrorsInfoDataCallback = it
pushReceiver(context, Const.TYPE_APP_ERRORS_DATA_GET)
fun fetchAppErrorsInfoData(context: Context, result: (ArrayList<AppErrorsInfoBean>) -> 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)
}
}
}