Added ability to save and view logs

This commit is contained in:
tonlirise 2022-08-04 12:10:02 +07:00
parent b2b9caa4d3
commit e14273642d
10 changed files with 309 additions and 2 deletions

View File

@ -2,6 +2,7 @@ apply from: "../android-configs/lib-config.gradle"
dependencies {
implementation "androidx.recyclerview:recyclerview"
implementation "androidx.coordinatorlayout:coordinatorlayout"
implementation "androidx.fragment:fragment-ktx"
implementation project(path: ':logging')
@ -12,6 +13,12 @@ dependencies {
}
}
implementation("androidx.coordinatorlayout:coordinatorlayout") {
version {
require '1.1.0'
}
}
implementation("androidx.fragment:fragment-ktx") {
version {
require '1.2.1'

View File

@ -2,9 +2,11 @@ apply from: "../android-configs/lib-config.gradle"
dependencies {
implementation "androidx.annotation:annotation"
implementation "com.google.firebase:firebase-crashlytics"
implementation "androidx.recyclerview:recyclerview"
implementation "androidx.constraintlayout:constraintlayout"
constraints {
implementation("androidx.annotation:annotation") {
version {
@ -17,5 +19,17 @@ dependencies {
require '17.1.0'
}
}
implementation("androidx.recyclerview:recyclerview") {
version {
require '1.1.0'
}
}
implementation("androidx.constraintlayout:constraintlayout"){
version {
require '2.2.0-alpha03'
}
}
}
}

View File

@ -1 +1,15 @@
<manifest package="ru.touchin.roboswag.core.log" />
<manifest
package="ru.touchin.roboswag.core.log"
xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="ru.touchin.roboswag.core.log.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
</application>
</manifest>

View File

@ -0,0 +1,84 @@
package ru.touchin.roboswag.core.log_file
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import androidx.core.content.FileProvider
import androidx.fragment.app.DialogFragment
import androidx.recyclerview.widget.LinearLayoutManager
import ru.touchin.roboswag.core.log.BuildConfig
import ru.touchin.roboswag.core.log.R
import ru.touchin.roboswag.core.log.databinding.DialogFragmentDebugLogsBinding
import ru.touchin.roboswag.core.log_file.LogFileManager.Companion.getLogDirectory
import java.io.File
class DebugLogsDialogFragment : DialogFragment() {
private val logItemsList: MutableList<String> = mutableListOf()
private lateinit var binding: DialogFragmentDebugLogsBinding
override fun getTheme(): Int = R.style.DialogFullscreenTheme
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = DialogFragmentDebugLogsBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initSpinner()
binding.logsRecycler.layoutManager = LinearLayoutManager(requireContext())
binding.logsRecycler.adapter = LogItemAdapter(requireContext(), logItemsList)
binding.shareBtn.setOnClickListener {
val files = getLogDirectory(requireContext()).listFiles()
if (!files.isNullOrEmpty()) {
val uri = FileProvider.getUriForFile(
requireContext(),
BuildConfig.LIBRARY_PACKAGE_NAME + LogFileManager.fileProviderName,
files.first()
)
val intent = Intent(Intent.ACTION_SEND)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.setType("*/*")
intent.putExtra(Intent.EXTRA_STREAM, uri)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent)
}
}
}
private fun initSpinner() {
val priorityTitle = LogFileManager.Priority.values().map { it.title }
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, priorityTitle)
adapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line)
binding.priorityFilter.adapter = adapter;
binding.priorityFilter.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
val priority = LogFileManager.Priority.values()[position]
LogFileManager.saveLogcatToFile(requireContext(), priority.tag)
}
override fun onNothingSelected(parent: AdapterView<*>) {}
}
binding.updateBtn.setOnClickListener { updateRecycler() }
}
private fun updateRecycler() {
logItemsList.clear()
val files = getLogDirectory(requireContext()).listFiles()
if (!files.isNullOrEmpty()) {
File(files.firstOrNull()?.getAbsolutePath() ?: "")
.useLines { lines -> lines.forEach { logItemsList.add(it) } }
}
binding.logsRecycler.adapter?.notifyDataSetChanged()
}
}

View File

@ -0,0 +1,60 @@
package ru.touchin.roboswag.core.log_file
import android.content.Context
import java.io.File
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
class LogFileManager {
enum class Priority(val title: String, val tag: String) {
VERBOSE("VERBOSE", "*:V"),
DEBUG("DEBUG", "*:D"),
INFO("INFO", "*:I"),
WARNING("WARNING", "*:W"),
ERROR("ERROR", "*:E"),
ASSERT("ASSERT", "*:A")
}
companion object {
private const val logDirecroryName = "log"
const val fileProviderName = ".fileprovider"
fun getLogDirectory(context: Context) : File{
val appDirectory = context.getExternalFilesDir(null)
return File(appDirectory.toString() + "/$logDirecroryName")
}
fun saveLogcatToFile(context: Context, priorityTag: String) {
val logDirectory = initLogDirectory(context)
val sdf = SimpleDateFormat("yyyy-MM-dd'T'HH_mm_ss_SSS", Locale.getDefault())
val logFile = File(logDirectory, "logcat_${sdf.format(Date())}.txt")
try {
Runtime.getRuntime().exec("logcat ${priorityTag} -f $logFile")
} catch (e: IOException) {
e.printStackTrace()
}
}
private fun initLogDirectory(context: Context): File {
val appDirectory = context.getExternalFilesDir(null)
if (!appDirectory!!.exists()) {
appDirectory.mkdir()
}
val logDirectory = File(appDirectory.toString() + "/$logDirecroryName")
if (!logDirectory.exists()) {
logDirectory.mkdir()
}
for (file in logDirectory.listFiles()) {
file.delete()
}
return logDirectory
}
}
}

View File

@ -0,0 +1,35 @@
package ru.touchin.roboswag.core.log_file
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import ru.touchin.roboswag.core.log.databinding.LogItemBinding
class LogItemAdapter(private val context: Context, private val logItemList:MutableList<String>)
: RecyclerView.Adapter<LogItemAdapter.LogItemViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LogItemViewHolder {
val binding = LogItemBinding.inflate(LayoutInflater.from(context),parent,false)
return LogItemViewHolder(binding)
}
override fun onBindViewHolder(holder: LogItemViewHolder, position: Int) {
val foodItem = logItemList[position]
holder.bind(foodItem)
}
override fun getItemCount(): Int {
return logItemList.size
}
class LogItemViewHolder(logItemLayoutBinding: LogItemBinding)
: RecyclerView.ViewHolder(logItemLayoutBinding.root){
private val binding = logItemLayoutBinding
fun bind(logItem: String){
binding.logDescription.text = logItem
}
}
}

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="10dp"
android:paddingVertical="10dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<Spinner
android:id="@+id/priority_filter"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/update_btn"/>
<Button
android:id = "@+id/update_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="update"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/logs_recycler"
app:layout_constraintEnd_toEndOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/logs_recycler"
android:layout_width="0dp"
android:layout_height="0dp"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbars="vertical"
android:layout_marginBottom="20dp"
app:layout_constraintTop_toBottomOf="@id/priority_filter"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:listitem="@layout/log_item"
tools:visibility="visible" />
<Button
android:id = "@+id/share_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="share"
app:layout_constraintTop_toBottomOf="@id/logs_recycler"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,28 @@
<?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="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="10dp">
<TextView
android:id="@+id/log_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:fontFamily="sans-serif"
android:textIsSelectable="false"
android:maxLines="30"
android:textSize="17sp"
tools:maxLines="5"
tools:text="@tools:sample/lorem/random" />
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginBottom="1dp"
android:background="@android:color/black" />
</LinearLayout>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="DialogFullscreenTheme">
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">false</item>
<item name="android:windowIsFloating">false</item>
</style>
</resources>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external_files"
path="." />
</paths>