簡體   English   中英

為什么“System.out.println”在Android 中不起作用?

[英]Why doesn't “System.out.println” work in Android?

我想在控制台中打印一些東西,以便我可以調試它。 但出於某種原因,我的 Android 應用程序中沒有打印任何內容。

那我該如何調試呢?

public class HelloWebview extends Activity {
    WebView webview;    
    private static final String LOG_TAG = "WebViewDemo";
    private class HelloWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        webview = (WebView) findViewById(R.id.webview);
        webview.setWebViewClient(new HelloWebViewClient());
        webview.getSettings().setJavaScriptEnabled(true);
        webview.setWebChromeClient(new MyWebChromeClient());
        webview.loadUrl("http://example.com/");    
        System.out.println("I am here");
    }

更正:

在模擬器和大多數設備上System.out.println被重定向到 LogCat 並使用Log.i()打印。 這可能不適用於非常舊的或自定義的 Android 版本。

原來的:

沒有控制台可以發送消息,因此System.out.println消息會丟失。 以同樣的方式,當您使用javaw運行“傳統”Java 應用程序時, javaw發生這種情況。

相反,您可以使用Android Log

Log.d("MyApp","I am here");

然后,您可以在 Eclipse 的Logcat視圖中查看日志,或者運行以下命令:

adb logcat

養成查看 logcat 輸出的習慣很好,因為這也是顯示任何未捕獲異常的堆棧跟蹤的地方。

每個日志記錄調用的第一個條目是標識日志消息來源的日志標記。 這很有用,因為您可以過濾日志的輸出以僅顯示您的消息。 為了確保您與您的日志標簽一致,最好在某處將其定義為static final String

Log.d(MyActivity.LOG_TAG,"Application started");

Log一字法有五種,分別對應以下級別:

  • e() - 錯誤
  • w() - 警告
  • i() - 信息
  • d() - 調試
  • v() - 詳細
  • wtf() - 多么可怕的失敗

文檔說明了以下級別

除非在開發過程中,否則不應將 Verbose 編譯到應用程序中。 調試日志被編譯但在運行時被剝離。 錯誤、警告和信息日志始終保留。

使用日志類 LogCat 輸出可見

是的,它確實。 如果您使用模擬器,它將顯示在System.out標記下的 Logcat 視圖中。 寫一些東西並在你的模擬器中嘗試。

當然,要在logcat中看到結果,至少應該將Log級別設置為“Info”( logcat中的Log級別); 否則,就像我遇到的那樣,您將看不到輸出。

如果你真的需要 System.out.println 工作(例如,它是從第三方庫調用的)。 您可以簡單地使用反射來更改 System.class 中的字段:

try{
    Field outField = System.class.getDeclaredField("out");
    Field modifiersField = Field.class.getDeclaredField("accessFlags");
    modifiersField.setAccessible(true);
    modifiersField.set(outField, outField.getModifiers() & ~Modifier.FINAL);
    outField.setAccessible(true);
    outField.set(null, new PrintStream(new RedirectLogOutputStream()); 
}catch(NoSuchFieldException e){
    e.printStackTrace(); 
}catch(IllegalAccessException e){
    e.printStackTrace(); 
}

RedirectLogOutputStream 類:

public class RedirectLogOutputStream extends OutputStream{
    private String mCache;

    @Override
    public void write(int b) throws IOException{
        if(mCache == null) mCache = "";

        if(((char) b) == '\n'){
            Log.i("redirect from system.out", mCache);
            mCache = "";
        }else{
            mCache += (char) b;
        }
    }
}

它沒有顯示在您的應用程序中...它在您的模擬器的 logcat 下

手機上沒有地方可以讀取System.out.println();

相反,如果您想查看結果,請查看您的logcat/console窗口,或者在設備屏幕上顯示ToastSnackbar (如果您使用的是較新的設備)並顯示消息 :) 這就是我所做的例如,當我必須檢查它在switch case代碼中的位置時! 玩得開心編碼! :)

System.out.println("...") 顯示在 Android Studio 的 Android Monitor 上

我會把這個留給更多的訪問者,因為對我來說這是關於主線程無法System.out.println事情。

public class LogUtil {

private static String log = "";
private static boolean started = false;
public static void print(String s) {
    //Start the thread unless it's already running
    if(!started) {
        start();
    }
    //Append a String to the log
    log += s;
}

public static void println(String s) {
    //Start the thread unless it's already running
    if(!started) {
        start();
    }
    //Append a String to the log with a newline.
    //NOTE: Change to print(s + "\n") if you don't want it to trim the last newline.
    log += (s.endsWith("\n") )? s : (s + "\n");
}

private static void start() {
    //Creates a new Thread responsible for showing the logs.
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            while(true) {
                //Execute 100 times per second to save CPU cycles.
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //If the log variable has any contents...
                if(!log.isEmpty()) {
                    //...print it and clear the log variable for new data.
                    System.out.print(log);
                    log = "";
                }
            }
        }
    });
    thread.start();
    started = true;
}
}

用法: LogUtil.println("This is a string");

我沒有花哨的 IDE 來使用 LogCat,因為我使用的是移動 IDE。

我不得不使用各種其他方法,如果您需要,我有類和實用程序供您使用。

  1. 類 jav.android.Msg。 有一組靜態方法。 A:打印android TOASTS的方法。 B:彈出對話框的方法。 每個方法都需要一個有效的上下文。 您可以設置默認上下文。

  2. 一個更雄心勃勃的方式,一個 Android 控制台。 您在應用程序中實例化控制台的句柄,它會啟動控制台(如果已安裝),並且您可以寫入控制台。 我最近更新了控制台以實現從控制台讀取輸入。 在收到輸入之前不會返回,就像常規控制台一樣。 A:下載並安裝 Android 控制台(從我這里獲取) B:附帶一個 java 文件(jav.android.console.IConsole)。 將其放在適當的目錄中。 它包含操作 Android Console 的方法。 C:調用完成初始化的構造函數。 D:讀取<*>並寫入控制台。 還有工作要做。 即,由於 OnServiceConnected 不會立即調用,因此您不能在實例化它的同一函數中使用 IConsole。

  3. 在創建 Android Console 之前,我創建了 Console Dialog,這是一個在同一個應用程序中運行的對話框,類似於控制台。 優點:無需等待 OnServiceConnected 使用它。 缺點:當應用程序崩潰時,您不會收到導致應用程序崩潰的消息。

由於 Android Console 是單獨進程中的單獨應用程序,如果您的應用程序崩潰,您肯定會看到錯誤。 此外,IConsole 在您的應用程序中設置了一個未捕獲的異常處理程序,以防您不熱衷於異常處理。 它幾乎將堆棧跟蹤和異常消息打印到 Android 控制台。 最后,如果 Android 控制台崩潰,它會將其堆棧跟蹤和異常發送給您,您可以選擇一個應用程序來讀取它。 實際上,AndroidConsole 不需要崩潰。

Edit Extras我注意到我的 while APK Builder 沒有 LogCat; AIDE 可以。 然后我意識到無論如何都可以使用我的 Android 控制台。

  1. Android 控制台設計為僅占據屏幕的一部分,因此您可以看到您的應用程序以及從您的應用程序發送到控制台的數據。 這在 AIDE 中是不可能的。 所以我想觸摸屏幕並查看坐標,Android Console 使這變得容易。

  2. Android 控制台旨在在您寫入時彈出。

  3. 當您后退時,Android 控制台將隱藏。

最近我在 Android Studio 3.3 中發現了同樣的問題。 我關閉了其他 Android Studio 項目,Logcat 開始工作。 上面接受的答案根本不合邏輯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM