Eclipse中Logcat中文解决办法,重装该ADT即可

     这个问题从一开始接触到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里,

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);
                         } 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就可以了...

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"); //问题在这里,把所有输出的字串都使用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("\r\n", start); //$NON-NLS-1$

                     // if \r\n 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 \r\n;
                     // extract the line
                     String line = s.substring(start, index);
                     if (mTrimLines) {
                         line = line.trim();
                     }
                     mArray.add(line);

                     // move start to after the \r\n 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,其中除了中文问题,其他与官方的完全相同。

你可能感兴趣的:(eclipse,android,json,sqlite,Google)