我昨天安装了Android Studio,我试着用LogCat查看日志。但是日志里什么都没有。我使用终端运行。/adb logcat,它工作。

有人能给我解释一下如何在Android Studio中使用logcat吗?


当前回答

Easy fix that worked for me (after trying some of these other suggestion). My logcat was sitting blank in a separate window (on my second screen). Just had to drag the Logcat tab back to it's original place in the debug panel next to the Debugger and Console tabs, and VOILA... it began immediately updating and showing all processes verbose. So (If your logcat is anywhere outside of the debugger panel (i.e. the logcat tab isn't sitting nested alongside the debugger and console tab) then it won't receive updates and will sit there blankly. Don't know if this is an issue with older versions of Android Studio. But again, easy to try and if it works... it works!!

其他回答

在我的情况下,我只是过滤了输出,所以即使在重新启动Logcat等后,它也显示为空。

在我的例子中,在开发人员选项菜单中有一个名为

撤销USB调试授权。

一旦你撤销所有现有的授权,它会再次要求信任你正在使用的计算机,之后它开始再次显示日志。

当其他方法都不管用的时候,我是这么做的。由于adb logcat工作得很好,我决定依赖它。在Android Studio的嵌入式终端中运行adb logcat -v color,输出与普通的logcat类似,并且允许代码链接工作:

但这也带来了一些问题:

您不能指定要监视的包。使用——pid=<your pid >选项,您可以查看单个进程的输出。但由于每次重新启动应用程序,PID都会发生变化,因此每次重新启动时都要重新运行此命令。 (在我看来)这些颜色令人讨厌。 输出字段没有与之前的消息对齐,整个事情没有很好地格式化,这使得跟踪logcat比它应该发生的要困难得多(尽管嵌入的logcat也发生了同样的情况)。

所以我决定制作自己的工具来自动监视我的包PID并美化logcat输出:

import java.awt.AWTException;
import java.io.*;
import java.util.ArrayList;
import java.awt.Robot;
import java.awt.event.KeyEvent;

public class Logcat {

    private static final String ADB_FILE_PATH = "adb";

    // Customizations,
    private static final Color     V_COLOR = Color.RESET;
    private static final Color     D_COLOR = Color.RESET;
    private static final Color     I_COLOR = Color.RESET;
    private static final Color     W_COLOR = Color.BLUE;
    private static final Color     E_COLOR = Color.RED_BRIGHT;
    private static final Color  HINT_COLOR = Color.MAGENTA_BOLD_BRIGHT;
    private static final Color OTHER_COLOR = Color.GREEN_BOLD_BRIGHT;

    private static final int       DATE_LENGTH =   5;
    private static final int       TIME_LENGTH =  12;
    private static final int PROCESS_ID_LENGTH =   5;
    private static final int  THREAD_ID_LENGTH =   5;
    private static final int  LOG_LEVEL_LENGTH =   1;
    private static final int        TAG_LENGTH =  20;
    private static final int    MESSAGE_LENGTH = 110;

    private static final String SEPARATOR = " | ";
    private static final String CONTINUATION = "→";
    private static final String INDENTATION = "  ";

    private static final int PROCESS_IDS_UPDATE_INTERVAL_MILLIS = 1224;

    private static final int HISTORY_LENGTH = 1000;

    // State,
    private static boolean skipProcessIDCheck;
    private static ArrayList<String> processIDs = new ArrayList<String>();

    private static String logLevelToShow="V";  // All.

    private static Process logcatProcess;
    private static boolean appClosed;
    private static boolean stopEverything;

    private static String[] history = new String[HISTORY_LENGTH];
    private static int currentLocationInHistory, historyLength;

    public static void main(final String args[]) {

        clearAndroidStudioConsole();
        System.out.println("besm Allah");

        // Get processes ids of the provided package,
        if (args.length==0) {
            skipProcessIDCheck = true;
        } else {
            skipProcessIDCheck = false;
            getProcessIDs    (args[0]);    // Do it once before we start.
            monitorProcessIDs(args[0]);    // Do it periodically from now on.
        }

        // Start capturing and prettifying logcat,
        if (!monitorLogcat()) {
            stopEverything = true;
            return;
        }

        // Handle user input,
        handleUserInput();
    }

    private static void watch(final Process process, final ProcessListener listener) {

        // Read process standard output and send it to the listener line by line,
        new Thread() {
            public void run() {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                String line = "";
                try {
                    do {
                        if (bufferedReader.ready()) {
                            line = bufferedReader.readLine();
                            if (line!=null && !line.isEmpty()) listener.onNewLine(line);
                        } else {
                            Thread.sleep(100);
                        }
                    } while (line!=null && !stopEverything);
                } catch (Exception e) { e.printStackTrace(); }
            }
        }.start();
    }

    private static void monitorProcessIDs(String packageName) {

        // Continuously monitor the process IDs of this package and update when changed,
        new Thread() {
            public void run() {
                do {
                    try { Thread.sleep(PROCESS_IDS_UPDATE_INTERVAL_MILLIS); } catch (InterruptedException e) {}
                    getProcessIDs(packageName);
                } while (!stopEverything);
            }
        }.start();
    }

    private static void getProcessIDs(String packageName) {

        // Get the process IDs associated with this package once,
        ArrayList<String> newProcessIDs = new ArrayList<String>();
        Runtime runtime = Runtime.getRuntime();
        try {
            Process getPIDProcess = runtime.exec(ADB_FILE_PATH + " shell ps");
            watch(getPIDProcess, (line) -> {
                if (line.contains(packageName)) {
                    newProcessIDs.add(removeRedundantSpaces(line).split(" ")[1]);
                }
            });
            getPIDProcess.waitFor();
            Thread.sleep(500);  // Make sure we've already handled all the input from the process.
        } catch (Exception e) { e.printStackTrace(); }

        // Return immediately if program is closed,
        if (stopEverything) return ;

        // Some action upon getting the pid(s),
        boolean shouldRepeatHistory = false;
        if (newProcessIDs.isEmpty()) {

            // Just closed,
            if (!appClosed) {
                appClosed = true;
                prettify("----- App closed -----");
            }
        } else if (appClosed) {

            // Just opened, clear,
            appClosed = false;
            clearAndroidStudioConsole();
            prettify("----- App opened -----");
            shouldRepeatHistory = true;
        } else {

            // Detect changes in processes,
            for (String pid : newProcessIDs) {
                if (!processIDs.contains(pid)) {
                    clearAndroidStudioConsole();
                    prettify("----- Process(es) changed (or app restarted - some logs could have been missed) -----");
                    shouldRepeatHistory = true;
                    break ;
                }
            }
        }

        // Set the new PID(s),
        processIDs = newProcessIDs;
        if (shouldRepeatHistory) repeatHistory();
    }

    private static boolean monitorLogcat() {

        Runtime runtime = Runtime.getRuntime();
        try {
            logcatProcess = runtime.exec(ADB_FILE_PATH + " logcat -v threadtime");
            watch(logcatProcess, (line) -> {

                // Learn history, in case we need to repeat it,
                if (appClosed || processLogcatLine(line)) {
                    history[currentLocationInHistory] = line;
                    currentLocationInHistory = (currentLocationInHistory + 1) % history.length;
                    if (historyLength<history.length) historyLength++;
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    private static boolean processLogcatLine(String line) {
        try {
            return prettify(line);
        } catch (Exception e) {
            print(line, OTHER_COLOR);
            System.out.println();

            // Debug,
            e.printStackTrace();
            return true;
        }
    }

    // Returns true if line should be kept in history,
    private static synchronized boolean prettify(String line) {

        if (line.startsWith("-")) {
            // It's a "beginning of <something>" line,
            print(line, HINT_COLOR);
            System.out.println();
            return true;
        }

        // Get the individual fields,
        String      date = line.substring(0, line.indexOf(' ')); line = line.substring(line.indexOf(' ')+1); line = line.trim();
        String      time = line.substring(0, line.indexOf(' ')); line = line.substring(line.indexOf(' ')+1); line = line.trim();
        String processID = line.substring(0, line.indexOf(' ')); line = line.substring(line.indexOf(' ')+1); line = line.trim();

        // Break early if possible,
        if (!skipProcessIDCheck && !processIDs.contains(processID.trim())) return false;

        // Continue parsing,
        String  threadID = line.substring(0, line.indexOf(' ')); line = line.substring(line.indexOf(' ')+1); line = line.trim();
        String  logLevel = line.substring(0, line.indexOf(' ')); line = line.substring(line.indexOf(' ')+1); line = line.trim();

        // Break early if possible,
        switch (logLevel) {
            case "V": if (!"V"    .contains(logLevelToShow)) return true; break;
            case "D": if (!"VD"   .contains(logLevelToShow)) return true; break;
            case "I": if (!"VDI"  .contains(logLevelToShow)) return true; break;
            case "W": if (!"VDIW" .contains(logLevelToShow)) return true; break;
            case "E": if (!"VDIWE".contains(logLevelToShow)) return true; break;
        }

        // Continue parsing,
        String       tag = line.substring(0, line.indexOf(':')); line = line.substring(line.indexOf(':')+1); line = line.trim();

        // Because some tags have a trailing ":",
        if (line.startsWith(":")) {
            tag += ":";
            line = line.substring(1);
        }

        // Indent lines starting by "at",
        String indentation = "";
        if (line.startsWith("at ")) {
            indentation = "   " + INDENTATION;
            line = " " + INDENTATION + line;
        }

        // Print the prettified log,
        Color color;
        switch (logLevel) {
            case "V": color = V_COLOR; break;
            case "D": color = D_COLOR; break;
            case "I": color = I_COLOR; break;
            case "W": color = W_COLOR; break;
            case "E": color = E_COLOR; break;
            default:
                color = Color.RESET;
        }

        String fields = adjustLength(     date,       DATE_LENGTH) + SEPARATOR +
                        adjustLength(     time,       TIME_LENGTH) + SEPARATOR +
                        adjustLength(processID, PROCESS_ID_LENGTH) + SEPARATOR +
                        adjustLength( threadID,  THREAD_ID_LENGTH) + SEPARATOR +
                        adjustLength( logLevel,  LOG_LEVEL_LENGTH) + SEPARATOR +
                        adjustLength(      tag,        TAG_LENGTH) + SEPARATOR;

        // Split the message onto multiple lines if needed,
        String message = chunkPreservingParentheses(line, MESSAGE_LENGTH, 2);
        print(fields + message, color);
        System.out.println();

        while (line.length() > message.length()) {

            // Debug,
            //print(line, OTHER_COLOR);
            //System.out.println("Line: " + line.length() + "length: " + message.length() + ", cont: " + CONTINUATION.length() + "dent: " + indentation.length());
            //System.out.println();

            // Remove the already printed part.
            line = line.substring(message.length()-CONTINUATION.length());

            // Add a dot to make links work,
            boolean shouldAddDot=false;
            if (line.matches("^[^\\.]*\\(.*:[123456789][1234567890]*\\).*")) shouldAddDot = true;

            // Indent,
            line = (shouldAddDot ? "." : (indentation.isEmpty() ? "" : " ")) + indentation + line;

            // Take another chunk,
            message = chunkPreservingParentheses(line, MESSAGE_LENGTH, 2+indentation.length());

            // Front pad to align this part with the message body,
            String paddedMessage = message;
            for (int i=0; i<fields.length(); i++) paddedMessage = ' ' + paddedMessage;

            // Print,
            print(paddedMessage, color);
            System.out.println();
        }

        return true;  // Keep in local buffer.
    }

    private static String adjustLength(String text, int length) {
        while (text.length() < length) text += ' ';
        if (text.length() > length) {
            text = text.substring(0, length-CONTINUATION.length());
            text += CONTINUATION;
        }
        return text;
    }

    private static String chunkPreservingParentheses(String text, int length, int minChunckLength) {

        if (text.length() <= length) return text;

        // Take a chunk out of the text,
        String chunk = text.substring(0, length-CONTINUATION.length()) + CONTINUATION;

        // Check if a paranthesis was opened and not closed,
        int lastOpenParanthesisIndex = chunk.lastIndexOf('(');
        int lastCloseParanthesisIndex = chunk.lastIndexOf(')');
        if (lastCloseParanthesisIndex <= lastOpenParanthesisIndex) {  // Also works when either is not found.
            if (minChunckLength<1) minChunckLength = 1;
            if (lastOpenParanthesisIndex > minChunckLength+CONTINUATION.length()) { // Avoid endless loops.
                int includeParenthesisSize = (CONTINUATION.length()>0) ? 1 : 0;
                chunk = text.substring(0, lastOpenParanthesisIndex+includeParenthesisSize-CONTINUATION.length()) + CONTINUATION;
            }
        }

        return chunk;
    }

    private static void repeatHistory() {
        int index = currentLocationInHistory-historyLength;
        if (index < 0) index += history.length;
        for (int i=0; i<historyLength; i++) {
            processLogcatLine(history[index]);
            index = (index + 1) % history.length;
        }
    }

    private static void print(String text, Color color) {
        System.out.print(color);
        System.out.print(text);
        System.out.print(Color.RESET);
    }

    private static String removeRedundantSpaces(String text) {
        String newText = text.replace("  ", " ");
        while (!text.equals(newText)) {
            text = newText;
            newText = text.replace("  ", " ");
        }
        return text;
    }

    private static void clearAndroidStudioConsole() {

        // Couldn't find a reliable way to clear Intellij terminal scrollback, so we just print
        // a LOT of newlines,
        StringBuilder bunchOfNewLines = new StringBuilder();
        for (int i=0; i<124; i++) bunchOfNewLines.append(System.lineSeparator());
        System.out.print(bunchOfNewLines);

        // Scroll the current line to the top of the window,
        try {
            // If we are on Windows,
            new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
        } catch (Exception e) {

            // We are not on Windows,
            bunchOfNewLines = new StringBuilder();
            for (int i=0; i<124; i++) bunchOfNewLines.append("\b\r");
            System.out.print(bunchOfNewLines);
        }
    }

    private static void handleUserInput() {

        // Line read. Unfortunately, java doesn't provide character by character reading out of the box.
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        String input = "";
        do {
            try {
                if (bufferedReader.ready()) {
                    input = input = bufferedReader.readLine().toUpperCase();

                    // Set log level,
                    if (input.equals("V")||input.equals("D")||input.equals("I")||input.equals("W")||input.equals("E")) {

                        if (!logLevelToShow.equals(input)) {
                            logLevelToShow = input;
                            clearAndroidStudioConsole();
                            repeatHistory();
                        }

                        prettify("----- Log level set to " + logLevelToShow + " -----");

                    } else if (input.equals("C")) {

                        // Clear screen and history,
                        clearAndroidStudioConsole();
                        historyLength = 0;
                    }
                } else {
                    Thread.sleep(100);
                }
            } catch (Exception e) { e.printStackTrace(); }

            // Check if the logcat process is still alive,
            if (!logcatProcess.isAlive()) {
                prettify("----- adb logcat process terminated -----");
                stopEverything = true;
            }

        } while (!stopEverything && !input.equals("Q"));

        // Allow all monitoring threads to exit,
        stopEverything = true;
    }

    interface ProcessListener {
        void onNewLine(String line);
    }

    enum Color {

        // Thanks to this answer: https://stackoverflow.com/a/51944613/1942069

        //Color end string, color reset
        RESET("\033[0m"),

        // Regular Colors. Normal color, no bold, background color etc.
        BLACK  ("\033[0;30m"),
        RED    ("\033[0;31m"),
        GREEN  ("\033[0;32m"),
        YELLOW ("\033[0;33m"),
        BLUE   ("\033[0;34m"),
        MAGENTA("\033[0;35m"),
        CYAN   ("\033[0;36m"),
        WHITE  ("\033[0;37m"),

        // Bold
        BLACK_BOLD  ("\033[1;30m"),
        RED_BOLD    ("\033[1;31m"),
        GREEN_BOLD  ("\033[1;32m"),
        YELLOW_BOLD ("\033[1;33m"),
        BLUE_BOLD   ("\033[1;34m"),
        MAGENTA_BOLD("\033[1;35m"),
        CYAN_BOLD   ("\033[1;36m"),
        WHITE_BOLD  ("\033[1;37m"),

        // Underline
        BLACK_UNDERLINED  ("\033[4;30m"),
        RED_UNDERLINED    ("\033[4;31m"),
        GREEN_UNDERLINED  ("\033[4;32m"),
        YELLOW_UNDERLINED ("\033[4;33m"),
        BLUE_UNDERLINED   ("\033[4;34m"),
        MAGENTA_UNDERLINED("\033[4;35m"),
        CYAN_UNDERLINED   ("\033[4;36m"),
        WHITE_UNDERLINED  ("\033[4;37m"),

        // Background
        BLACK_BACKGROUND  ("\033[40m"),
        RED_BACKGROUND    ("\033[41m"),
        GREEN_BACKGROUND  ("\033[42m"),
        YELLOW_BACKGROUND ("\033[43m"),
        BLUE_BACKGROUND   ("\033[44m"),
        MAGENTA_BACKGROUND("\033[45m"),
        CYAN_BACKGROUND   ("\033[46m"),
        WHITE_BACKGROUND  ("\033[47m"),

        // High Intensity
        BLACK_BRIGHT  ("\033[0;90m"),
        RED_BRIGHT    ("\033[0;91m"),
        GREEN_BRIGHT  ("\033[0;92m"),
        YELLOW_BRIGHT ("\033[0;93m"),
        BLUE_BRIGHT   ("\033[0;94m"),
        MAGENTA_BRIGHT("\033[0;95m"),
        CYAN_BRIGHT   ("\033[0;96m"),
        WHITE_BRIGHT  ("\033[0;97m"),

        // Bold High Intensity
        BLACK_BOLD_BRIGHT  ("\033[1;90m"),
        RED_BOLD_BRIGHT    ("\033[1;91m"),
        GREEN_BOLD_BRIGHT  ("\033[1;92m"),
        YELLOW_BOLD_BRIGHT ("\033[1;93m"),
        BLUE_BOLD_BRIGHT   ("\033[1;94m"),
        MAGENTA_BOLD_BRIGHT("\033[1;95m"),
        CYAN_BOLD_BRIGHT   ("\033[1;96m"),
        WHITE_BOLD_BRIGHT  ("\033[1;97m"),

        // High Intensity backgrounds
        BLACK_BACKGROUND_BRIGHT  ("\033[0;100m"),
        RED_BACKGROUND_BRIGHT    ("\033[0;101m"),
        GREEN_BACKGROUND_BRIGHT  ("\033[0;102m"),
        YELLOW_BACKGROUND_BRIGHT ("\033[0;103m"),
        BLUE_BACKGROUND_BRIGHT   ("\033[0;104m"),
        MAGENTA_BACKGROUND_BRIGHT("\033[0;105m"),
        CYAN_BACKGROUND_BRIGHT   ("\033[0;106m"),
        WHITE_BACKGROUND_BRIGHT  ("\033[0;107m");

        private final String code;

        Color(String code) { this.code = code; }
        @Override public String toString() { return code; }
    }
}

只需将这段代码转储到Logcat.java并使用以下方法进行编译:

javac Logcat.java

并在Android Studio的嵌入式终端中运行:

java Logcat <your.package.name>

例如:

java Logcat com.nomone.vr_desktop

结果如下所示:

它是高度可定制的,我在应用程序的第一部分分离了大部分选项,所以你可以很容易地调整颜色和格式。如果adb工具不在PATH环境变量中,只需在编译前在ADB_FILE_PATH变量中设置它的完整路径(在代码中)。

当应用程序正在运行时,您可以键入以下快捷方式:

C清除屏幕和本地缓冲区。 V, i, d, w, e来改变logcat的级别。 优雅地退出。Ctrl+c也可以。

不幸的是,在按完这些键后,您必须按回车键。似乎Java不允许在不编写系统特定代码的情况下从控制台输入单个字符。对不起!

免责声明

如果使用adb连接多个设备,这将不起作用。 我还没有彻底测试这个。我只在少数设备上使用过一段时间。 我还没有在Windows或Mac上测试,但我尽量避免使用任何特定于系统的东西,所以它应该仍然有效。

我希望这能解决你的问题:)

我有同样的症状,但我的问题要简单得多,这真的是我的错误。我的滤镜设置错了。

解决方案只是验证我设置了正确的过滤器。

禁用并卸载您最近安装且不使用的任何插件。