mirror of
https://github.com/KitsunePie/AppErrorsTracking.git
synced 2025-09-01 08:45:16 +08:00
feat: lots of changes
- add BuildConfigWrapper - add project promote - add ci version tag support - change app analytics config item show when available - fix system api compat issues
This commit is contained in:
@@ -66,7 +66,7 @@ androidComponents {
|
||||
val currentSuffix = property.github.ci.commit.id.let { suffix -> if (suffix.isNotBlank()) "-$suffix" else "" }
|
||||
val currentVersion = "${output.versionName.get()}$currentSuffix(${output.versionCode.get()})"
|
||||
if (output is com.android.build.api.variant.impl.VariantOutputImpl)
|
||||
output.outputFileName.set("${property.project.name}-v$currentVersion-$currentType.apk")
|
||||
output.outputFileName.set("${property.project.name}-demo-v$currentVersion-$currentType.apk")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -19,19 +19,25 @@
|
||||
*
|
||||
* This file is Created by fankes on 2022/5/10.
|
||||
*/
|
||||
@file:Suppress("SetTextI18n")
|
||||
|
||||
package com.fankes.apperrorsdemo.ui.activity
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.SystemClock
|
||||
import com.fankes.apperrorsdemo.R
|
||||
import com.fankes.apperrorsdemo.databinding.ActivityMainBinding
|
||||
import com.fankes.apperrorsdemo.databinding.ActivityMultiProcessBinding
|
||||
import com.fankes.apperrorsdemo.generated.DemoAppProperties
|
||||
import com.fankes.apperrorsdemo.native.Channel
|
||||
import com.fankes.apperrorsdemo.ui.activity.base.BaseActivity
|
||||
|
||||
class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
|
||||
override fun onCreate() {
|
||||
binding.titleBackIcon.setOnClickListener { finish() }
|
||||
DemoAppProperties.GITHUB_CI_COMMIT_ID.takeIf(String::isNotBlank)?.also {
|
||||
binding.titleText.text = "${getString(R.string.app_name)} ($it)"
|
||||
}; binding.titleBackIcon.setOnClickListener { finish() }
|
||||
binding.throwRuntimeButton.setOnClickListener { Channel.throwRuntimeException() }
|
||||
binding.throwIllegalStateButton.setOnClickListener { Channel.throwIllegalStateException() }
|
||||
binding.throwNullPointerButton.setOnClickListener { Channel.throwNullPointerException() }
|
||||
|
@@ -19,8 +19,6 @@
|
||||
*
|
||||
* This file is Created by fankes on 2022/5/10.
|
||||
*/
|
||||
@file:Suppress("UNCHECKED_CAST")
|
||||
|
||||
package com.fankes.apperrorsdemo.ui.activity.base
|
||||
|
||||
import android.os.Build
|
||||
|
@@ -30,6 +30,7 @@
|
||||
android:tooltipText="@string/back" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="2.5dp"
|
||||
|
0
app/.gitignore → module-app/.gitignore
vendored
0
app/.gitignore → module-app/.gitignore
vendored
@@ -61,7 +61,7 @@ androidComponents {
|
||||
val currentSuffix = property.github.ci.commit.id.let { suffix -> if (suffix.isNotBlank()) "-$suffix" else "" }
|
||||
val currentVersion = "${output.versionName.get()}$currentSuffix(${output.versionCode.get()})"
|
||||
if (output is com.android.build.api.variant.impl.VariantOutputImpl)
|
||||
output.outputFileName.set("${property.project.name}-v$currentVersion-$currentType.apk")
|
||||
output.outputFileName.set("${property.project.name}-module-v$currentVersion-$currentType.apk")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -64,4 +64,7 @@
|
||||
public static *** throwUninitializedPropertyAccessException(...);
|
||||
}
|
||||
|
||||
-keep class com.fankes.apperrorstracking.databinding**{*;}
|
||||
-keep class * extends android.app.Activity
|
||||
-keepclassmembers class * implements androidx.viewbinding.ViewBinding {
|
||||
*** inflate(android.view.LayoutInflater);
|
||||
}
|
BIN
module-app/src/main/ic_launcher-playstore.png
Normal file
BIN
module-app/src/main/ic_launcher-playstore.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
@@ -25,11 +25,16 @@ import android.app.ApplicationErrorReport
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import com.fankes.apperrorstracking.locale.LocaleString
|
||||
import com.fankes.apperrorstracking.utils.factory.*
|
||||
import com.fankes.apperrorstracking.utils.factory.appCpuAbiOf
|
||||
import com.fankes.apperrorstracking.utils.factory.appVersionCodeOf
|
||||
import com.fankes.apperrorstracking.utils.factory.appVersionNameOf
|
||||
import com.fankes.apperrorstracking.utils.factory.difference
|
||||
import com.fankes.apperrorstracking.utils.factory.toUtcTime
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import java.io.Serializable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* 应用异常信息 bean
|
||||
@@ -130,7 +135,7 @@ data class AppErrorsInfoBean(
|
||||
* 获取生成的 Json 文件名
|
||||
* @return [String]
|
||||
*/
|
||||
val jsonFileName get() = "${packageName}_${pid}_${timestamp}.json"
|
||||
val jsonFileName get() = "${packageName}_${pid}_$timestamp.json"
|
||||
|
||||
/**
|
||||
* 获取 APP 版本信息与版本号
|
||||
@@ -170,39 +175,46 @@ data class AppErrorsInfoBean(
|
||||
* @return [String]
|
||||
*/
|
||||
val stackOutputShareContent
|
||||
get() = "Generated by AppErrorsTracking\n" +
|
||||
"Project Url: https://github.com/KitsunePie/AppErrorsTracking\n" +
|
||||
"===============\n$environmentInfo"
|
||||
get() = """
|
||||
Generated by AppErrorsTracking
|
||||
Project Url: https://github.com/KitsunePie/AppErrorsTracking
|
||||
===============
|
||||
$environmentInfo
|
||||
""".trimIndent()
|
||||
|
||||
/**
|
||||
* 获取异常堆栈文件模板
|
||||
* @return [String]
|
||||
*/
|
||||
val stackOutputFileContent
|
||||
get() = "================================================================\n" +
|
||||
" Generated by AppErrorsTracking\n" +
|
||||
" Project Url: https://github.com/KitsunePie/AppErrorsTracking\n" +
|
||||
"================================================================\n" +
|
||||
environmentInfo
|
||||
get() = """
|
||||
================================================================
|
||||
Generated by AppErrorsTracking
|
||||
Project Url: https://github.com/KitsunePie/AppErrorsTracking
|
||||
================================================================
|
||||
""".trimIndent()
|
||||
|
||||
/**
|
||||
* 获取运行环境信息
|
||||
* @return [String]
|
||||
*/
|
||||
private val environmentInfo
|
||||
get() = "[Device Brand]: ${Build.BRAND}\n" +
|
||||
"[Device Model]: ${Build.MODEL}\n" +
|
||||
"[Display]: ${Build.DISPLAY}\n" +
|
||||
"[Android Version]: ${Build.VERSION.RELEASE}\n" +
|
||||
"[Android API Level]: ${Build.VERSION.SDK_INT}\n" +
|
||||
"[System Locale]: ${Locale.getDefault()}\n" +
|
||||
"[Process ID]: $pid\n" +
|
||||
(if (userId > 0) "[User Id]: $userId\n" else "") +
|
||||
"[CPU ABI]: ${cpuAbi.ifBlank { "none" }}\n" +
|
||||
"[Package Name]: $packageName\n" +
|
||||
"[Version Name]: ${versionName.ifBlank { "unknown" }}\n" +
|
||||
"[Version Code]: ${versionCode.takeIf { it != -1L } ?: "unknown"}\n" +
|
||||
"[Error Type]: ${if (isNativeCrash) "Native" else "JVM"}\n" +
|
||||
"[Crash Time]: $utcTime\n" +
|
||||
"[Stack Trace]:\n" + stackTrace
|
||||
get() = """
|
||||
[Device Brand]: ${Build.BRAND}
|
||||
[Device Model]: ${Build.MODEL}
|
||||
[Display]: ${Build.DISPLAY}
|
||||
[Android Version]: ${Build.VERSION.RELEASE}
|
||||
[Android API Level]: ${Build.VERSION.SDK_INT}
|
||||
[System Locale]: ${Locale.getDefault()}
|
||||
[Process ID]: $pid
|
||||
[User ID]: $userId
|
||||
[CPU ABI]: ${cpuAbi.ifBlank { "none" }}
|
||||
[Package Name]: $packageName
|
||||
[Version Name]: ${versionName.ifBlank { "unknown" }}
|
||||
[Version Code]: ${versionCode.takeIf { it != -1L } ?: "unknown"}
|
||||
[Error Type]: ${if (isNativeCrash) "Native" else "JVM"}
|
||||
[Crash Time]: $utcTime
|
||||
[Stack Trace]:
|
||||
$stackTrace
|
||||
""".trimIndent()
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer.
|
||||
* Copyright (C) 2017-2023 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 2023/9/19.
|
||||
*/
|
||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
package com.fankes.apperrorstracking.const
|
||||
|
||||
import com.fankes.apperrorstracking.generated.ModuleAppProperties
|
||||
import com.fankes.apperrorstracking.wrapper.BuildConfigWrapper
|
||||
|
||||
/**
|
||||
* 包名常量定义类
|
||||
*/
|
||||
object PackageName {
|
||||
|
||||
/** 系统框架 */
|
||||
const val SYSTEM_FRAMEWORK = "android"
|
||||
}
|
||||
|
||||
/**
|
||||
* 模块版本常量定义类
|
||||
*/
|
||||
object ModuleVersion {
|
||||
|
||||
/** 当前 GitHub 提交的 ID (CI 自动构建) */
|
||||
const val GITHUB_COMMIT_ID = ModuleAppProperties.GITHUB_CI_COMMIT_ID
|
||||
|
||||
/** 版本名称 */
|
||||
const val NAME = BuildConfigWrapper.VERSION_NAME
|
||||
|
||||
/** 版本号 */
|
||||
const val CODE = BuildConfigWrapper.VERSION_CODE
|
||||
|
||||
/** 是否为 CI 自动构建版本 */
|
||||
val isCiMode = GITHUB_COMMIT_ID.isNotBlank()
|
||||
|
||||
/** 当前版本名称后缀 */
|
||||
val suffix = GITHUB_COMMIT_ID.let { if (it.isNotBlank()) "-$it" else "" }
|
||||
|
||||
override fun toString() = "$NAME$suffix($CODE)"
|
||||
}
|
@@ -74,9 +74,9 @@ object AppErrorsConfigData {
|
||||
if (packageName.isNotBlank()) when (type) {
|
||||
AppErrorsConfigType.GLOBAL ->
|
||||
showDialogApps.contains(packageName).not() &&
|
||||
showNotifyApps.contains(packageName).not() &&
|
||||
showToastApps.contains(packageName).not() &&
|
||||
showNothingApps.contains(packageName).not()
|
||||
showNotifyApps.contains(packageName).not() &&
|
||||
showToastApps.contains(packageName).not() &&
|
||||
showNothingApps.contains(packageName).not()
|
||||
AppErrorsConfigType.DIALOG -> showDialogApps.contains(packageName)
|
||||
AppErrorsConfigType.NOTIFY -> showNotifyApps.contains(packageName)
|
||||
AppErrorsConfigType.TOAST -> showToastApps.contains(packageName)
|
@@ -26,7 +26,11 @@ package com.fankes.apperrorstracking.data
|
||||
import android.content.Context
|
||||
import android.provider.Settings
|
||||
import com.fankes.apperrorstracking.bean.AppErrorsInfoBean
|
||||
import com.fankes.apperrorstracking.utils.factory.*
|
||||
import com.fankes.apperrorstracking.utils.factory.appCpuAbiOf
|
||||
import com.fankes.apperrorstracking.utils.factory.appVersionCodeOf
|
||||
import com.fankes.apperrorstracking.utils.factory.appVersionNameOf
|
||||
import com.fankes.apperrorstracking.utils.factory.toEntityOrNull
|
||||
import com.fankes.apperrorstracking.utils.factory.toJsonOrNull
|
||||
import com.highcapable.yukihookapi.hook.log.loggerE
|
||||
import java.io.File
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
@@ -91,11 +95,11 @@ object AppErrorsRecordData {
|
||||
e.versionCode = it.appVersionCodeOf(e.packageName)
|
||||
e.toJsonOrNull()?.also { json -> File(errorsInfoDataFolder.absolutePath, e.jsonFileName).writeText(json) }
|
||||
}.let { result ->
|
||||
if (result != null) {
|
||||
Settings.Secure.putString(it.contentResolver, keyName, "")
|
||||
result
|
||||
} else null
|
||||
}
|
||||
if (result != null) {
|
||||
Settings.Secure.putString(it.contentResolver, keyName, "")
|
||||
result
|
||||
} else null
|
||||
}
|
||||
}.getOrNull()
|
||||
}
|
||||
|
@@ -19,6 +19,8 @@
|
||||
*
|
||||
* This file is Created by fankes on 2022/5/7.
|
||||
*/
|
||||
@file:Suppress("ConstPropertyName")
|
||||
|
||||
package com.fankes.apperrorstracking.hook.entity
|
||||
|
||||
import android.app.ApplicationErrorReport
|
||||
@@ -33,7 +35,6 @@ import android.os.SystemClock
|
||||
import android.util.ArrayMap
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import com.fankes.apperrorstracking.BuildConfig
|
||||
import com.fankes.apperrorstracking.R
|
||||
import com.fankes.apperrorstracking.bean.AppErrorsDisplayBean
|
||||
import com.fankes.apperrorstracking.bean.AppErrorsInfoBean
|
||||
@@ -47,8 +48,16 @@ import com.fankes.apperrorstracking.data.enum.AppErrorsConfigType
|
||||
import com.fankes.apperrorstracking.locale.LocaleString
|
||||
import com.fankes.apperrorstracking.ui.activity.errors.AppErrorsDisplayActivity
|
||||
import com.fankes.apperrorstracking.ui.activity.errors.AppErrorsRecordActivity
|
||||
import com.fankes.apperrorstracking.utils.factory.*
|
||||
import com.fankes.apperrorstracking.utils.factory.appNameOf
|
||||
import com.fankes.apperrorstracking.utils.factory.drawableOf
|
||||
import com.fankes.apperrorstracking.utils.factory.isAppCanOpened
|
||||
import com.fankes.apperrorstracking.utils.factory.listOfPackages
|
||||
import com.fankes.apperrorstracking.utils.factory.openApp
|
||||
import com.fankes.apperrorstracking.utils.factory.pushNotify
|
||||
import com.fankes.apperrorstracking.utils.factory.toArrayList
|
||||
import com.fankes.apperrorstracking.utils.factory.toast
|
||||
import com.fankes.apperrorstracking.utils.tool.FrameworkTool
|
||||
import com.fankes.apperrorstracking.wrapper.BuildConfigWrapper
|
||||
import com.highcapable.yukihookapi.hook.bean.VariousClass
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.field
|
||||
@@ -241,7 +250,7 @@ object FrameworkHooker : YukiBaseHooker() {
|
||||
onPushAppListData { filters ->
|
||||
appContext?.let { context ->
|
||||
context.listOfPackages()
|
||||
.filter { it.packageName.let { e -> e != "android" && e != BuildConfig.APPLICATION_ID } }
|
||||
.filter { it.packageName.let { e -> e != "android" && e != BuildConfigWrapper.APPLICATION_ID } }
|
||||
.let { info ->
|
||||
arrayListOf<AppInfoBean>().apply {
|
||||
if (info.isNotEmpty())
|
||||
@@ -309,9 +318,9 @@ object FrameworkHooker : YukiBaseHooker() {
|
||||
title = errorTitle,
|
||||
isShowAppInfoButton = isActualApp,
|
||||
isShowReopenButton = isActualApp &&
|
||||
(isRepeatingCrash.not() || ConfigData.isEnableAlwaysShowsReopenAppOptions) &&
|
||||
context.isAppCanOpened(packageName) &&
|
||||
isMainProcess,
|
||||
(isRepeatingCrash.not() || ConfigData.isEnableAlwaysShowsReopenAppOptions) &&
|
||||
context.isAppCanOpened(packageName) &&
|
||||
isMainProcess,
|
||||
isShowCloseAppButton = isActualApp
|
||||
)
|
||||
)
|
||||
@@ -322,7 +331,7 @@ object FrameworkHooker : YukiBaseHooker() {
|
||||
/** 判断是否为主进程 */
|
||||
if (isMainProcess.not() && ConfigData.isEnableOnlyShowErrorsInMain) return
|
||||
when {
|
||||
packageName == BuildConfig.APPLICATION_ID -> {
|
||||
packageName == BuildConfigWrapper.APPLICATION_ID -> {
|
||||
context.toast(msg = "AppErrorsTracking has crashed, please see the log in console")
|
||||
loggerE(msg = "AppErrorsTracking has crashed itself, please see the Android Runtime Exception in console")
|
||||
}
|
||||
@@ -343,8 +352,8 @@ object FrameworkHooker : YukiBaseHooker() {
|
||||
/** 打印错误日志 */
|
||||
if (isActualApp) loggerE(
|
||||
msg = "Application \"$packageName\" ${if (isRepeatingCrash) "keeps stopping" else "has stopped"}" +
|
||||
(if (packageName != processName) " --process \"$processName\"" else "") +
|
||||
"${if (userId != 0) " --user $userId" else ""} --pid $pid"
|
||||
(if (packageName != processName) " --process \"$processName\"" else "") +
|
||||
"${if (userId != 0) " --user $userId" else ""} --pid $pid"
|
||||
) else loggerE(msg = "Process \"$processName\" ${if (isRepeatingCrash) "keeps stopping" else "has stopped"} --pid $pid")
|
||||
}
|
||||
|
@@ -19,8 +19,6 @@
|
||||
*
|
||||
* This file is Created by fankes on 2022/5/7.
|
||||
*/
|
||||
@file:Suppress("UNCHECKED_CAST")
|
||||
|
||||
package com.fankes.apperrorstracking.ui.activity.base
|
||||
|
||||
import android.app.ActivityManager
|
@@ -31,20 +31,24 @@ import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import androidx.core.view.isVisible
|
||||
import com.fankes.apperrorstracking.R
|
||||
import com.fankes.apperrorstracking.const.PackageName
|
||||
import com.fankes.apperrorstracking.databinding.ActivitiyLoggerBinding
|
||||
import com.fankes.apperrorstracking.databinding.AdapterLoggerBinding
|
||||
import com.fankes.apperrorstracking.databinding.DiaLoggerFilterBinding
|
||||
import com.fankes.apperrorstracking.locale.LocaleString
|
||||
import com.fankes.apperrorstracking.ui.activity.base.BaseActivity
|
||||
import com.fankes.apperrorstracking.utils.factory.*
|
||||
import com.fankes.apperrorstracking.utils.tool.FrameworkTool
|
||||
import com.fankes.apperrorstracking.utils.factory.bindAdapter
|
||||
import com.fankes.apperrorstracking.utils.factory.copyToClipboard
|
||||
import com.fankes.apperrorstracking.utils.factory.showDialog
|
||||
import com.fankes.apperrorstracking.utils.factory.toUtcTime
|
||||
import com.fankes.apperrorstracking.utils.factory.toast
|
||||
import com.highcapable.yukihookapi.hook.factory.dataChannel
|
||||
import com.highcapable.yukihookapi.hook.log.YukiHookLogger
|
||||
import com.highcapable.yukihookapi.hook.log.YukiLoggerData
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.PrintStream
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.Date
|
||||
|
||||
class LoggerActivity : BaseActivity<ActivitiyLoggerBinding>() {
|
||||
|
||||
@@ -124,7 +128,7 @@ class LoggerActivity : BaseActivity<ActivitiyLoggerBinding>() {
|
||||
|
||||
/** 更新列表数据 */
|
||||
private fun refreshData() {
|
||||
dataChannel(FrameworkTool.SYSTEM_FRAMEWORK_NAME).obtainLoggerInMemoryData {
|
||||
dataChannel(PackageName.SYSTEM_FRAMEWORK).obtainLoggerInMemoryData {
|
||||
listData.clear()
|
||||
it.takeIf { e -> e.isNotEmpty() }?.reversed()?.filter { filters.any { e -> it.priority == e } }?.forEach { e -> listData.add(e) }
|
||||
onChanged?.invoke()
|
@@ -36,7 +36,15 @@ import com.fankes.apperrorstracking.data.factory.bind
|
||||
import com.fankes.apperrorstracking.databinding.ActivityAppErrorsDetailBinding
|
||||
import com.fankes.apperrorstracking.locale.LocaleString
|
||||
import com.fankes.apperrorstracking.ui.activity.base.BaseActivity
|
||||
import com.fankes.apperrorstracking.utils.factory.*
|
||||
import com.fankes.apperrorstracking.utils.factory.appIconOf
|
||||
import com.fankes.apperrorstracking.utils.factory.appNameOf
|
||||
import com.fankes.apperrorstracking.utils.factory.copyToClipboard
|
||||
import com.fankes.apperrorstracking.utils.factory.dp
|
||||
import com.fankes.apperrorstracking.utils.factory.getSerializableExtraCompat
|
||||
import com.fankes.apperrorstracking.utils.factory.navigate
|
||||
import com.fankes.apperrorstracking.utils.factory.openSelfSetting
|
||||
import com.fankes.apperrorstracking.utils.factory.showDialog
|
||||
import com.fankes.apperrorstracking.utils.factory.toast
|
||||
import com.highcapable.yukihookapi.hook.log.loggerE
|
||||
|
||||
class AppErrorsDetailActivity : BaseActivity<ActivityAppErrorsDetailBinding>() {
|
@@ -31,7 +31,12 @@ import com.fankes.apperrorstracking.databinding.ActivityAppErrorsDisplayBinding
|
||||
import com.fankes.apperrorstracking.databinding.DiaAppErrorsDisplayBinding
|
||||
import com.fankes.apperrorstracking.locale.LocaleString
|
||||
import com.fankes.apperrorstracking.ui.activity.base.BaseActivity
|
||||
import com.fankes.apperrorstracking.utils.factory.*
|
||||
import com.fankes.apperrorstracking.utils.factory.colorOf
|
||||
import com.fankes.apperrorstracking.utils.factory.getSerializableExtraCompat
|
||||
import com.fankes.apperrorstracking.utils.factory.navigate
|
||||
import com.fankes.apperrorstracking.utils.factory.openSelfSetting
|
||||
import com.fankes.apperrorstracking.utils.factory.showDialog
|
||||
import com.fankes.apperrorstracking.utils.factory.toast
|
||||
import com.fankes.apperrorstracking.utils.tool.FrameworkTool
|
||||
|
||||
class AppErrorsDisplayActivity : BaseActivity<ActivityAppErrorsDisplayBinding>() {
|
@@ -19,8 +19,6 @@
|
||||
*
|
||||
* This file is Created by fankes on 2022/6/3.
|
||||
*/
|
||||
@file:Suppress("DEPRECATION", "OVERRIDE_DEPRECATION")
|
||||
|
||||
package com.fankes.apperrorstracking.ui.activity.errors
|
||||
|
||||
import androidx.core.view.isVisible
|
@@ -31,7 +31,6 @@ import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.AdapterView.AdapterContextMenuInfo
|
||||
import androidx.core.view.isVisible
|
||||
import com.fankes.apperrorstracking.BuildConfig
|
||||
import com.fankes.apperrorstracking.R
|
||||
import com.fankes.apperrorstracking.bean.AppErrorsInfoBean
|
||||
import com.fankes.apperrorstracking.bean.AppFiltersBean
|
||||
@@ -44,6 +43,7 @@ import com.fankes.apperrorstracking.ui.activity.base.BaseActivity
|
||||
import com.fankes.apperrorstracking.utils.factory.*
|
||||
import com.fankes.apperrorstracking.utils.tool.FrameworkTool
|
||||
import com.fankes.apperrorstracking.utils.tool.ZipFileTool
|
||||
import com.fankes.apperrorstracking.wrapper.BuildConfigWrapper
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
|
||||
@@ -58,7 +58,7 @@ class AppErrorsRecordActivity : BaseActivity<ActivityAppErrorsRecordBinding>() {
|
||||
* 获取 [Intent]
|
||||
* @return [Intent]
|
||||
*/
|
||||
fun intent() = Intent().apply { component = ComponentName(BuildConfig.APPLICATION_ID, AppErrorsRecordActivity::class.java.name) }
|
||||
fun intent() = Intent().apply { component = ComponentName(BuildConfigWrapper.APPLICATION_ID, AppErrorsRecordActivity::class.java.name) }
|
||||
}
|
||||
|
||||
/** 当前导出文件的路径 */
|
@@ -25,8 +25,8 @@ package com.fankes.apperrorstracking.ui.activity.main
|
||||
|
||||
import android.os.Build
|
||||
import androidx.core.view.isVisible
|
||||
import com.fankes.apperrorstracking.BuildConfig
|
||||
import com.fankes.apperrorstracking.R
|
||||
import com.fankes.apperrorstracking.const.ModuleVersion
|
||||
import com.fankes.apperrorstracking.data.ConfigData
|
||||
import com.fankes.apperrorstracking.data.factory.bind
|
||||
import com.fankes.apperrorstracking.databinding.ActivityMainBinding
|
||||
@@ -35,10 +35,18 @@ import com.fankes.apperrorstracking.ui.activity.base.BaseActivity
|
||||
import com.fankes.apperrorstracking.ui.activity.debug.LoggerActivity
|
||||
import com.fankes.apperrorstracking.ui.activity.errors.AppErrorsMutedActivity
|
||||
import com.fankes.apperrorstracking.ui.activity.errors.AppErrorsRecordActivity
|
||||
import com.fankes.apperrorstracking.utils.factory.*
|
||||
import com.fankes.apperrorstracking.utils.factory.hideOrShowLauncherIcon
|
||||
import com.fankes.apperrorstracking.utils.factory.isLauncherIconShowing
|
||||
import com.fankes.apperrorstracking.utils.factory.isSystemLanguageSimplifiedChinese
|
||||
import com.fankes.apperrorstracking.utils.factory.navigate
|
||||
import com.fankes.apperrorstracking.utils.factory.openBrowser
|
||||
import com.fankes.apperrorstracking.utils.factory.showDialog
|
||||
import com.fankes.apperrorstracking.utils.factory.toast
|
||||
import com.fankes.apperrorstracking.utils.tool.AppAnalyticsTool
|
||||
import com.fankes.apperrorstracking.utils.tool.AppAnalyticsTool.bindAppAnalytics
|
||||
import com.fankes.apperrorstracking.utils.tool.FrameworkTool
|
||||
import com.fankes.apperrorstracking.utils.tool.GithubReleaseTool
|
||||
import com.fankes.projectpromote.ProjectPromote
|
||||
import com.highcapable.yukihookapi.YukiHookAPI
|
||||
|
||||
class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
@@ -55,13 +63,15 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
override fun onCreate() {
|
||||
checkingTopComponentName()
|
||||
/** 检查更新 */
|
||||
GithubReleaseTool.checkingForUpdate(context = this, BuildConfig.VERSION_NAME) { version, function ->
|
||||
GithubReleaseTool.checkingForUpdate(context = this, ModuleVersion.NAME) { version, function ->
|
||||
binding.mainTextReleaseVersion.apply {
|
||||
text = LocaleString.clickToUpdate(version)
|
||||
isVisible = true
|
||||
setOnClickListener { function() }
|
||||
}
|
||||
}
|
||||
/** 推广、恰饭 */
|
||||
if (YukiHookAPI.Status.isXposedModuleActive) ProjectPromote.show(activity = this, ModuleVersion.toString())
|
||||
/** 显示开发者提示 */
|
||||
if (ConfigData.isShowDeveloperNotice)
|
||||
showDialog {
|
||||
@@ -70,7 +80,21 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
confirmButton(LocaleString.gotIt) { ConfigData.isShowDeveloperNotice = false }
|
||||
noCancelable()
|
||||
}
|
||||
binding.mainTextVersion.text = LocaleString.moduleVersion(BuildConfig.VERSION_NAME)
|
||||
/** 设置 CI 自动构建标识 */
|
||||
if (ModuleVersion.isCiMode)
|
||||
binding.mainTextReleaseVersion.apply {
|
||||
text = "CI ${ModuleVersion.GITHUB_COMMIT_ID}"
|
||||
isVisible = true
|
||||
setOnClickListener {
|
||||
showDialog {
|
||||
title = LocaleString.ciNoticeDialogTitle
|
||||
msg = LocaleString.ciNoticeDialogContent(ModuleVersion.GITHUB_COMMIT_ID)
|
||||
confirmButton(LocaleString.gotIt)
|
||||
noCancelable()
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.mainTextVersion.text = LocaleString.moduleVersion(ModuleVersion.NAME)
|
||||
binding.mainTextSystemVersion.text = LocaleString.systemVersion(systemVersion)
|
||||
binding.onlyShowErrorsInFrontSwitch.bind(ConfigData.ENABLE_ONLY_SHOW_ERRORS_IN_FRONT)
|
||||
binding.onlyShowErrorsInMainProcessSwitch.bind(ConfigData.ENABLE_ONLY_SHOW_ERRORS_IN_MAIN)
|
||||
@@ -81,6 +105,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
}
|
||||
binding.enableMaterial3AppErrorsDialogSwitch.bind(ConfigData.ENABLE_MATERIAL3_STYLE_APP_ERRORS_DIALOG)
|
||||
/** 设置匿名统计 */
|
||||
binding.appAnalyticsConfigItem.isVisible = AppAnalyticsTool.isAvailable
|
||||
binding.enableAnonymousStatisticsSwitch.bindAppAnalytics()
|
||||
/** 系统版本点击事件 */
|
||||
binding.mainTextSystemVersion.setOnClickListener {
|
||||
@@ -101,6 +126,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
binding.titleRestartIcon.setOnClickListener { FrameworkTool.restartSystem(context = this) }
|
||||
/** 项目地址按钮点击事件 */
|
||||
binding.titleGithubIcon.setOnClickListener { openBrowser(url = "https://github.com/KitsunePie/AppErrorsTracking") }
|
||||
/** 恰饭! */
|
||||
binding.paymentFollowingZhCnItem.isVisible = isSystemLanguageSimplifiedChinese
|
||||
binding.linkWithFollowMe.setOnClickListener {
|
||||
openBrowser(url = "https://www.coolapk.com/u/876977", packageName = "com.coolapk.market")
|
||||
}
|
||||
/** 设置桌面图标显示隐藏 */
|
||||
binding.hideIconInLauncherSwitch.isChecked = isLauncherIconShowing.not()
|
||||
binding.hideIconInLauncherSwitch.setOnCheckedChangeListener { btn, b ->
|
@@ -19,7 +19,7 @@
|
||||
*
|
||||
* This file is Created by fankes on 2022/5/12.
|
||||
*/
|
||||
@file:Suppress("unused", "DEPRECATION", "OPT_IN_USAGE", "EXPERIMENTAL_API_USAGE")
|
||||
@file:Suppress("unused", "OPT_IN_USAGE", "EXPERIMENTAL_API_USAGE")
|
||||
|
||||
package com.fankes.apperrorstracking.utils.factory
|
||||
|
@@ -23,8 +23,16 @@
|
||||
|
||||
package com.fankes.apperrorstracking.utils.factory
|
||||
|
||||
import android.app.*
|
||||
import android.content.*
|
||||
import android.app.Activity
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.app.Service
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.PackageManager.PackageInfoFlags
|
||||
@@ -43,9 +51,9 @@ import androidx.core.content.getSystemService
|
||||
import androidx.core.content.pm.PackageInfoCompat
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import com.fankes.apperrorstracking.BuildConfig
|
||||
import com.fankes.apperrorstracking.R
|
||||
import com.fankes.apperrorstracking.locale.LocaleString
|
||||
import com.fankes.apperrorstracking.wrapper.BuildConfigWrapper
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.highcapable.yukihookapi.hook.factory.field
|
||||
import com.highcapable.yukihookapi.hook.factory.method
|
||||
@@ -58,7 +66,18 @@ import java.io.Serializable
|
||||
import java.math.RoundingMode
|
||||
import java.text.DecimalFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* 当前系统环境是否为简体中文
|
||||
* @return [Boolean]
|
||||
*/
|
||||
val isSystemLanguageSimplifiedChinese
|
||||
get(): Boolean {
|
||||
val locale = Locale.getDefault()
|
||||
return locale.language == "zh" && locale.country == "CN"
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统深色模式是否开启
|
||||
@@ -107,7 +126,7 @@ fun Resources.colorOf(@ColorRes resId: Int) = ResourcesCompat.getColor(this, res
|
||||
* @return [PackageInfo] or null
|
||||
*/
|
||||
private fun Context.getPackageInfoCompat(packageName: String, flag: Number = 0) = runCatching {
|
||||
@Suppress("DEPRECATION")
|
||||
@Suppress("DEPRECATION", "KotlinRedundantDiagnosticSuppress")
|
||||
if (Build.VERSION.SDK_INT >= 33)
|
||||
packageManager?.getPackageInfo(packageName, PackageInfoFlags.of(flag.toLong()))
|
||||
else packageManager?.getPackageInfo(packageName, flag.toInt())
|
||||
@@ -124,7 +143,7 @@ private val PackageInfo.versionCodeCompat get() = PackageInfoCompat.getLongVersi
|
||||
* @return [List]<[PackageInfo]>
|
||||
*/
|
||||
fun Context.listOfPackages() = runCatching {
|
||||
@Suppress("DEPRECATION")
|
||||
@Suppress("DEPRECATION", "KotlinRedundantDiagnosticSuppress")
|
||||
if (Build.VERSION.SDK_INT >= 33)
|
||||
packageManager?.getInstalledPackages(PackageInfoFlags.of(PackageManager.GET_CONFIGURATIONS.toLong()))
|
||||
else packageManager?.getInstalledPackages(PackageManager.GET_CONFIGURATIONS)
|
||||
@@ -306,7 +325,7 @@ inline fun <reified T : Activity> Context.navigate(isOutSide: Boolean = false, i
|
||||
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(BuildConfig.APPLICATION_ID, T::class.java.name)
|
||||
if (isOutSide) component = ComponentName(BuildConfigWrapper.APPLICATION_ID, T::class.java.name)
|
||||
initiate(this)
|
||||
})
|
||||
}.onFailure { toast(msg = "Start ${T::class.java.name} failed") }
|
||||
@@ -377,7 +396,10 @@ fun Context.openApp(packageName: String = getPackageName(), userId: Int = 0) = r
|
||||
* 是否有 Root 权限
|
||||
* @return [Boolean]
|
||||
*/
|
||||
val isRootAccess get() = runCatching { Shell.rootAccess() }.getOrNull() ?: false
|
||||
val isRootAccess get() = runCatching {
|
||||
@Suppress("DEPRECATION")
|
||||
Shell.rootAccess()
|
||||
}.getOrNull() ?: false
|
||||
|
||||
/**
|
||||
* 执行命令
|
||||
@@ -386,6 +408,7 @@ val isRootAccess get() = runCatching { Shell.rootAccess() }.getOrNull() ?: false
|
||||
* @return [String] 执行结果
|
||||
*/
|
||||
fun execShell(cmd: String, isSu: Boolean = true) = runCatching {
|
||||
@Suppress("DEPRECATION")
|
||||
(if (isSu) Shell.su(cmd) else Shell.sh(cmd)).exec().out.let {
|
||||
if (it.isNotEmpty()) it[0].trim() else ""
|
||||
}
|
||||
@@ -399,7 +422,7 @@ fun execShell(cmd: String, isSu: Boolean = true) = runCatching {
|
||||
*/
|
||||
fun Context.hideOrShowLauncherIcon(isShow: Boolean) {
|
||||
packageManager?.setComponentEnabledSetting(
|
||||
ComponentName(packageName, "${BuildConfig.APPLICATION_ID}.Home"),
|
||||
ComponentName(packageName, "${BuildConfigWrapper.APPLICATION_ID}.Home"),
|
||||
if (isShow) PackageManager.COMPONENT_ENABLED_STATE_DISABLED else PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
|
||||
PackageManager.DONT_KILL_APP
|
||||
)
|
||||
@@ -411,5 +434,5 @@ fun Context.hideOrShowLauncherIcon(isShow: Boolean) {
|
||||
*/
|
||||
val Context.isLauncherIconShowing
|
||||
get() = packageManager?.getComponentEnabledSetting(
|
||||
ComponentName(packageName, "${BuildConfig.APPLICATION_ID}.Home")
|
||||
ComponentName(packageName, "${BuildConfigWrapper.APPLICATION_ID}.Home")
|
||||
) != PackageManager.COMPONENT_ENABLED_STATE_DISABLED
|
@@ -25,7 +25,7 @@ package com.fankes.apperrorstracking.utils.tool
|
||||
|
||||
import android.app.Application
|
||||
import android.widget.CompoundButton
|
||||
import com.fankes.apperrorstracking.BuildConfig
|
||||
import com.fankes.apperrorstracking.generated.ModuleAppProperties
|
||||
import com.highcapable.yukihookapi.hook.factory.prefs
|
||||
import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData
|
||||
import com.microsoft.appcenter.AppCenter
|
||||
@@ -38,7 +38,7 @@ import com.microsoft.appcenter.crashes.Crashes
|
||||
object AppAnalyticsTool {
|
||||
|
||||
/** App Secret */
|
||||
private const val APP_CENTER_SECRET = BuildConfig.APP_CENTER_SECRET
|
||||
private const val APP_CENTER_SECRET = ModuleAppProperties.APP_CENTER_SECRET
|
||||
|
||||
/** 启用匿名统计收集使用情况功能 */
|
||||
private val ENABLE_APP_CENTER_ANALYTICS = PrefsData("_enable_app_center_analytics", true)
|
||||
@@ -56,6 +56,9 @@ object AppAnalyticsTool {
|
||||
instance?.prefs()?.edit { put(ENABLE_APP_CENTER_ANALYTICS, value) }
|
||||
}
|
||||
|
||||
/** 是否可用 */
|
||||
val isAvailable = APP_CENTER_SECRET.isNotBlank()
|
||||
|
||||
/** 绑定到 [CompoundButton] 自动设置选中状态 */
|
||||
fun CompoundButton.bindAppAnalytics() {
|
||||
isChecked = isEnableAppCenterAnalytics
|
||||
@@ -81,7 +84,7 @@ object AppAnalyticsTool {
|
||||
*/
|
||||
fun init(instance: Application) {
|
||||
this.instance = instance
|
||||
if (isEnableAppCenterAnalytics && APP_CENTER_SECRET.isNotBlank())
|
||||
if (isEnableAppCenterAnalytics && isAvailable)
|
||||
AppCenter.start(instance, APP_CENTER_SECRET, Analytics::class.java, Crashes::class.java)
|
||||
}
|
||||
}
|
@@ -19,8 +19,6 @@
|
||||
*
|
||||
* This file is Created by fankes on 2022/5/12.
|
||||
*/
|
||||
@file:Suppress("UNCHECKED_CAST")
|
||||
|
||||
package com.fankes.apperrorstracking.utils.tool
|
||||
|
||||
import android.content.Context
|
||||
@@ -28,6 +26,7 @@ import com.fankes.apperrorstracking.bean.AppErrorsInfoBean
|
||||
import com.fankes.apperrorstracking.bean.AppFiltersBean
|
||||
import com.fankes.apperrorstracking.bean.AppInfoBean
|
||||
import com.fankes.apperrorstracking.bean.MutedErrorsAppBean
|
||||
import com.fankes.apperrorstracking.const.PackageName
|
||||
import com.fankes.apperrorstracking.locale.LocaleString
|
||||
import com.fankes.apperrorstracking.utils.factory.execShell
|
||||
import com.fankes.apperrorstracking.utils.factory.isRootAccess
|
||||
@@ -41,9 +40,6 @@ import com.highcapable.yukihookapi.hook.xposed.channel.data.ChannelData
|
||||
*/
|
||||
object FrameworkTool {
|
||||
|
||||
/** 系统框架包名 */
|
||||
const val SYSTEM_FRAMEWORK_NAME = "android"
|
||||
|
||||
private const val CALL_REFRESH_HOST_PREFS_DATA = "call_refresh_host_prefs_data"
|
||||
private const val CALL_APP_ERRORS_DATA_GET = "call_app_errors_data_get"
|
||||
private const val CALL_MUTED_ERRORS_APP_DATA_GET = "call_muted_app_errors_data_get"
|
||||
@@ -249,13 +245,13 @@ object FrameworkTool {
|
||||
* @param result 成功后回调
|
||||
*/
|
||||
fun checkingActivated(context: Context, result: (Boolean) -> Unit) =
|
||||
context.dataChannel(SYSTEM_FRAMEWORK_NAME).checkingVersionEquals(result = result)
|
||||
context.dataChannel(PackageName.SYSTEM_FRAMEWORK).checkingVersionEquals(result = result)
|
||||
|
||||
/**
|
||||
* 通知系统框架刷新存储的数据
|
||||
* @param context 实例
|
||||
*/
|
||||
fun refreshFrameworkPrefsData(context: Context) = context.dataChannel(SYSTEM_FRAMEWORK_NAME).put(CALL_REFRESH_HOST_PREFS_DATA)
|
||||
fun refreshFrameworkPrefsData(context: Context) = context.dataChannel(PackageName.SYSTEM_FRAMEWORK).put(CALL_REFRESH_HOST_PREFS_DATA)
|
||||
|
||||
/**
|
||||
* 使用系统框架打开 [packageName]
|
||||
@@ -264,7 +260,7 @@ object FrameworkTool {
|
||||
* @param userId APP 用户 ID
|
||||
*/
|
||||
fun openAppUsedFramework(context: Context, packageName: String, userId: Int) =
|
||||
context.dataChannel(SYSTEM_FRAMEWORK_NAME).put(CALL_OPEN_SPECIFY_APP, Pair(packageName, userId))
|
||||
context.dataChannel(PackageName.SYSTEM_FRAMEWORK).put(CALL_OPEN_SPECIFY_APP, Pair(packageName, userId))
|
||||
|
||||
/**
|
||||
* 获取指定 APP 异常信息
|
||||
@@ -273,7 +269,7 @@ object FrameworkTool {
|
||||
* @param result 回调数据
|
||||
*/
|
||||
fun fetchAppErrorInfoData(context: Context, pid: Int, result: (AppErrorsInfoBean) -> Unit) {
|
||||
context.dataChannel(SYSTEM_FRAMEWORK_NAME).with {
|
||||
context.dataChannel(PackageName.SYSTEM_FRAMEWORK).with {
|
||||
wait(CALL_APP_ERROR_DATA_GET_RESULT) { result(it) }
|
||||
put(CALL_APP_ERROR_DATA_GET, pid)
|
||||
}
|
||||
@@ -285,7 +281,7 @@ object FrameworkTool {
|
||||
* @param result 回调数据
|
||||
*/
|
||||
fun fetchAppErrorsInfoData(context: Context, result: (ArrayList<AppErrorsInfoBean>) -> Unit) {
|
||||
context.dataChannel(SYSTEM_FRAMEWORK_NAME).with {
|
||||
context.dataChannel(PackageName.SYSTEM_FRAMEWORK).with {
|
||||
wait(CALL_APP_ERRORS_DATA_GET_RESULT) { result(it) }
|
||||
put(CALL_APP_ERRORS_DATA_GET)
|
||||
}
|
||||
@@ -298,7 +294,7 @@ object FrameworkTool {
|
||||
* @param callback 成功后回调
|
||||
*/
|
||||
fun removeAppErrorsInfoData(context: Context, appErrorsInfo: AppErrorsInfoBean, callback: () -> Unit) {
|
||||
context.dataChannel(SYSTEM_FRAMEWORK_NAME).with {
|
||||
context.dataChannel(PackageName.SYSTEM_FRAMEWORK).with {
|
||||
wait(CALL_APP_ERRORS_DATA_REMOVE_RESULT) { callback() }
|
||||
put(CALL_APP_ERRORS_DATA_REMOVE, appErrorsInfo)
|
||||
}
|
||||
@@ -310,7 +306,7 @@ object FrameworkTool {
|
||||
* @param callback 成功后回调
|
||||
*/
|
||||
fun clearAppErrorsInfoData(context: Context, callback: () -> Unit) {
|
||||
context.dataChannel(SYSTEM_FRAMEWORK_NAME).with {
|
||||
context.dataChannel(PackageName.SYSTEM_FRAMEWORK).with {
|
||||
wait(CALL_APP_ERRORS_DATA_CLEAR_RESULT) { callback() }
|
||||
put(CALL_APP_ERRORS_DATA_CLEAR)
|
||||
}
|
||||
@@ -323,7 +319,7 @@ object FrameworkTool {
|
||||
* @param callback 成功后回调
|
||||
*/
|
||||
fun mutedErrorsIfUnlock(context: Context, packageName: String, callback: () -> Unit) {
|
||||
context.dataChannel(SYSTEM_FRAMEWORK_NAME).with {
|
||||
context.dataChannel(PackageName.SYSTEM_FRAMEWORK).with {
|
||||
wait(CALL_MUTED_ERRORS_IF_UNLOCK_RESULT) { callback() }
|
||||
put(CALL_MUTED_ERRORS_IF_UNLOCK, packageName)
|
||||
}
|
||||
@@ -336,7 +332,7 @@ object FrameworkTool {
|
||||
* @param callback 成功后回调
|
||||
*/
|
||||
fun mutedErrorsIfRestart(context: Context, packageName: String, callback: () -> Unit) {
|
||||
context.dataChannel(SYSTEM_FRAMEWORK_NAME).with {
|
||||
context.dataChannel(PackageName.SYSTEM_FRAMEWORK).with {
|
||||
wait(CALL_MUTED_ERRORS_IF_RESTART_RESULT) { callback() }
|
||||
put(CALL_MUTED_ERRORS_IF_RESTART, packageName)
|
||||
}
|
||||
@@ -348,7 +344,7 @@ object FrameworkTool {
|
||||
* @param result 回调数据
|
||||
*/
|
||||
fun fetchMutedErrorsAppsData(context: Context, result: (ArrayList<MutedErrorsAppBean>) -> Unit) {
|
||||
context.dataChannel(SYSTEM_FRAMEWORK_NAME).with {
|
||||
context.dataChannel(PackageName.SYSTEM_FRAMEWORK).with {
|
||||
wait(CALL_MUTED_ERRORS_APP_DATA_GET_RESULT) { result(it) }
|
||||
put(CALL_MUTED_ERRORS_APP_DATA_GET)
|
||||
}
|
||||
@@ -361,7 +357,7 @@ object FrameworkTool {
|
||||
* @param callback 成功后回调
|
||||
*/
|
||||
fun unmuteErrorsApp(context: Context, mutedErrorsApp: MutedErrorsAppBean, callback: () -> Unit) {
|
||||
context.dataChannel(SYSTEM_FRAMEWORK_NAME).with {
|
||||
context.dataChannel(PackageName.SYSTEM_FRAMEWORK).with {
|
||||
wait(CALL_UNMUTE_ERRORS_APP_DATA_RESULT) { callback() }
|
||||
put(CALL_UNMUTE_ERRORS_APP_DATA, mutedErrorsApp)
|
||||
}
|
||||
@@ -373,7 +369,7 @@ object FrameworkTool {
|
||||
* @param callback 成功后回调
|
||||
*/
|
||||
fun unmuteAllErrorsApps(context: Context, callback: () -> Unit) {
|
||||
context.dataChannel(SYSTEM_FRAMEWORK_NAME).with {
|
||||
context.dataChannel(PackageName.SYSTEM_FRAMEWORK).with {
|
||||
wait(CALL_UNMUTE_ALL_ERRORS_APPS_DATA_RESULT) { callback() }
|
||||
put(CALL_UNMUTE_ALL_ERRORS_APPS_DATA)
|
||||
}
|
||||
@@ -386,7 +382,7 @@ object FrameworkTool {
|
||||
* @param result 回调数据
|
||||
*/
|
||||
fun fetchAppListData(context: Context, appFilters: AppFiltersBean, result: (ArrayList<AppInfoBean>) -> Unit) {
|
||||
context.dataChannel(SYSTEM_FRAMEWORK_NAME).with {
|
||||
context.dataChannel(PackageName.SYSTEM_FRAMEWORK).with {
|
||||
wait(CALL_APP_LIST_DATA_GET_RESULT) { result(it) }
|
||||
put(CALL_APP_LIST_DATA_GET, appFilters)
|
||||
}
|
@@ -29,11 +29,15 @@ import android.icu.util.TimeZone
|
||||
import com.fankes.apperrorstracking.locale.LocaleString
|
||||
import com.fankes.apperrorstracking.utils.factory.openBrowser
|
||||
import com.fankes.apperrorstracking.utils.factory.showDialog
|
||||
import okhttp3.*
|
||||
import okhttp3.Call
|
||||
import okhttp3.Callback
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.json.JSONObject
|
||||
import java.io.IOException
|
||||
import java.io.Serializable
|
||||
import java.util.*
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* 获取 GitHub Release 最新版本工具类
|
@@ -23,7 +23,13 @@
|
||||
|
||||
package com.fankes.apperrorstracking.utils.tool
|
||||
|
||||
import java.io.*
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
import java.util.zip.ZipOutputStream
|
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer.
|
||||
* Copyright (C) 2017-2023 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 2023/9/19.
|
||||
*/
|
||||
@file:Suppress("unused")
|
||||
|
||||
package com.fankes.apperrorstracking.wrapper
|
||||
|
||||
import com.fankes.apperrorstracking.BuildConfig
|
||||
|
||||
/**
|
||||
* 对 [BuildConfig] 的包装
|
||||
*/
|
||||
object BuildConfigWrapper {
|
||||
const val APPLICATION_ID = BuildConfig.APPLICATION_ID
|
||||
const val VERSION_NAME = BuildConfig.VERSION_NAME
|
||||
const val VERSION_CODE = BuildConfig.VERSION_CODE
|
||||
val isDebug = BuildConfig.DEBUG
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user