Skip to content

Commit ac91ce6

Browse files
committed
Live logcat
1 parent cdbe367 commit ac91ce6

3 files changed

Lines changed: 49 additions & 21 deletions

File tree

LogcatCoreLib/src/main/java/info/hannes/logcat/LogcatFragment.kt

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,40 @@ package info.hannes.logcat
33
import android.annotation.SuppressLint
44
import android.os.Bundle
55
import android.util.Log
6+
import android.view.LayoutInflater
7+
import android.view.View
8+
import android.view.ViewGroup
69
import info.hannes.logcat.base.LogBaseFragment
710
import java.io.IOException
811
import java.util.*
912

1013

1114
class LogcatFragment : LogBaseFragment() {
1215

16+
private val logList = ArrayList<String>()
17+
18+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
19+
live = true
20+
return super.onCreateView(inflater, container, savedInstanceState)
21+
}
22+
1323
@SuppressLint("LogNotTimber")
1424
override fun readLogFile(): ArrayList<String> {
15-
val logList = ArrayList<String>()
1625
try {
1726
val process = Runtime.getRuntime().exec("logcat -dv time")
1827

19-
logList.addAll(
20-
process.inputStream.bufferedReader().use {
21-
it.readLines().map { line ->
22-
line.replace(" W/", " W: ")
23-
.replace(" E/", " E: ")
24-
.replace(" V/", " V: ")
25-
.replace(" I/", " I: ")
26-
.replace(" D/", " D: ")
27-
}
28-
}
29-
)
28+
process.inputStream.bufferedReader().use {
29+
it.readLines().map { line ->
30+
val newLine = line.replace(" W/", " W: ")
31+
.replace(" E/", " E: ")
32+
.replace(" V/", " V: ")
33+
.replace(" I/", " I: ")
34+
.replace(" D/", " D: ")
35+
36+
if (!logList.contains(newLine))
37+
logList.add(newLine)
38+
}
39+
}
3040

3141
} catch (e: IOException) {
3242
Log.e("LoadingLogcatTask", e.message!!)

LogcatCoreLib/src/main/java/info/hannes/logcat/base/LogBaseFragment.kt

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import android.content.Context
66
import android.content.Intent
77
import android.net.Uri
88
import android.os.Bundle
9+
import android.os.Handler
10+
import android.os.Looper
911
import android.os.StrictMode
1012
import android.view.*
1113
import androidx.appcompat.widget.SearchView
@@ -33,6 +35,7 @@ abstract class LogBaseFragment : Fragment() {
3335

3436
private var filename: String? = null
3537
private var searchHint: String? = null
38+
protected var live: Boolean = false
3639

3740
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
3841
super.onCreateView(inflater, container, savedInstanceState)
@@ -43,7 +46,10 @@ abstract class LogBaseFragment : Fragment() {
4346
logsRecycler = view.findViewById(R.id.log_recycler)
4447
logsRecycler.layoutManager = layoutManager
4548
// empty adapter to avoid "E/RecyclerView﹕ No adapter attached; skipping layou..."
46-
logsRecycler.adapter = LogListAdapter(mutableListOf(), currentFilter)
49+
logListAdapter = LogListAdapter(mutableListOf(), currentFilter)
50+
logsRecycler.adapter = logListAdapter
51+
52+
setFilter2LogAdapter("")
4753

4854
activity!!.actionBar?.setDisplayHomeAsUpEnabled(true)
4955
if (savedInstanceState == null) {
@@ -63,13 +69,19 @@ abstract class LogBaseFragment : Fragment() {
6369
return view
6470
}
6571

66-
private fun showLogContent() = lifecycle.coroutineScope.launch(Dispatchers.Main) {
67-
val logEntries = withContext(Dispatchers.Default) {
68-
readLogFile()
72+
private fun showLogContent() {
73+
lifecycle.coroutineScope.launch(Dispatchers.Main) {
74+
val logEntries = withContext(Dispatchers.Default) {
75+
readLogFile()
76+
}
77+
logListAdapter?.setItems(logEntries)
78+
logsRecycler.adapter = logListAdapter
79+
logsRecycler.adapter?.itemCount?.minus(1)?.let { logsRecycler.scrollToPosition(it) }
80+
81+
if (live) {
82+
Handler(Looper.getMainLooper()).postDelayed({ showLogContent() }, 1000)
83+
}
6984
}
70-
logListAdapter = LogListAdapter(logEntries, currentFilter)
71-
logsRecycler.adapter = logListAdapter
72-
logsRecycler.adapter?.itemCount?.minus(1)?.let { logsRecycler.scrollToPosition(it) }
7385
}
7486

7587
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {

LogcatCoreLib/src/main/java/info/hannes/logcat/base/LogListAdapter.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import androidx.recyclerview.widget.RecyclerView
1212
import info.hannes.logcat.R
1313
import java.util.*
1414

15-
class LogListAdapter(private val completeLogs: MutableList<String>, filter: String) : RecyclerView.Adapter<LogListAdapter.LogViewHolder>() {
15+
class LogListAdapter(private var completeLogs: MutableList<String>, filter: String) : RecyclerView.Adapter<LogListAdapter.LogViewHolder>() {
1616

1717
private var currentFilter: Array<out String>? = null
1818
var filterLogs: List<String> = ArrayList()
@@ -21,9 +21,15 @@ class LogListAdapter(private val completeLogs: MutableList<String>, filter: Stri
2121
setFilter(filter)
2222
}
2323

24+
fun setItems(newItems: MutableList<String>) {
25+
completeLogs = newItems
26+
setFilter(currentFilter!![0])
27+
notifyDataSetChanged()
28+
}
29+
2430
fun setFilter(vararg filters: String) {
2531
currentFilter = filters
26-
filterLogs = completeLogs.filter { line ->
32+
filterLogs = Collections.synchronizedList(completeLogs).filter { line ->
2733
var include = false
2834
for (filter in filters)
2935
if (filter.length == 3 && filter.takeLast(2) == ": ") { // eg 'E: '

0 commit comments

Comments
 (0)