在TextView中显示Android Logcat

13

我正在构建的应用程序拥有对Android的root访问权限。我希望在其中一个TextView中显示Logcat日志信息,以便在调试时能够在屏幕上显示出来。

有人可以给我一些想法,我可以调用哪个库/函数来访问这些日志呢?

谢谢


你想自己实现logcat查看功能而不使用开源应用alogcat的原因是什么? - k3b
3
主要原因是alogcat无法与应用程序并行运行。我遇到了一个问题,即应用程序完全使Android Shell无响应。因此,我想在我的应用程序上方实时叠加查看发生了什么。 - WorldWind
可能是Can logcat results for Log.i be viewed in our activity?的重复问题。 - Alex P.
3个回答

30

这里有一篇博客文章,它可以完美地满足您的需求。 它提供了一个完整的代码示例,展示如何显示Logcat日志的内容。以下是代码:

  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import android.app.Activity;
  import android.os.Bundle;
  import android.widget.TextView;

  class ReadLogDemo extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);

         try {
              Process process = Runtime.getRuntime().exec("logcat -d");
              BufferedReader bufferedReader = new BufferedReader(
                   new InputStreamReader(process.getInputStream()));

              StringBuilder log=new StringBuilder();
              String line = ""; 
              while ((line = bufferedReader.readLine()) != null) {
                   log.append(line);
              }   
              TextView tv = (TextView)findViewById(R.id.textView1);
              tv.setText(log.toString());
         } catch (IOException e) {
              // Handle Exception
         }
    }

  } 

仅澄清,这不是我的答案,这是原始的


3
谢谢您的提问。然而,我主要关注的问题之一是如何知道系统中是否出现了新的日志行可以显示? 我只需将它们放入无限循环中并定期检查它们吗? - WorldWind
1
这是一种方法,你可以添加一个OnClickListenear来加载新的Logcat流。你提到你的应用程序使Android Shell无响应。你是否使用TRY/CATCH语句?它们应该能够处理这个问题。你也可以通过USB电缆将手机连接到工作站,并使用Eclipse和从那里使用Logcat视图。 - Dawid Czerwinski
@SteveC。尝试这个:https://dev59.com/dG025IYBdhLWcg3wKSmP - Dawid Czerwinski
@DawidCzerwinski 在安卓中我该如何定义它,因为我不能使用引号? - Steve C.
@SteveC. 你试过使用单引号吗?或者其他在字符串中表示引号的方式?比如,在Python中,你可以在前面加上“\”这个符号来实现。例如:print "Hello "Steve""。我不记得在Android中怎么做了。 - Dawid Czerwinski
显示剩余4条评论

1

嗯,有一个解决方案可以使用this库将您想要记录的任何内容记录到屏幕上。但它对我没有用,所以我开发了自己的解决方案,您可以在这里找到一个示例。它非常简单,只需将OnScreenLog类添加到您的项目中即可。

package br.com.ideiageni.onscreenlogSample;

import android.app.Activity;
import android.graphics.Color;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;


/**
 * Created by ariel on 07/07/2016.
 */
    public class OnScreenLog {
    private static int timeoutTime = 1000;
    private static TextView tvLog;
    private static int logCount = 0;
    private static int logCountMax = 30;
    private static String[] logs = new String[logCountMax];
    private static int cntClicks = 0;
    private static boolean visibility = false;
    private static Activity activity;
    private int maxClicks = 5;

    public OnScreenLog(){}

    public OnScreenLog(Activity activity, int ViewID){
        OnScreenLog.activity = activity;
        tvLog = new TextView(activity.getApplicationContext());
        maintainLog("Log is working");
        tvLog.setLayoutParams(new RelativeLayout.LayoutParams(
            RelativeLayout.LayoutParams.WRAP_CONTENT,
            RelativeLayout.LayoutParams.WRAP_CONTENT));
        tvLog.setTextColor(Color.BLACK);
        tvLog.setBackgroundColor(Color.LTGRAY);
        tvLog.setAlpha((float) 0.4);

        View v = null;
        LinearLayout linearLayout;
        RelativeLayout relativeLayout;
        try {
            linearLayout = (LinearLayout) activity.findViewById(ViewID);
        } catch (ClassCastException e) {linearLayout = null;};

        try {
            relativeLayout = (RelativeLayout) activity.findViewById(ViewID);
        } catch (ClassCastException e) {relativeLayout = null;};
        if(linearLayout != null) {
            linearLayout.addView(tvLog);
            v = linearLayout;
        } else if(relativeLayout != null) {
            relativeLayout.addView(tvLog);
            v = relativeLayout;
        }

        if(v != null) {
            v.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                            cntClicks++;
                            timerHandler.removeCallbacks(rTimeout);
                            timerHandler.postDelayed(rTimeout, timeoutTime);

                            if (cntClicks > maxClicks-1) {
                                setLogVisible(!visibility);
                                timerHandler.removeCallbacks(rTimeout);
                                cntClicks = 0;
                            }
                            break;

                    }
                    return false;
                }
            });
        }

    }

    public void log (String text){
        String logText = text;
        maintainLog(logText);
    }

    public void log (int text){
        String logText = String.valueOf(text);
        maintainLog(logText);
    }

    public void log (int[] text){
        StringBuilder builder = new StringBuilder();
        for (int i : text) {
            builder.append(i);
            builder.append("-");
        }
        String logText = builder.toString();
        maintainLog(logText);
    }

    public void log (byte[] text){
        StringBuilder builder = new StringBuilder();
        for (int i : text) {
            builder.append(i);
            builder.append("-");
        }
        String logText = builder.toString();
        maintainLog(logText);
    }

    private void maintainLog(String newText){
        String logText = "";
        if(logCount<logCountMax) logCount++;
        for(int i=logCount-1; i>0; i--){
            logs[i] = logs[i-1];
        }
        logs[0] = newText;
        for(int i=0; i<logCount; i++){
            if(i<logCount-1) logText+=logs[i]+System.getProperty("line.separator");
            else logText+=logs[i];
        }
        tvLog.setText(logText);
    }

    public void clearLog(){
        tvLog.setText("");
    }

    public void setLogVisible(boolean visibility){
        if(visibility) tvLog.setVisibility(View.VISIBLE);
        else tvLog.setVisibility(View.INVISIBLE);
        OnScreenLog.visibility = visibility;
    }

    public static int getLogCountMax() {
        return logCountMax;
    }

    public static void setLogCountMax(int logCountMax) {
        OnScreenLog.logCountMax = logCountMax;
        logs = new String[logCountMax];
    }

    public int getMaxClicks() {
        return maxClicks;
    }

    public void setMaxClicks(int maxClicks) {
        this.maxClicks = maxClicks;
    }

    Handler timerHandler = new Handler();
    Runnable rTimeout = new Runnable() {

        @Override
        public void run() {
            cntClicks = 0;
        }
    };
}

那么,例如:

public class Activity1 extends AppCompatActivity {

private OnScreenLog log;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_1);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    log = new OnScreenLog(this, R.id.content_1);
    log.log("Started log on Activity 1");

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(getApplicationContext(), Activity2.class);
            startActivity(intent);
            log.log("Starting Activity 2");
            Snackbar.make(view, "Starting Activity 2", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });
}

其中R.id.content_1是您活动的主LinearLayout或RelativeLayout的名称。

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout 
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:id="@+id/content_1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="br.com.ideiageni.onscreenlogSample.Activity1"
tools:showIn="@layout/activity_1">

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Activity 1!" />

</RelativeLayout>

工作尚未完成,但可供需要的任何人使用。缺少一些关于如何使用的指导。欢迎提出建议。


0
如果你想要将上面的答案输出整理成特定主题,那么这里有一个解决方案:
**冒号可能无法正常工作,这取决于日志的格式**。
while ((line = bufferedReader.readLine()) != null) {
    CharSequence cs = "Mqtt:";  //topic string (the colon helps cut out false positives)
    if (line.contains(cs)) {
        log.append(line.substring(line.indexOf("Mqtt:"),line.length())); // Cuts out the junk at the beginning of the log
        log.append("\n"); // makes log print line by line like normal
    }
}

感谢 @Dawid 提供了一个好答案的链接!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接