Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 高級開發 >> Android Eclipse中Logcat中文解決辦法

Android Eclipse中Logcat中文解決辦法

編輯:高級開發

 這個問題從一開始接觸到android開發就困擾我很久了,平常除錯少用中文log這個問題影響到不大,但是碰到需要把data (通常是遠端的JSon or 本地端cache的sqlite)印出來觀察這一種除錯的情境時,這問題就頭大了!

  問了google也沒有好解答,在android的google code裡issue 1590就是在陳述這個問題,下面Comment提供的方法我試不出來,有趣的是用adb logcat在console下是不會有亂碼的,所以問題一定出在ADT上,最近自已build了ADT trunk來用,剛好又遇到需要dump中文的data來debug的case,所以就嘗試著自已來trace問題。

  LogCat的相關的code都在LogPanel.Java裡,

  Java代碼

  public class LogPanel extends SelectionDependentPanel {

  private LogCatOuputReceiver mCurrentLogCat;

  @Override

  protected Control createControl(Composite parent) {...}

  private TabItem createTab(LogFilter filter, int index, boolean fillTable) {...}

  /**

  * Sent when a new device is selected. The new device can be Accessed

  * with {@link #getCurrentDevice()}.

  */

  @Override

  public void deviceSelected() {

  startLogCat(getCurrentDevice());

  }

  public void startLogCat(final IDevice device) {

  if (device == mCurrentLoggedDevice) {

  return;

  }

  // if we have a logcat already running

  if (mCurrentLoggedDevice != null) {

  stopLogCat(false);

  mCurrentLoggedDevice = null;

  }

  resetUI(false);

  if (device != null) {

  // create a new output receiver

  mCurrentLogCat = new LogCatOuputReceiver();

  // start the logcat in a different thread

  new Thread("Logcat") { //$NON-NLS-1$

  @Override

  public void run() {

  while (device.isOnline() == false &&

  mCurrentLogCat != null &&

  mCurrentLogCat.isCancelled == false) {

  try {

  sleep(2000);


  點擊下載:重新編譯後的的ADT

  接上頁

  } catch (InterruptedException e) {

  return;

  }

  }

  if (mCurrentLogCat == null || mCurrentLogCat.isCancelled) {

  // logcat was stopped/cancelled before the device became ready.

  return;

  }

  try {

  mCurrentLoggedDevice = device;

  device.executeShellCommand("logcat -v long", mCurrentLogCat, 0 /*timeout*/); //$NON-NLS-1$

  } catch (Exception e) {

  Log.e("Logcat", e);

  } finally {

  // at this point the command is terminated.

  mCurrentLogCat = null;

  mCurrentLoggedDevice = null;

  }

  }

  }.start();

  }

  }

  }

  public class LogPanel extends SelectionDependentPanel {

  private LogCatOuputReceiver mCurrentLogCat;

  @Override

  protected Control createControl(Composite parent) {...}

  private TabItem createTab(LogFilter filter, int index, boolean fillTable) {...}

  /**

  * Sent when a new device is selected. The new device can be Accessed

  * with {@link #getCurrentDevice()}.

  */

  @Override

  public void deviceSelected() {

  startLogCat(getCurrentDevice());

  }

  public void startLogCat(final IDevice device) {

  if (device == mCurrentLoggedDevice) {

  return;

  }

  // if we have a logcat already running

  if (mCurrentLoggedDevice != null) {

  stopLogCat(false);

  mCurrentLoggedDevice = null;

  }

  resetUI(false);

  if (device != null) {

  // create a new output receiver

  mCurrentLogCat = new LogCatOuputReceiver();

  // start the logcat in a different thread

  new Thread("Logcat") { //$NON-NLS-1$

  @Override

  public void run() {


  點擊下載:重新編譯後的的ADT

  接上頁

  while (device.isOnline() == false &&

  mCurrentLogCat != null &&

  mCurrentLogCat.isCancelled == false) {

  try {

  sleep(2000);

  } catch (InterruptedException e) {

  return;

  }

  }

  if (mCurrentLogCat == null || mCurrentLogCat.isCancelled) {

  // logcat was stopped/cancelled before the device became ready.

  return;

  }

  try {

  mCurrentLoggedDevice = device;

  device.executeShellCommand("logcat -v long", mCurrentLogCat, 0 /*timeout*/); //$NON-NLS-1$

  } catch (Exception e) {

  Log.e("Logcat", e);

  } finally {

  // at this point the command is terminated.

  mCurrentLogCat = null;

  mCurrentLoggedDevice = null;

  }

  }

  }.start();

  }

  }

  }

  class Device的method executeShellCommand有三個參數分別是String command, IShellOutputReceiver receiver, int maxTimeToOutputResponse,它會透過class AdbHelper來做一下adb utility的指令操作。在第xx行時,執行了logcat -v long並把輸出丟給LogCatOutputReceiver處理,所以我們的重點在於class LogCatOutputReceiver。繼續追進去method executeShellCommand會發現它會把所有接收的data丟給interface IShellOutputReceiver的method addOutput處理,現在這個角色就是class LogCatOutputReceiver,而它的method addOutput是繼承class MultiLineReceiver而來,問題就出在這裡,把ISO -8859-1改成UTF-8就可以了...

  Java代碼

  public abstract class MultiLineReceiver implements IShellOutputReceiver {

  /* (non-Javadoc)

  * @see com.android.ddmlib.adb.IShellOutputReceiver#addOutput(

  * byte[], int, int)

  */

  public final void addOutput(byte[] data, int offset, int length) {

  if (isCancelled() == false) {

  String s = null;

  try {

  s = new String(data, offset, length, "ISO-8859-1");


  點擊下載:重新編譯後的的ADT

  接上頁

//問題在這裡,把所有輸出的字串都使用ISO-8859-1 decode

  } catch (UnsupportedEncodingException e) {

  // normal encoding didn't work, try the default one

  s = new String(data, offset,length);

  }

  // ok we've got a string

  if (s != null) {

  // if we had an unfinished line we add it.

  if (mUnfinishedLine != null) {

  s = mUnfinishedLine + s;

  mUnfinishedLine = null;

  }

  // now we split the lines

  mArray.clear();

  int start = 0;

  do {

  int index = s.indexOf("", start); //$NON-NLS-1$

  // if was not found, this is an unfinished line

  // and we store it to be processed for the next packet

  if (index == -1) {

  mUnfinishedLine = s.substring(start);

  break;

  }

  // so we found a ;

  // extract the line

  String line = s.substring(start, index);

  if (mTrimLines) {

  line = line.trim();

  }

  mArray.add(line);

  // move start to after the we found

  start = index + 2;

  } while (true);

  if (mArray.size() > 0) {

  // at this point we've split all the lines.

  // make the array

  String[] lines = mArray.toArray(new String[mArray.size()]);

  // send it for final processing

  processNewLines(lines);

  }

  }

  }

  }

  }

  public abstract class MultiLineReceiver implements IShellOutputReceiver {

  /* (non-Javadoc)

  * @see com.android.ddmlib.adb.IShellOutputReceiver#addOutput(

  * byte[], int, int)

  */

  public final void addOutput(byte[] data, int offset, int length) {

  if (isCancelled() == false) {

  String s = null;

  try {

  s = new String(data, offset, length, "ISO-8859-1");


  點擊下載:重新編譯後的的ADT

  接上頁

//問題在這裡,把所有輸出的字串都使用ISO-8859-1 decode

  } catch (UnsupportedEncodingException e) {

  // normal encoding didn't work, try the default one

  s = new String(data, offset,length);

  }

  // ok we've got a string

  if (s != null) {

  // if we had an unfinished line we add it.

  if (mUnfinishedLine != null) {

  s = mUnfinishedLine + s;

  mUnfinishedLine = null;

  }

  // now we split the lines

  mArray.clear();

  int start = 0;

  do {

  int index = s.indexOf("", start); //$NON-NLS-1$

  // if was not found, this is an unfinished line

  // and we store it to be processed for the next packet

  if (index == -1) {

  mUnfinishedLine = s.substring(start);

  break;

  }

  // so we found a ;

  // extract the line

  String line = s.substring(start, index);

  if (mTrimLines) {

  line = line.trim();

  }

  mArray.add(line);

  // move start to after the we found

  start = index + 2;

  } while (true);

  if (mArray.size() > 0) {

  // at this point we've split all the lines.

  // make the array

  String[] lines = mArray.toArray(new String[mArray.size()]);

  // send it for final processing

  processNewLines(lines);

  }

  }

  }

  }

  }

  然後重新編譯DDMS即可。

  $javac -classpath ./ddms.jar:./ddmlib.jar MultiLineReceiver.Java

  下面便為重新編譯後的的ADT,其中除了中文問題,其他與官方的完全相同。


  點擊下載:重新編譯後的的ADT

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved