<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          被Bug搞瘋了?給你的應(yīng)用嵌入一個(gè)Logcat吧

          共 8913字,需瀏覽 18分鐘

           ·

          2021-03-11 02:54

          作者:椎鋒陷陳

          https://www.jianshu.com/u/9bfd80e684ad

          前言

          利用日志埋點(diǎn),以排查由于邏輯出錯(cuò)而引發(fā)的Bug,是我們常用的排障手段。(什么?你還在通過Debug斷點(diǎn)調(diào)試?),但在生產(chǎn)環(huán)境下出于安全性考慮,往往Release包需要將日志輸出到屏幕的功能關(guān)閉。

          于是常會(huì)出現(xiàn)一種很尷尬的場(chǎng)景,你需要用電腦重新在手機(jī)上打一個(gè)Debug包覆蓋才能重新看到日志輸出,而如果恰巧事故發(fā)生在周末,你手上只有一臺(tái)手機(jī),一個(gè)APP,你該如何快速定位問題呢?

          你是否會(huì)想,要是在手機(jī)上能有一個(gè)Logcat就好了,發(fā)生故障時(shí)立馬就能快速定位問題,而這,正是本文想與你分享的。

          偷偷先瞄一眼效果:


          等不及要立即使用了?我已將該庫上傳到遠(yuǎn)程倉庫了,可以通過以下方式引入。在項(xiàng)目級(jí)build.gradle添加:

          allprojects {
              repositories {
                  ...
                  maven{ url "https://dl.bintray.com/madchan/maven" }
              }
          }

          以及在模塊級(jí)build.gradle添加:

          implementation 'com.madchan.library:embeddedlogcat:1.0.0'

          使用也很容易,以正常啟動(dòng)Activity的方式跳轉(zhuǎn)即可:

          startActivity(Intent(this, LogcatActivity::class.java))

          同時(shí)示例源碼也發(fā)布到GitHub了,如果對(duì)你有幫助,給點(diǎn)個(gè)Star_吧~

          項(xiàng)目地址:
          https://github.com/madchan/EmbeddedLogcat

          正文

          知識(shí)儲(chǔ)備

          Logcat窗口布局講解

          既然是要模仿Android Studio的Logcat功能,我們自然需要先分析Logcat窗口的功能布局,并評(píng)判哪一些功能是我們需要抄襲(參考)的,如圖:


          先從頂部欄開始分析,從左到右依次為: 

          設(shè)備:默認(rèn)情況下,Logcat 僅顯示在指定設(shè)備上運(yùn)行的應(yīng)用的日志消息。

          進(jìn)程:通常情況下,我們只關(guān)心自身應(yīng)用進(jìn)程的日志消息,但需考慮到應(yīng)用可能存在多進(jìn)程的情況。

          日志級(jí)別:通常情況下,我們通過設(shè)置日志級(jí)別來表示對(duì)不同信息的關(guān)心程度。 

          具體的級(jí)別分布如下:


          • Verbose:顯示所有日志消息(默認(rèn)值)。
          • Debug:顯示僅在開發(fā)期間有用的調(diào)試日志消息,以及此列表中較低的消息級(jí)別。
          • Info:顯示常規(guī)使用情況的預(yù)期日志消息,以及此列表中較低的消息級(jí)別。 
          • Warn:顯示尚不是錯(cuò)誤的潛在問題,以及此列表中較低的消息級(jí)別。
          • Error:顯示已經(jīng)引發(fā)錯(cuò)誤的問題,以及此列表中較低的消息級(jí)別。
          • Assert:顯示開發(fā)者預(yù)計(jì)絕不會(huì)發(fā)生的問題。



          搜索字段:搜索包含特定字段的日志,支持正則表達(dá)式。

          過濾器:過濾器菜單中,包含以下三個(gè)過濾選項(xiàng):


          • Show only selected application:僅顯示通過應(yīng)用代碼生成的消息(默認(rèn)選項(xiàng))。Logcat 使用正在運(yùn)行的應(yīng)用的 PID 來過濾日志消息。
          • No Filters:不應(yīng)用過濾器。無論您選擇哪個(gè)進(jìn)程,logcat 都會(huì)顯示設(shè)備中的所有日志消息。
          • Edit Filter Configuration:創(chuàng)建或修改自定義過濾器。例如,您可以創(chuàng)建一個(gè)過濾器,以同時(shí)查看兩個(gè)應(yīng)用中的日志消息。



          再從左側(cè)繼續(xù)分析,從上到下。。。我們只挑幾個(gè)常用的講吧:

          清除日志:通常是為了排除之前的日志消息的干擾。需加入。
          滾動(dòng)到底部:可以跳轉(zhuǎn)到日志底部并查看最新的日志消息。需加入。 

          Logcat 命令行工具

          可通過adb shell運(yùn)行Logcat命令行,該命令行用于轉(zhuǎn)儲(chǔ)系統(tǒng)消息日志,包括設(shè)備拋出錯(cuò)誤時(shí)的堆棧軌跡,以及應(yīng)用使用Log類寫入的消息。

          Logcat包含了許多命令行選項(xiàng),用以查看不同過濾條件下的日志輸出,如需獲取 logcat 在線幫助,可執(zhí)行以下命令,此處不具體展開:

          adb logcat --help

          方案實(shí)現(xiàn)

          聰明的同學(xué)可能已經(jīng)猜到,Logcat命令行工具即是我們實(shí)現(xiàn)本主題的主要途徑,而Logcat窗口布局控件的選擇結(jié)果則是為命令行添加不同的過濾選項(xiàng),下面我們來逐步實(shí)現(xiàn)。

          首先,定義一個(gè)Command數(shù)據(jù)類,每一個(gè)過濾選項(xiàng)都作為該類的屬性之一,toString方法負(fù)責(zé)將該類轉(zhuǎn)換為一個(gè)完整的命令行。

          data class Command(var level: String = " *:V") {    // 級(jí)別

              var pid: Int? = 0        // 進(jìn)程ID
              var expr: String? = null    // 關(guān)鍵詞

              override fun toString(): String {
                  val builder = StringBuilder("logcat -d -v time $level")

                  pid?.let {
                      builder.append(" --pid=$pid")
                  }

                  if (!TextUtils.isEmpty(expr)) {
                      builder.append(" -e $expr+")
                  }

                  return builder.toString()
              }
          }

          -d選項(xiàng)

          接著,介紹一個(gè)最基本的命令行,此命令行將日志轉(zhuǎn)儲(chǔ)到屏幕并退出 :

          adb logcat -d

          我們?cè)趫?zhí)行完該命令行后,逐行讀取日志信息并輸出到TextView:

          // LogcatExecutor.kt
          ...
          private fun execOutputCommand(command: Command?) {
              try {
                  val command = command?.toString() ?: "logcat -d"
                  val process = Runtime.getRuntime().exec(command)
                  val bufferedReader = BufferedReader(InputStreamReader(process.inputStream))

                  val log = StringBuilder()
                  var line: String? = bufferedReader.readLine()
                  while (line != null) {
                      log.append(line)
                      log.append("\n\n")

                      line = bufferedReader.readLine()
                  }

                  callback?.onLogOutput(log.toString())

              } catch (e: IOException) {
                  Log.e("LogcatHandler""執(zhí)行Logcat命令行失?。? + e.message)
              }

          }
          ...

          --pid=<pid>選項(xiàng)

          此命令行僅輸出來自給定 PID 的日志。由進(jìn)程Spinner選中指定選項(xiàng)后,為Command類的pid屬性賦值,并重新執(zhí)行此命令行輸出日志:

          // LogcatActivity.kt
          ...
          private lateinit var process: Spinner
          ...
          process.onItemSelectedListener = object : OnItemSelectedListener {
              override fun onItemSelected(
                  adapterView: AdapterView<*>?,
                  view: View,
                  position: Int,
                  l: Long
              )
           {
                  command.pid = processMap[(process.adapter.getItem(position) as String)]
                  startOutput()
              }

              override fun onNothingSelected(adapterView: AdapterView<*>?) {}
          }
          ...

          *:S選項(xiàng)

          此命令行用于指示最低優(yōu)先級(jí),不低于指定優(yōu)先級(jí)的標(biāo)記的消息會(huì)寫入日志。與上面步驟相似,只不過賦值的是level屬性。

          // LogcatActivity.kt
          ...
          private lateinit var level: Spinner
          ...
          level.onItemSelectedListener = object : OnItemSelectedListener {
              override fun onItemSelected(
                  adapterView: AdapterView<*>?,
                  view: View,
                  i: Int,
                  l: Long
              )
           {
                  when (i) {
                      0 -> command.level = "*:V"
                      1 -> command.level = "*:D"
                      2 -> command.level = "*:I"
                      3 -> command.level = "*:W"
                      4 -> command.level = "*:E"
                      else -> {
                      }
                  }
                  startOutput()
              }

              override fun onNothingSelected(adapterView: AdapterView<*>?) {}
          }
          ...

          -e <expr>選項(xiàng)

          此命令行只輸出日志消息與 <expr> 匹配的行,其中 <expr> 是正則表達(dá)式。

          // LogcatActivity.kt
          ...
          private lateinit var search: EditText
          ...
          search.addTextChangedListener (object : TextWatcher{

              override fun afterTextChanged(s: Editable?) {
                  command.expr = s.toString().trim()
                  startOutput()
              }

              override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

              override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}

          })
          ...

          其他的如清除日志、滾動(dòng)到底部、高亮ERROR級(jí)別日志是屬于交互的優(yōu)化,不在本文介紹的范圍之內(nèi),感興趣的可以閱讀源碼。

          使用場(chǎng)景

          可以參考我之前寫的文章《Preference庫:為你的應(yīng)用快速搭建一個(gè)「開發(fā)者選項(xiàng)」》,為你的應(yīng)用添加調(diào)試入口,并增加「進(jìn)入日志調(diào)試頁」的調(diào)試選項(xiàng)。

          文章地址鏈接如下所示:


          https://www.jianshu.com/p/6ae1794d8fca

          總結(jié)

          本文以Android Studio的Logcat功能為參考模板,使用Logcat 命令行工具搭配合適的交互控件,在應(yīng)用內(nèi)搭建了一個(gè)類似的功能,可幫助開發(fā)者根據(jù)日志信息快速定位問題,快跟我來一起使用吧!


          ·················END·················

          推薦閱讀

          ? 耗時(shí)2年,Android進(jìn)階三部曲第三部《Android進(jìn)階指北》出版!

          ? 『BATcoder』做了多年安卓還沒編譯過源碼?一個(gè)視頻帶你玩轉(zhuǎn)!

          ? 『BATcoder』是時(shí)候下載Android11系統(tǒng)源碼和內(nèi)核源碼了!

          推薦我的技術(shù)博客

          推薦一下我的獨(dú)立博客: liuwangshu.cn ,內(nèi)含Android最強(qiáng)原創(chuàng)知識(shí)體系,一直在更新,歡迎體驗(yàn)和收藏!

          BATcoder技術(shù)群,讓一部分人先進(jìn)大廠

          你好,我是劉望舒,百度百科收錄的騰訊云TVP專家,著有三本技術(shù)暢銷書,蟬聯(lián)四屆電子工業(yè)出版社年度優(yōu)秀作者,谷歌開發(fā)者社區(qū)特邀講師。


          前華為面試官,現(xiàn)大廠技術(shù)負(fù)責(zé)人。


          歡迎添加我的微信 henglimogan ,備注:BATcoder,加入BATcoder技術(shù)群。



          明天見(??ω??)

          瀏覽 52
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久久精品一区二区三区 | 最新国产亚洲免费在线视频 | 久爱视频在线观看 | 厂里宿舍少妇愉情视频 | 伊人在线大香蕉视频 |