mirror of
https://github.com/KitsunePie/AppErrorsTracking.git
synced 2025-09-01 08:45:16 +08:00
feat: add stack trace share optional dialog
This commit is contained in:
@@ -183,43 +183,67 @@ data class AppErrorsInfoBean(
|
||||
|
||||
/**
|
||||
* 获取异常堆栈分享模板
|
||||
* @param sDeviceBrand
|
||||
* @param sDeviceModel
|
||||
* @param sDisplay
|
||||
* @param sPackageName
|
||||
* @return [String]
|
||||
*/
|
||||
val stackOutputShareContent
|
||||
get() = """
|
||||
fun stackOutputShareContent(
|
||||
sDeviceBrand: Boolean = true,
|
||||
sDeviceModel: Boolean = true,
|
||||
sDisplay: Boolean = true,
|
||||
sPackageName: Boolean = true
|
||||
) = """
|
||||
Generated by AppErrorsTracking $ModuleVersion
|
||||
Project URL: https://github.com/KitsunePie/AppErrorsTracking
|
||||
===============
|
||||
""".trimIndent() + "\n$environmentInfo"
|
||||
""".trimIndent() + "\n${environmentInfo(sDeviceBrand, sDeviceModel, sDisplay, sPackageName)}"
|
||||
|
||||
/**
|
||||
* 获取异常堆栈文件模板
|
||||
* @param sDeviceBrand
|
||||
* @param sDeviceModel
|
||||
* @param sDisplay
|
||||
* @param sPackageName
|
||||
* @return [String]
|
||||
*/
|
||||
val stackOutputFileContent
|
||||
get() = """
|
||||
fun stackOutputFileContent(
|
||||
sDeviceBrand: Boolean = true,
|
||||
sDeviceModel: Boolean = true,
|
||||
sDisplay: Boolean = true,
|
||||
sPackageName: Boolean = true
|
||||
) = """
|
||||
================================================================
|
||||
Generated by AppErrorsTracking $ModuleVersion
|
||||
Project URL: https://github.com/KitsunePie/AppErrorsTracking
|
||||
================================================================
|
||||
""".trimIndent() + "\n$environmentInfo"
|
||||
""".trimIndent() + "\n${environmentInfo(sDeviceBrand, sDeviceModel, sDisplay, sPackageName)}"
|
||||
|
||||
/**
|
||||
* 获取运行环境信息
|
||||
* @param sDeviceBrand
|
||||
* @param sDeviceModel
|
||||
* @param sDisplay
|
||||
* @param sPackageName
|
||||
* @return [String]
|
||||
*/
|
||||
private val environmentInfo
|
||||
get() = """
|
||||
[Device Brand]: ${Build.BRAND}
|
||||
[Device Model]: ${Build.MODEL}
|
||||
[Display]: ${Build.DISPLAY}
|
||||
private fun environmentInfo(
|
||||
sDeviceBrand: Boolean,
|
||||
sDeviceModel: Boolean,
|
||||
sDisplay: Boolean,
|
||||
sPackageName: Boolean
|
||||
) = """
|
||||
[Device Brand]: ${Build.BRAND.by(sDeviceBrand)}
|
||||
[Device Model]: ${Build.MODEL.by(sDeviceModel)}
|
||||
[Display]: ${Build.DISPLAY.by(sDisplay)}
|
||||
[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
|
||||
[Package Name]: ${packageName.by(sPackageName)}
|
||||
[Version Name]: ${versionName.ifBlank { "unknown" }}
|
||||
[Version Code]: ${versionCode.takeIf { it != -1L } ?: "unknown"}
|
||||
[Target SDK]: ${targetSdk.takeIf { it != -1 } ?: "unknown"}
|
||||
@@ -227,5 +251,12 @@ data class AppErrorsInfoBean(
|
||||
[Error Type]: ${if (isNativeCrash) "Native" else "JVM"}
|
||||
[Crash Time]: $utcTime
|
||||
[Stack Trace]:
|
||||
""".trimIndent() + "\n$stackTrace"
|
||||
""".trimIndent() + "\n$stackTrace"
|
||||
|
||||
/**
|
||||
* 判断字符串是否需要显示
|
||||
* @param isDisplay 是否需要显示
|
||||
* @return [String]
|
||||
*/
|
||||
private fun String.by(isDisplay: Boolean) = if (isDisplay) this else "***"
|
||||
}
|
@@ -45,6 +45,7 @@ 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.StackTraceShareHelper
|
||||
import com.highcapable.yukihookapi.hook.log.loggerE
|
||||
|
||||
class AppErrorsDetailActivity : BaseActivity<ActivityAppErrorsDetailBinding>() {
|
||||
@@ -121,22 +122,31 @@ class AppErrorsDetailActivity : BaseActivity<ActivityAppErrorsDetailBinding>() {
|
||||
loggerE(msg = appErrorsInfo.stackTrace)
|
||||
toast(locale.printToLogcatSuccess)
|
||||
}
|
||||
binding.copyIcon.setOnClickListener { copyToClipboard(appErrorsInfo.stackOutputShareContent) }
|
||||
binding.copyIcon.setOnClickListener {
|
||||
StackTraceShareHelper.showChoose(context = this, locale.copyErrorStack) { sDeviceBrand, sDeviceModel, sDisplay, sPackageName ->
|
||||
copyToClipboard(appErrorsInfo.stackOutputShareContent(sDeviceBrand, sDeviceModel, sDisplay, sPackageName))
|
||||
}
|
||||
}
|
||||
binding.exportIcon.setOnClickListener {
|
||||
stackTrace = appErrorsInfo.stackOutputFileContent
|
||||
runCatching {
|
||||
startActivityForResult(Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "*/application"
|
||||
putExtra(Intent.EXTRA_TITLE, "${appErrorsInfo.packageName}_${appErrorsInfo.utcTime}.log")
|
||||
}, WRITE_REQUEST_CODE)
|
||||
}.onFailure { toast(msg = "Start Android SAF failed") }
|
||||
StackTraceShareHelper.showChoose(context = this, locale.exportToFile) { sDeviceBrand, sDeviceModel, sDisplay, sPackageName ->
|
||||
stackTrace = appErrorsInfo.stackOutputFileContent(sDeviceBrand, sDeviceModel, sDisplay, sPackageName)
|
||||
runCatching {
|
||||
startActivityForResult(Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "*/application"
|
||||
val packageName = if (sPackageName) appErrorsInfo.packageName else "anonymous"
|
||||
putExtra(Intent.EXTRA_TITLE, "${packageName}_${appErrorsInfo.utcTime}.log")
|
||||
}, WRITE_REQUEST_CODE)
|
||||
}.onFailure { toast(msg = "Start Android SAF failed") }
|
||||
}
|
||||
}
|
||||
binding.shareIcon.setOnClickListener {
|
||||
startActivity(Intent.createChooser(Intent(Intent.ACTION_SEND).apply {
|
||||
type = "text/plain"
|
||||
putExtra(Intent.EXTRA_TEXT, appErrorsInfo.stackOutputShareContent)
|
||||
}, locale.shareErrorStack))
|
||||
StackTraceShareHelper.showChoose(context = this, locale.shareErrorStack) { sDeviceBrand, sDeviceModel, sDisplay, sPackageName ->
|
||||
startActivity(Intent.createChooser(Intent(Intent.ACTION_SEND).apply {
|
||||
type = "text/plain"
|
||||
putExtra(Intent.EXTRA_TEXT, appErrorsInfo.stackOutputShareContent(sDeviceBrand, sDeviceModel, sDisplay, sPackageName))
|
||||
}, locale.shareErrorStack))
|
||||
}
|
||||
}
|
||||
binding.appIcon.setImageDrawable(appIconOf(appErrorsInfo.packageName))
|
||||
binding.appNameText.text = appNameOf(appErrorsInfo.packageName).ifBlank { appErrorsInfo.packageName }
|
||||
|
@@ -50,6 +50,7 @@ import com.fankes.apperrorstracking.utils.factory.showDialog
|
||||
import com.fankes.apperrorstracking.utils.factory.toUtcTime
|
||||
import com.fankes.apperrorstracking.utils.factory.toast
|
||||
import com.fankes.apperrorstracking.utils.tool.FrameworkTool
|
||||
import com.fankes.apperrorstracking.utils.tool.StackTraceShareHelper
|
||||
import com.fankes.apperrorstracking.utils.tool.ZipFileTool
|
||||
import com.fankes.apperrorstracking.wrapper.BuildConfigWrapper
|
||||
import java.io.File
|
||||
@@ -176,20 +177,24 @@ class AppErrorsRecordActivity : BaseActivity<ActivityAppErrorsRecordBinding>() {
|
||||
/** 打包导出全部 */
|
||||
private fun exportAll() {
|
||||
clearAllExportTemp()
|
||||
("${cacheDir.absolutePath}/temp").also { path ->
|
||||
File(path).mkdirs()
|
||||
listData.takeIf { it.isNotEmpty() }?.forEach {
|
||||
File("$path/${it.packageName}_${it.utcTime}.log").writeText(it.stackOutputFileContent)
|
||||
StackTraceShareHelper.showChoose(context = this, locale.exportAll) { sDeviceBrand, sDeviceModel, sDisplay, sPackageName ->
|
||||
("${cacheDir.absolutePath}/temp").also { path ->
|
||||
File(path).mkdirs()
|
||||
listData.takeIf { it.isNotEmpty() }?.forEachIndexed { index, bean ->
|
||||
val packageName = if (sPackageName) bean.packageName else "anonymous_$index"
|
||||
File("$path/${packageName}_${bean.utcTime}.log")
|
||||
.writeText(bean.stackOutputFileContent(sDeviceBrand, sDeviceModel, sDisplay, sPackageName))
|
||||
}
|
||||
outPutFilePath = "${cacheDir.absolutePath}/temp_${System.currentTimeMillis()}.zip"
|
||||
ZipFileTool.zipMultiFile(path, outPutFilePath)
|
||||
runCatching {
|
||||
startActivityForResult(Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "*/application"
|
||||
putExtra(Intent.EXTRA_TITLE, "app_errors_info_${System.currentTimeMillis().toUtcTime()}.zip")
|
||||
}, WRITE_REQUEST_CODE)
|
||||
}.onFailure { toast(msg = "Start Android SAF failed") }
|
||||
}
|
||||
outPutFilePath = "${cacheDir.absolutePath}/temp_${System.currentTimeMillis()}.zip"
|
||||
ZipFileTool.zipMultiFile(path, outPutFilePath)
|
||||
runCatching {
|
||||
startActivityForResult(Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "*/application"
|
||||
putExtra(Intent.EXTRA_TITLE, "app_errors_info_${System.currentTimeMillis().toUtcTime()}.zip")
|
||||
}, WRITE_REQUEST_CODE)
|
||||
}.onFailure { toast(msg = "Start Android SAF failed") }
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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/11/3.
|
||||
*/
|
||||
package com.fankes.apperrorstracking.utils.tool
|
||||
|
||||
import android.content.Context
|
||||
import com.fankes.apperrorstracking.databinding.DiaStackTraceShareBinding
|
||||
import com.fankes.apperrorstracking.utils.factory.showDialog
|
||||
|
||||
/**
|
||||
* 异常堆栈分享工具类
|
||||
*/
|
||||
object StackTraceShareHelper {
|
||||
|
||||
/**
|
||||
* 显示分享选择器
|
||||
* @param context 当前实例
|
||||
* @param title 对话框标题
|
||||
* @param onChoose 回调选择的结果
|
||||
*/
|
||||
fun showChoose(
|
||||
context: Context,
|
||||
title: String,
|
||||
onChoose: (sDeviceBrand: Boolean, sDeviceModel: Boolean, sDisplay: Boolean, sPackageName: Boolean) -> Unit
|
||||
) {
|
||||
context.showDialog<DiaStackTraceShareBinding> {
|
||||
this.title = title
|
||||
confirmButton {
|
||||
val sDeviceBrand = binding.configCheck0.isChecked
|
||||
val sDeviceModel = binding.configCheck1.isChecked
|
||||
val sDisplay = binding.configCheck2.isChecked
|
||||
val sPackageName = binding.configCheck3.isChecked
|
||||
onChoose(sDeviceBrand, sDeviceModel, sDisplay, sPackageName)
|
||||
cancel()
|
||||
}
|
||||
cancelButton()
|
||||
}
|
||||
}
|
||||
}
|
73
module-app/src/main/res/layout/dia_stack_trace_share.xml
Normal file
73
module-app/src/main/res/layout/dia_stack_trace_share.xml
Normal file
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="15dp"
|
||||
android:paddingTop="15dp"
|
||||
android:paddingRight="15dp"
|
||||
tools:ignore="HardcodedText">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8.5dp"
|
||||
android:layout_marginRight="8.5dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:lineSpacingExtra="6dp"
|
||||
android:text="@string/stack_trace_share_top_tip"
|
||||
android:textSize="13sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8.5dp"
|
||||
android:layout_marginRight="8.5dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:lineSpacingExtra="6dp"
|
||||
android:text="@string/stack_trace_share_bottom_tip"
|
||||
android:textColor="#FFFF5722"
|
||||
android:textSize="13sp" />
|
||||
|
||||
<com.google.android.material.checkbox.MaterialCheckBox
|
||||
android:id="@+id/config_check_0"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"
|
||||
android:text="@string/stack_trace_share_device_brand"
|
||||
app:buttonTint="@color/colorPrimaryAccent" />
|
||||
|
||||
<com.google.android.material.checkbox.MaterialCheckBox
|
||||
android:id="@+id/config_check_1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"
|
||||
android:text="@string/stack_trace_share_device_model"
|
||||
app:buttonTint="@color/colorPrimaryAccent" />
|
||||
|
||||
<com.google.android.material.checkbox.MaterialCheckBox
|
||||
android:id="@+id/config_check_2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"
|
||||
android:text="@string/stack_trace_share_system_build_id"
|
||||
app:buttonTint="@color/colorPrimaryAccent" />
|
||||
|
||||
<com.google.android.material.checkbox.MaterialCheckBox
|
||||
android:id="@+id/config_check_3"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"
|
||||
android:text="@string/stack_trace_share_package_name"
|
||||
app:buttonTint="@color/colorPrimaryAccent" />
|
||||
|
||||
<com.google.android.material.checkbox.MaterialCheckBox
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"
|
||||
android:enabled="false"
|
||||
android:text="@string/stack_trace_share_other"
|
||||
app:buttonTint="@color/colorPrimaryAccent" />
|
||||
</LinearLayout>
|
@@ -148,4 +148,11 @@
|
||||
<string name="record_count">%1$s の合計紀錄</string>
|
||||
<string name="ci_notice_dialog_title">CI 自動ビルド手順</string>
|
||||
<string name="ci_notice_dialog_content">コミット ID %1$s の CI 自動ビルドを使用しています。\n\nコードが送信された後、自動的にトリガーされてビルドされ、自動的にコンパイルされてリリースされますが、安定性についてはテストされていません。ご自身の責任で使用してください。</string>
|
||||
<string name="stack_trace_share_top_tip">共有したいコンテンツを選択すると、表示したくないコンテンツの一部を非表示にすることができます。</string>
|
||||
<string name="stack_trace_share_bottom_tip">システム言語地域、バージョン、アプリケーションのバージョン、およびエラー ログは、非表示にしてはいけないコンテンツとして共有する必要があります。これらのコンテンツは、開発者が問題を特定するのに役立ちます。</string>
|
||||
<string name="stack_trace_share_device_brand">デバイスのブランド</string>
|
||||
<string name="stack_trace_share_device_model">デバイスモデル</string>
|
||||
<string name="stack_trace_share_system_build_id">システムビルドID</string>
|
||||
<string name="stack_trace_share_package_name">アプリのパッケージ名</string>
|
||||
<string name="stack_trace_share_other">その他の要件</string>
|
||||
</resources>
|
@@ -148,4 +148,11 @@
|
||||
<string name="record_count">共 %1$s 条记录</string>
|
||||
<string name="ci_notice_dialog_title">CI 自动构建说明</string>
|
||||
<string name="ci_notice_dialog_content">你正在使用的是 CI 自动构建版本,Commit ID 为 %1$s。\n\n它是由代码提交后自动触发并构建、自动编译发布的,并未经任何稳定性测试,使用风险自负。</string>
|
||||
<string name="stack_trace_share_top_tip">选择你想要分享的内容,你可以隐藏部分你不想展示的内容。</string>
|
||||
<string name="stack_trace_share_bottom_tip">系统语言区域、版本、应用版本和错误日志等作为必须分享的内容不能被隐藏,这些内容都有助于帮助开发者定位问题。</string>
|
||||
<string name="stack_trace_share_device_brand">设备制造商</string>
|
||||
<string name="stack_trace_share_device_model">设备型号</string>
|
||||
<string name="stack_trace_share_system_build_id">系统构建 ID</string>
|
||||
<string name="stack_trace_share_package_name">APP 包名</string>
|
||||
<string name="stack_trace_share_other">其它必要信息</string>
|
||||
</resources>
|
@@ -148,4 +148,11 @@
|
||||
<string name="record_count">共 %1$s 條紀錄</string>
|
||||
<string name="ci_notice_dialog_title">CI 自動建置說明</string>
|
||||
<string name="ci_notice_dialog_content">你正在使用的是 CI 自動建置版本,Commit ID 為 %1$s。\n\n它是由程式碼提交後自動觸發並建置、自動編譯發布的,並未經任何穩定性測試,使用風險自負。</string>
|
||||
<string name="stack_trace_share_top_tip">選擇您要分享的內容,您可以隱藏一些您不想顯示的內容。</string>
|
||||
<string name="stack_trace_share_bottom_tip">系統語言區域、版本、應用程式版本和錯誤日誌必須作為內容共享,且不得隱藏,這些內容將幫助開發人員定位問題。</string>
|
||||
<string name="stack_trace_share_device_brand">設備品牌</string>
|
||||
<string name="stack_trace_share_device_model">設備型號</string>
|
||||
<string name="stack_trace_share_system_build_id">系統建置 ID</string>
|
||||
<string name="stack_trace_share_package_name">應用程式包名稱</string>
|
||||
<string name="stack_trace_share_other">其它必要資訊</string>
|
||||
</resources>
|
@@ -148,4 +148,11 @@
|
||||
<string name="record_count">共 %1$s 條紀錄</string>
|
||||
<string name="ci_notice_dialog_title">CI 自動建置說明</string>
|
||||
<string name="ci_notice_dialog_content">你正在使用的是 CI 自動建置版本,Commit ID 為 %1$s。\n\n它是由程式碼提交後自動觸發並建置、自動編譯發布的,並未經任何穩定性測試,使用風險自負。</string>
|
||||
<string name="stack_trace_share_top_tip">選擇您要分享的內容,您可以隱藏一些您不想顯示的內容。</string>
|
||||
<string name="stack_trace_share_bottom_tip">系統語言區域、版本、應用程式版本和錯誤日誌必須作為內容共享,且不得隱藏,這些內容將幫助開發人員定位問題。</string>
|
||||
<string name="stack_trace_share_device_brand">設備品牌</string>
|
||||
<string name="stack_trace_share_device_model">設備型號</string>
|
||||
<string name="stack_trace_share_system_build_id">系統建置 ID</string>
|
||||
<string name="stack_trace_share_package_name">應用程式包名稱</string>
|
||||
<string name="stack_trace_share_other">其它必要資訊</string>
|
||||
</resources>
|
@@ -148,4 +148,11 @@
|
||||
<string name="record_count">共 %1$s 條紀錄</string>
|
||||
<string name="ci_notice_dialog_title">CI 自動建置說明</string>
|
||||
<string name="ci_notice_dialog_content">你正在使用的是 CI 自動建置版本,Commit ID 為 %1$s。\n\n它是由程式碼提交後自動觸發並建置、自動編譯發布的,並未經任何穩定性測試,使用風險自負。</string>
|
||||
<string name="stack_trace_share_top_tip">選擇您要分享的內容,您可以隱藏一些您不想顯示的內容。</string>
|
||||
<string name="stack_trace_share_bottom_tip">系統語言區域、版本、應用程式版本和錯誤日誌必須作為內容共享,且不得隱藏,這些內容將幫助開發人員定位問題。</string>
|
||||
<string name="stack_trace_share_device_brand">設備品牌</string>
|
||||
<string name="stack_trace_share_device_model">設備型號</string>
|
||||
<string name="stack_trace_share_system_build_id">系統建置 ID</string>
|
||||
<string name="stack_trace_share_package_name">應用程式包名稱</string>
|
||||
<string name="stack_trace_share_other">其它必要資訊</string>
|
||||
</resources>
|
@@ -151,4 +151,11 @@
|
||||
<string name="ci_notice_dialog_content">You are using a CI automated build with Commit ID %1$s.\n\nIt is automatically triggered and built after the code is committed, automatically compiled and released, and has not been tested for stability, use it at your own risk.</string>
|
||||
<string name="app_target_sdk" translatable="false">Target %1$s</string>
|
||||
<string name="app_min_sdk" translatable="false">Min %1$s</string>
|
||||
<string name="stack_trace_share_top_tip">Select the content you want to share, and you can hide some of the content you don\'t want to show.</string>
|
||||
<string name="stack_trace_share_bottom_tip">System language region, version, application version and error logs must be shared as content that must not be hidden, these content will help developers locate problems.</string>
|
||||
<string name="stack_trace_share_device_brand">Device Brand</string>
|
||||
<string name="stack_trace_share_device_model">Device Model</string>
|
||||
<string name="stack_trace_share_system_build_id">System Build ID</string>
|
||||
<string name="stack_trace_share_package_name">App Package Name</string>
|
||||
<string name="stack_trace_share_other">Other Requirement</string>
|
||||
</resources>
|
Reference in New Issue
Block a user