mirror of
https://github.com/KitsunePie/AppErrorsTracking.git
synced 2025-09-01 08:45:16 +08:00
Added debug log viewing function
This commit is contained in:
@@ -63,6 +63,11 @@
|
||||
android:exported="false"
|
||||
android:screenOrientation="behind" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.activity.debug.LoggerActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="behind" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.activity.errors.AppErrorsRecordActivity"
|
||||
android:exported="true"
|
||||
|
@@ -33,7 +33,10 @@ import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit
|
||||
class HookEntry : IYukiHookXposedInit {
|
||||
|
||||
override fun onInit() = configs {
|
||||
debugLog { tag = "AppErrorsTracking" }
|
||||
debugLog {
|
||||
tag = "AppErrorsTracking"
|
||||
isRecord = true
|
||||
}
|
||||
isDebug = false
|
||||
isEnableModulePrefsCache = false
|
||||
}
|
||||
|
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* 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/10/4.
|
||||
*/
|
||||
@file:Suppress("DEPRECATION", "OVERRIDE_DEPRECATION")
|
||||
|
||||
package com.fankes.apperrorstracking.ui.activity.debug
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.view.ContextMenu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import androidx.core.view.isVisible
|
||||
import com.fankes.apperrorstracking.R
|
||||
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.highcapable.yukihookapi.hook.factory.current
|
||||
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.*
|
||||
|
||||
class LoggerActivity : BaseActivity<ActivitiyLoggerBinding>() {
|
||||
|
||||
companion object {
|
||||
|
||||
/** 请求保存文件回调标识 */
|
||||
private const val WRITE_REQUEST_CODE = 0
|
||||
}
|
||||
|
||||
/** 回调适配器改变 */
|
||||
private var onChanged: (() -> Unit)? = null
|
||||
|
||||
/** 过滤条件 */
|
||||
private var filters = arrayListOf("D", "I", "W", "E")
|
||||
|
||||
/** 全部的调试日志数据 */
|
||||
private val listData = ArrayList<YukiLoggerData>()
|
||||
|
||||
override fun onCreate() {
|
||||
binding.titleBackIcon.setOnClickListener { finish() }
|
||||
binding.refreshIcon.setOnClickListener { refreshData() }
|
||||
binding.filterIcon.setOnClickListener {
|
||||
showDialog<DiaLoggerFilterBinding> {
|
||||
title = LocaleString.filterByCondition
|
||||
binding.configCheck0.isChecked = filters.any { it == "D" }
|
||||
binding.configCheck1.isChecked = filters.any { it == "I" }
|
||||
binding.configCheck2.isChecked = filters.any { it == "W" }
|
||||
binding.configCheck3.isChecked = filters.any { it == "E" }
|
||||
confirmButton {
|
||||
filters.clear()
|
||||
if (binding.configCheck0.isChecked) filters.add("D")
|
||||
if (binding.configCheck1.isChecked) filters.add("I")
|
||||
if (binding.configCheck2.isChecked) filters.add("W")
|
||||
if (binding.configCheck3.isChecked) filters.add("E")
|
||||
refreshData()
|
||||
}
|
||||
cancelButton()
|
||||
}
|
||||
}
|
||||
binding.exportAllIcon.setOnClickListener {
|
||||
runCatching {
|
||||
startActivityForResult(Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "*/application"
|
||||
putExtra(Intent.EXTRA_TITLE, "app_errors_tracking_${System.currentTimeMillis().toUtcTime()}.log")
|
||||
}, WRITE_REQUEST_CODE)
|
||||
}.onFailure { toast(msg = "Start Android SAF failed") }
|
||||
}
|
||||
/** 设置列表元素和 Adapter */
|
||||
binding.listView.apply {
|
||||
bindAdapter {
|
||||
onBindDatas { listData }
|
||||
onBindViews<AdapterLoggerBinding> { binding, position ->
|
||||
listData[position].also { bean ->
|
||||
binding.priorityText.apply {
|
||||
text = bean.priority
|
||||
setBackgroundResource(
|
||||
when (bean.priority) {
|
||||
"D" -> R.drawable.bg_logger_d_round
|
||||
"I" -> R.drawable.bg_logger_i_round
|
||||
"W" -> R.drawable.bg_logger_w_round
|
||||
"E" -> R.drawable.bg_logger_e_round
|
||||
else -> R.drawable.bg_logger_d_round
|
||||
}
|
||||
)
|
||||
}
|
||||
binding.messageText.text = bean.msg.format()
|
||||
binding.timeText.text = bean.timestamp.format()
|
||||
binding.throwableText.isVisible = bean.throwable != null
|
||||
binding.throwableText.text = bean.throwable?.toStackTrace() ?: ""
|
||||
}
|
||||
}
|
||||
}.apply { onChanged = { notifyDataSetChanged() } }
|
||||
registerForContextMenu(this)
|
||||
}
|
||||
}
|
||||
|
||||
/** 更新列表数据 */
|
||||
private fun refreshData() {
|
||||
dataChannel(FrameworkTool.SYSTEM_FRAMEWORK_NAME).obtainLoggerInMemoryData {
|
||||
listData.clear()
|
||||
it.takeIf { e -> e.isNotEmpty() }?.reversed()?.filter { filters.any { e -> it.priority == e } }?.forEach { e -> listData.add(e) }
|
||||
onChanged?.invoke()
|
||||
binding.listView.post { binding.listView.setSelection(0) }
|
||||
binding.exportAllIcon.isVisible = listData.isNotEmpty()
|
||||
binding.listView.isVisible = listData.isNotEmpty()
|
||||
binding.listNoDataView.isVisible = listData.isEmpty()
|
||||
binding.listNoDataView.text = if (filters.size < 4) LocaleString.noListResult else LocaleString.noListData
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前所有日志写出文件的格式
|
||||
*
|
||||
* 复制自 [YukiHookLogger.contents]
|
||||
* @return [String]
|
||||
*/
|
||||
private val loggerContents: String
|
||||
get() {
|
||||
var content = ""
|
||||
listData.takeIf { it.isNotEmpty() }?.forEach {
|
||||
val head = "${it.time} ------ "
|
||||
content += "$head$it\n"
|
||||
it.throwable?.also { e ->
|
||||
content += "${head}Dump stack trace for \"${e.current().name}\":\n"
|
||||
content += e.toStackTrace()
|
||||
}
|
||||
}
|
||||
return content
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化为本地时间格式
|
||||
* @return [String]
|
||||
*/
|
||||
private fun Long.format() = SimpleDateFormat.getDateTimeInstance().format(Date(this))
|
||||
|
||||
/**
|
||||
* 格式化消息字符串样式
|
||||
* @return [String]
|
||||
*/
|
||||
private fun String.format() = replace(oldValue = "--", newValue = "\n--")
|
||||
|
||||
/**
|
||||
* 获取完整的异常堆栈内容
|
||||
* @return [String]
|
||||
*/
|
||||
private fun Throwable.toStackTrace() = ByteArrayOutputStream().also { printStackTrace(PrintStream(it)) }.toString().trim()
|
||||
|
||||
override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) {
|
||||
menuInflater.inflate(R.menu.menu_logger_action, menu)
|
||||
super.onCreateContextMenu(menu, v, menuInfo)
|
||||
}
|
||||
|
||||
override fun onContextItemSelected(item: MenuItem): Boolean {
|
||||
if (item.menuInfo is AdapterView.AdapterContextMenuInfo)
|
||||
(item.menuInfo as? AdapterView.AdapterContextMenuInfo?)?.also {
|
||||
if (item.itemId == R.id.logger_copy)
|
||||
copyToClipboard(listData[it.position].let { e -> e.toString() + (e.throwable?.toStackTrace()?.let { t -> "\n$t" } ?: "") })
|
||||
}
|
||||
return super.onContextItemSelected(item)
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (requestCode == WRITE_REQUEST_CODE && resultCode == Activity.RESULT_OK) runCatching {
|
||||
data?.data?.let {
|
||||
contentResolver?.openOutputStream(it)?.apply { write(loggerContents.toByteArray()) }?.close()
|
||||
toast(LocaleString.exportAllLogsSuccess)
|
||||
} ?: toast(LocaleString.exportAllLogsFail)
|
||||
}.onFailure { toast(LocaleString.exportAllLogsFail) }
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
/** 执行更新 */
|
||||
refreshData()
|
||||
}
|
||||
}
|
@@ -32,6 +32,7 @@ import com.fankes.apperrorstracking.data.ConfigData.bind
|
||||
import com.fankes.apperrorstracking.databinding.ActivityMainBinding
|
||||
import com.fankes.apperrorstracking.locale.LocaleString
|
||||
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.*
|
||||
@@ -78,6 +79,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
/** 功能管理按钮点击事件 */
|
||||
binding.viewErrorsRecordButton.setOnClickListener { whenActivated { navigate<AppErrorsRecordActivity>() } }
|
||||
binding.viewMutedErrorsAppsButton.setOnClickListener { whenActivated { navigate<AppErrorsMutedActivity>() } }
|
||||
/** 调试日志按钮点击事件 */
|
||||
binding.titleLoggerIcon.setOnClickListener { navigate<LoggerActivity>() }
|
||||
/** 重启按钮点击事件 */
|
||||
binding.titleRestartIcon.setOnClickListener { FrameworkTool.restartSystem(context = this) }
|
||||
/** 项目地址按钮点击事件 */
|
||||
|
@@ -43,7 +43,7 @@ import com.highcapable.yukihookapi.hook.xposed.channel.data.ChannelData
|
||||
object FrameworkTool {
|
||||
|
||||
/** 系统框架包名 */
|
||||
private const val SYSTEM_FRAMEWORK_NAME = "android"
|
||||
const val SYSTEM_FRAMEWORK_NAME = "android"
|
||||
|
||||
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"
|
||||
|
8
app/src/main/res/drawable/bg_logger_d_round.xml
Normal file
8
app/src/main/res/drawable/bg_logger_d_round.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#565656" />
|
||||
<corners
|
||||
android:bottomLeftRadius="10dp"
|
||||
android:topLeftRadius="10dp" />
|
||||
</shape>
|
8
app/src/main/res/drawable/bg_logger_e_round.xml
Normal file
8
app/src/main/res/drawable/bg_logger_e_round.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#E53935" />
|
||||
<corners
|
||||
android:bottomLeftRadius="10dp"
|
||||
android:topLeftRadius="10dp" />
|
||||
</shape>
|
8
app/src/main/res/drawable/bg_logger_i_round.xml
Normal file
8
app/src/main/res/drawable/bg_logger_i_round.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#3974CB" />
|
||||
<corners
|
||||
android:bottomLeftRadius="10dp"
|
||||
android:topLeftRadius="10dp" />
|
||||
</shape>
|
8
app/src/main/res/drawable/bg_logger_w_round.xml
Normal file
8
app/src/main/res/drawable/bg_logger_w_round.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#FB8C00" />
|
||||
<corners
|
||||
android:bottomLeftRadius="10dp"
|
||||
android:topLeftRadius="10dp" />
|
||||
</shape>
|
9
app/src/main/res/drawable/ic_refresh.xml
Normal file
9
app/src/main/res/drawable/ic_refresh.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="150dp"
|
||||
android:height="150dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:pathData="M712.9,295.1c-120.7,-110.7 -308.3,-102.6 -419,18.1 -87.4,95.3 -103,236.3 -38.5,348.4 82,141.7 263.2,190.3 405,108.4 66.8,-38.6 116,-101.7 137,-176 8.9,-31.5 41.7,-49.8 73.2,-40.9 31.5,8.9 49.8,41.7 40.9,73.2C849.1,846.8 619.8,975 399.2,912.6 178.7,850.2 50.5,620.9 112.9,400.3S404.6,51.6 625.2,114c64.2,18.2 123.1,51.5 171.6,97.3l79.7,-79.7c11.6,-11.6 30.3,-11.6 41.9,-0.1 5.6,5.6 8.7,13.1 8.7,21V407c0,16.4 -13.3,29.6 -29.6,29.6H642.9c-16.4,0 -29.6,-13.3 -29.6,-29.7 0,-7.8 3.1,-15.3 8.6,-20.9l91,-90.9z"
|
||||
android:fillColor="#ffffff"/>
|
||||
</vector>
|
129
app/src/main/res/layout/activitiy_logger.xml
Normal file
129
app/src/main/res/layout/activitiy_logger.xml
Normal file
@@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/colorThemeBackground"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.activity.debug.LoggerActivity"
|
||||
tools:ignore="ContentDescription,UseCompoundDrawables">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center|start"
|
||||
android:paddingLeft="15dp"
|
||||
android:paddingTop="13dp"
|
||||
android:paddingRight="15dp"
|
||||
android:paddingBottom="5dp">
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/title_back_icon"
|
||||
style="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:src="@drawable/ic_back"
|
||||
android:tint="@color/colorTextGray"
|
||||
android:tooltipText="@string/back" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="2.5dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center|start"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/debug_log"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="19sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title_count_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:text="@string/this_contents_clear_when_restarts_tip"
|
||||
android:textColor="@color/colorTextDark"
|
||||
android:textSize="11.5sp"
|
||||
android:tooltipText="@string/this_contents_clear_when_restarts_tip" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:gravity="center|end"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/refresh_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:src="@drawable/ic_refresh"
|
||||
android:tint="@color/colorTextGray"
|
||||
android:tooltipText="@string/refresh" />
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/filter_icon"
|
||||
android:layout_width="22dp"
|
||||
android:layout_height="22dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:src="@drawable/ic_filter"
|
||||
android:tint="@color/colorTextGray"
|
||||
android:tooltipText="@string/filter_by_condition" />
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/export_all_icon"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/ic_export"
|
||||
android:tint="@color/colorTextGray"
|
||||
android:tooltipText="@string/export_all" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="10dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/list_no_data_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:lineSpacingExtra="6dp"
|
||||
android:text="@string/no_list_data"
|
||||
android:textColor="@color/colorTextDark"
|
||||
android:textSize="17sp" />
|
||||
|
||||
<ListView
|
||||
android:id="@+id/list_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:divider="@color/trans"
|
||||
android:dividerHeight="5dp"
|
||||
android:fadingEdgeLength="10dp"
|
||||
android:listSelector="@color/trans"
|
||||
android:paddingLeft="15dp"
|
||||
android:paddingRight="15dp"
|
||||
android:paddingBottom="5dp"
|
||||
android:requiresFadingEdge="vertical"
|
||||
android:scrollbars="none"
|
||||
android:visibility="gone" />
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
@@ -29,6 +29,18 @@
|
||||
android:textSize="25sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/title_logger_icon"
|
||||
style="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:alpha="0.85"
|
||||
android:padding="0.5dp"
|
||||
android:src="@drawable/ic_debug"
|
||||
android:tint="@color/colorTextGray"
|
||||
android:tooltipText="@string/debug_log" />
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/title_restart_icon"
|
||||
style="?android:attr/selectableItemBackgroundBorderless"
|
||||
|
53
app/src/main/res/layout/adapter_logger.xml
Normal file
53
app/src/main/res/layout/adapter_logger.xml
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/priority_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:padding="5dp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="13sp"
|
||||
android:typeface="monospace" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center|start"
|
||||
android:orientation="vertical"
|
||||
android:padding="10dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/message_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:lineSpacingExtra="3dp"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="13sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/time_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/colorTextDark"
|
||||
android:textSize="11sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/throwable_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:lineSpacingExtra="3dp"
|
||||
android:textColor="#EF5350"
|
||||
android:textSize="11sp"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
54
app/src/main/res/layout/dia_logger_filter.xml
Normal file
54
app/src/main/res/layout/dia_logger_filter.xml
Normal file
@@ -0,0 +1,54 @@
|
||||
<?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="10dp"
|
||||
android:lineSpacingExtra="6dp"
|
||||
android:text="@string/when_logger_how_to_show_tip"
|
||||
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="DEBUG"
|
||||
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="INFO"
|
||||
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="WARN"
|
||||
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="ERROR"
|
||||
app:buttonTint="@color/colorPrimaryAccent" />
|
||||
</LinearLayout>
|
6
app/src/main/res/menu/menu_logger_action.xml
Normal file
6
app/src/main/res/menu/menu_logger_action.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/logger_copy"
|
||||
android:title="@string/copy" />
|
||||
</menu>
|
Reference in New Issue
Block a user