android studio上HierarchyViewer的使用实例

使用方法:

1无法再真机运行,需要在模拟机运行

 

2app在manifest要添加
1<uses-permission android:name="android.permission.INTERNET"/>

2<application android:debugable=" true"

 

3在测试的activity中使用:

(1)添加三行代码:

                    public void onCreate(Bundle savedInstanceState) {

          super.onCreate(savedInstanceState);
 
          ViewServer.get(this).addWindow(this);
      }
 
      public void onDestroy() {
          super.onDestroy();
          ViewServer.get(this).removeWindow(this);
      }
 
      public void onResume() {
          super.onResume();
          ViewServer.get(this).setFocusedWindow(this);
      }

2)点击运行as项目,然后模拟器运行程序,

3tools--android--androiddevice monitor

(4)界面打开后,没有找到,搜索hierarachy view即可,本人亲测,没有问题

直接上使用的源码:

创建ViewServer.java类(拷贝过去就可以):

package com.linzhi.receiver (替换) ;

import android.app.Activity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewDebug;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 
*布局优化HierarchyViewer的类
 
*
 
* Created by sjy on 2017/5/2.
 */

public class ViewServer implements Runnable {
   
/**
    
* The default port used to startview servers.
     */
   
private static final int VIEW_SERVER_DEFAULT_PORT = 4939 ;
   
private static final int VIEW_SERVER_MAX_CONNECTIONS = 10 ;
   
private static final String BUILD_TYPE_USER = "user" ;

   
// Debug facility
   
private static final String LOG_TAG = "ViewServer" ;

   
private static final String VALUE_PROTOCOL_VERSION = "4" ;
   
private static final String VALUE_SERVER_VERSION = "4" ;

   
// Protocol commands
   
// Returns the protocol version
   
private static final String COMMAND_PROTOCOL_VERSION = "PROTOCOL" ;
   
// Returns the server version
   
private static final String COMMAND_SERVER_VERSION = "SERVER" ;
   
// Lists all of the available windows in thesystem
   
private static final String COMMAND_WINDOW_MANAGER_LIST = "LIST" ;
   
// Keeps a connection open and notifies when thelist of windows changes
   
private static final String COMMAND_WINDOW_MANAGER_AUTOLIST = "AUTOLIST" ;
   
// Returns the focused window
   
private static final String COMMAND_WINDOW_MANAGER_GET_FOCUS = "GET_FOCUS" ;

   
private ServerSocket mServer ;
   
private final int mPort ;

   
private Thread mThread ;
   
private ExecutorService mThreadPool ;

   
private final List<WindowListener> mListeners =
           
new CopyOnWriteArrayList<WindowListener>();

   
private final HashMap<View, String> mWindows = new HashMap<View,String>();
   
private final ReentrantReadWriteLock mWindowsLock = new ReentrantReadWriteLock();

   
private View mFocusedWindow ;
   
private final ReentrantReadWriteLock mFocusLock = new ReentrantReadWriteLock();

   
private static ViewServer sServer ;

   
/**
    
* Returns a unique instance of theViewServer. This method should only be
     * called from the main thread ofyour application. The server will have
     * the same lifetime as your process.
     * <p/>
     * If your application does not havethe <code>android:debuggable</code>
    * flag set in its manifest, the server returned by this method will
     * be a dummy object that does not doanything. This allows you to use
     * the same code in debug and releaseversions of your application.
     *
     * @param context A Context used to check whether the applicationis
    
*                debuggable, this can be theapplication context
     */
   
public static ViewServer get(Context context) {
       
ApplicationInfo info =context.getApplicationInfo();
        if ( BUILD_TYPE_USER .equals(Build. TYPE ) &&
               
(info. flags & ApplicationInfo. FLAG_DEBUGGABLE ) != 0 ) {
           
if ( sServer == null ) {
               
sServer = new ViewServer(ViewServer. VIEW_SERVER_DEFAULT_PORT );
           
}

            if (! sServer .isRunning()) {
               
try {
                   
sServer .start();
               
} catch (IOException e) {
                   
Log. d( LOG_TAG , "Error:" , e);
               
}
            }
        } else {
           
sServer = new NoopViewServer();
       
}

        return sServer ;
   
}

    private ViewServer() {
       
mPort = - 1 ;
   
}

    /**
    
* Creates a new ViewServerassociated with the specified window manager on the
     * specified local port. The serveris not started by default.
     *
     * @param port The port for the server to listen to.
    
* @see #start()
     */
   
private ViewServer( int port) {
       
mPort = port;
   
}

    /**
    
* Starts the server.
     *
     * @return True if the serverwas successfully created, or false if it already exists.
     * @throws java.io.IOExceptionIf the server cannot be created.
     * @see #stop()
     * @see #isRunning()
     */
   
public boolean start() throws IOException {
       
if ( mThread != null ) {
     
       return false ;
       
}

        mThread = new Thread( this , "LocalView Server [port=" + mPort + "]" );
       
mThreadPool = Executors.newFixedThreadPool( VIEW_SERVER_MAX_CONNECTIONS );
       
mThread .start();

       
return true ;
   
}

    /**
   
 * Stops the server.
     *
     * @return True if the serverwas stopped, false if an error occurred or if the
     * server wasn't started.
     * @see #start()
     * @see #isRunning()
     */
   
public boolean stop() {
       
if ( mThread != null ) {
 
           mThread .interrupt();
           
if ( mThreadPool != null ) {
               
try {
                   
mThreadPool .shutdownNow();
               
} catch (SecurityException e) {
                   
Log. w( LOG_TAG , "Couldnot stop all view server threads" );
               
}
            }

            mThreadPool = null ;
           
mThread = null ;

           
try {
               
mServer .close();
               
mServer = null ;
               
return true ;
           
} catch (IOException e) {
 
              Log. w( LOG_TAG , "Couldnot close the view server" );
           
}
        }

        mWindowsLock .writeLock().lock();
       
try {
           
mWindows .clear();
       
} finally {
           
mWindowsLock .writeLock().unlock();
       
}

         mFocusLock .writeLock().lock();
       
try {
           
mFocusedWindow = null ;
       
} finally {
           
mFocusLock .writeLock().unlock();
       
}

        return false ;
   
}

    /**
    
* Indicates whether the server iscurrently running.
     *
     * @return True if the serveris running, false otherwise.
     * @see #start()
     * @see #stop()
     */
   
public boolean isRunning() {
       
return mThread != null && mThread .isAlive();
   
}

    /**
    
* Invoke this method to register anew view hierarchy.
     *
     * @param activity The activity whose view hierarchy/window toregister
    
* @see #addWindow(android.view.View,String)
     * @see #removeWindow(android.app.Activity)
     */
   
public void addWindow(Activity activity) {
       
String name =activity.getTitle().toString();
        if (TextUtils.isEmpty(name)){
           
name =activity.getClass().getCanonicalName() +
                    "/0x" + System.identityHashCode(activity);
       
} else {
           
name += "(" + activity.getClass().getCanonicalName() + ")" ;
       
}
       addWindow(activity.getWindow().getDecorView(), name);
    }

    /**
    
* Invoke this method to unregister aview hierarchy.
     *
     * @param activity The activity whose view hierarchy/window tounregister
    
* @see #addWindow(android.app.Activity)
     * @see #removeWindow(android.view.View)
     */
   
public void removeWindow(Activity activity) {
       
removeWindow(activity.getWindow().getDecorView());
    }

    /**
    
* Invoke this method to register anew view hierarchy.
     *
     * @param view A view that belongs to the view hierarchy/windowto register
    
* @name name The name of theview hierarchy/window to register
     * @see #removeWindow(android.view.View)
     */
   
public void addWindow(View view, String name) {
       
mWindowsLock .writeLock().lock();
       
try {
           
mWindows .put(view.getRootView(), name);
       
} finally {
           
mWindowsLock .writeLock().unlock();
       
}
        fireWindowsChangedEvent();
    }


    /**
    
* Invoke this method to unregister aview hierarchy.
     *
     * @param view A view that belongs to the view hierarchy/windowto unregister
    
* @see #addWindow(android.view.View,String)
     */
   
public void removeWindow(View view) {
       
mWindowsLock .writeLock().lock();
       
try {
           
mWindows .remove(view.getRootView());
       
} finally {
           
mWindowsLock .writeLock().unlock();
       
}
        fireWindowsChangedEvent();
    }

    /**
    
* Invoke this method to change thecurrently focused window.
     *
     * @param activity The activity whose view hierarchy/windowhasfocus,
    
*                 or null to remove focus
     */
   
public void setFocusedWindow(Activity activity) {
       
setFocusedWindow(activity.getWindow().getDecorView());
    }


    /**
    
* Invoke this method to change thecurrently focused window.
     *
     * @param view A view that belongs to the view hierarchy/windowthat has focus,
    
*            or null to remove focus
     */
   
public void setFocusedWindow(View view) {
       
mFocusLock .writeLock().lock();
       
try {
           
mFocusedWindow = view == null ? null : view.getRootView();
       
} finally {
           
mFocusLock .writeLock().unlock();
       
}
        fireFocusChangedEvent();
    }

    /**
    
* Main server loop.
     */
   
public void run() {
       
try {
           
InetAddress address =InetAddress. getLocalHost();
            mServer = new ServerSocket( mPort , VIEW_SERVER_MAX_CONNECTIONS , address);
       
} catch (Exception e) {
           
Log. w( LOG_TAG , "StartingServerSocket error: " ,e);
       
}

        while ( mServer != null && Thread.currentThread() == mThread ) {
           
// Any uncaught exception will crash the systemprocess
           
try {
               
Socket client = mServer .accept();
               
if ( mThreadPool != null ) {
                   
mThreadPool .submit( new ViewServerWorker(client));
               
} else {
                   
try {
                       
client.close();
                    } catch (IOException e) {
                       
e.printStackTrace();
                    }
                }
            } catch (Exception e) {
               
Log. w( LOG_TAG , "Connectionerror: " ,e);
           
}
        }
    }

    private static boolean writeValue(Socket client, String value) {
       
boolean result;
       
BufferedWriter out = null ;
       
try {
           
OutputStream clientStream =client.getOutputStream();
            out = new BufferedWriter( new OutputStreamWriter(clientStream), 8 * 1024 );
           
out.write(value);
            out.write( "\n" );
           
out.flush();
            result = true ;
       
} catch (Exception e) {
           
result = false ;
  
     } finally {
           
if (out!= null ) {
               
try {
                   
out.close();
                } catch (IOException e) {
                   
result = false ;
               
}
            }
        }
        return result;
   
}

     privatevoid fireWindowsChangedEvent(){
       
for (WindowListener listener : mListeners ) {
           
listener.windowsChanged();
        }
    }

    private void fireFocusChangedEvent() {
       
for (WindowListener listener : mListeners ) {
        
   listener.focusChanged();
        }
    }

    private void addWindowListener(WindowListener listener) {
       
if (! mListeners .contains(listener)) {
           
mListeners .add(listener);
       
}
    }

    private void removeWindowListener(WindowListener listener) {
       
mListeners .remove(listener);
   
}

    private interface WindowListener {
       
void windowsChanged();

       
void focusChanged();
   
}

    private class ViewServerWorker implements Runnable, WindowListener {
       
private Socket mClient ;
       
private boolean mNeedWindowListUpdate ;
       
private boolean mNeedFocusedWindowUpdate ;

       
private final Object[] mLock = new Object[ 0 ];

       
public ViewServerWorker(Socket client) {
           
mClient = client;
      
      mNeedWindowListUpdate = false ;
           
mNeedFocusedWindowUpdate = false ;
       
}

        public void run() {
           
BufferedReader in = null ;
           
try {
               
in = new BufferedReader( new InputStreamReader( mClient .getInputStream()), 1024 );

               
final String request = in.readLine();

               
Log. i( "Command" , "===>" + request);

               
String command;
                String parameters;

                int index = request.indexOf( ' ' );
           
     if (index== - 1 ) {
                   
command = request;
                    parameters = "" ;
               
} else {
                   
command =request.substring( 0 , index);
                   
parameters =request.substring(index + 1 );
         
      }

                boolean result;
               
if ( COMMAND_PROTOCOL_VERSION .equalsIgnoreCase(command)) {
                   
result = writeValue( mClient , VALUE_PROTOCOL_VERSION );
               
} else if ( COMMAND_SERVER_VERSION .equalsIgnoreCase(command)) {
                   
result = writeValue( mClient , VALUE_SERVER_VERSION );
               
} else if ( COMMAND_WINDOW_MANAGER_LIST .equalsIgnoreCase(command)) {
                   
result = listWindows( mClient );
               
} else if ( COMMAND_WINDOW_MANAGER_GET_FOCUS .equalsIgnoreCase(command)) {
                   
result =getFocusedWindow( mClient );
               
} else if ( COMMAND_WINDOW_MANAGER_AUTOLIST .equalsIgnoreCase(command)) {
                   
result =windowManagerAutolistLoop();
                } else {
                   
result =windowCommand( mClient , command, parameters);
               
}

                if (!result){
                   
Log. w( LOG_TAG , "Anerror occurred with the command: " + command);
    
           }
            } catch (IOException e) {
               
Log. w( LOG_TAG , "Connectionerror: " ,e);
           
} finally {
               
if (in!= null ) {
                   
try {
                       
in.close();

                    } catch (IOException e) {
                       
e.printStackTrace();
                    }
                }
                if ( mClient != null ) {
                   
try {
                       
mClient .close();
                   
} catch (IOException e) {
                       
e.printStackTrace();
                    }
                }
            }
        }

        private boolean windowCommand(Socket client, String command,String parameters) {
           
boolean success = true ;
           
BufferedWriter out = null ;

           
try {
               
// Find the hash code of the window
               
int index = parameters.indexOf( ' ' );
               
if (index== - 1 ) {
                   
index =parameters.length();
                }
                 final String code = parameters.substring( 0 ,index);
               
int hashCode = ( int )Long.parseLong(code, 16 );

               
// Extract the command's parameter after thewindow description
               
if (index< parameters.length()) {
   
                parameters =parameters.substring(index + 1 );
               
} else {
                   
parameters = "" ;
               
}
                final View window = findWindow(hashCode);
               
if (window== null ) {
                 
   returnfalse ;
               
}

                // call stuff
               
final Method dispatch = ViewDebug. class .getDeclaredMethod( "dispatchCommand" ,
                       
View. class , String. class , String. class , OutputStream. class );
            
   dispatch.setAccessible( true );
               
dispatch.invoke( null , window, command, parameters,
                       
new UncloseableOutputStream(client.getOutputStream()));

               
if (!client.isOutputShutdown()){
                   
out = new BufferedWriter( new OutputStreamWriter(client.getOutputStream()));
                   
out.write( "DONE\n" );
                   
out.flush();
                }

            } catch (Exception e) {
               
Log. w( LOG_TAG , "Couldnot send command " +command +
                       
" with parameters " + parameters, e);
               
success = false ;
           
} finally {
               
if (out!= null ) {
                   
try {
                       
out.close();
                    } catch (IOException e) {
                       
success = false ;
                   
}
                }
            }

            return success;
       
}

        private View findWindow( int hashCode) {
           
if (hashCode== - 1 ) {
               
View window = null ;
               
mWindowsLock .readLock().lock();
               
try {
                   
window = mFocusedWindow ;
               
} finally {
                   
mWindowsLock .readLock().unlock();
               
}
                return window;
           
}


            mWindowsLock .readLock().lock();
           
try {
               
for (Map.Entry<View, String> entry : mWindows .entrySet()) {
                   
if (System.identityHashCode(entry.getKey())== hashCode) {
              
          return entry.getKey();
                   
}
                }
            } finally {
               
mWindowsLock .readLock().unlock();
           
}

            return null ;
       
}

        private boolean listWindows(Socket client) {
     
       boolean result = true ;
           
BufferedWriter out = null ;

           
try {
               
mWindowsLock .readLock().lock();

               
OutputStream clientStream= client.getOutputStream();
                out = new BufferedWriter( new OutputStreamWriter(clientStream), 8 * 1024 );

               
for (Map.Entry<View, String> entry : mWindows .entrySet()) {
                   
out.write(Integer. toHexString(System. identityHashCode(entry.getKey())));
                    out.write( ' ' );
         
          out.append(entry.getValue());
                    out.write( '\n' );
               
}

                out.write( "DONE.\n" );
               
out.flush();
            } catch (Exception e) {
               
result = false ;
           
} finally {
 
               mWindowsLock .readLock().unlock();

               
if (out!= null ) {
                   
try {
                       
out.close();
                    } catch (IOException e) {
                       
result = false ;
                   
}
                }
            }

            return result;
       
}

        private boolean getFocusedWindow(Socket client) {
           
boolean result = true ;
           
String focusName = null ;

           
BufferedWriter out = null ;
           
try {
               
OutputStream clientStream= client.getOutputStream();
                out = new BufferedWriter( new OutputStreamWriter(clientStream), 8 * 1024 );

               
View focusedWindow = null ;

               
mFocusLock .readLock().lock();
 
               try {
                   
focusedWindow = mFocusedWindow ;
               
} finally {
                   
mFocusLock .readLock().unlock();
               
}

                if (focusedWindow!= null ) {
                   
mWindowsLock .readLock().lock();
                   
try {
                       
focusName = mWindows .get( mFocusedWindow );
                   
} finally {
                       
mWindowsLock .readLock().unlock();
                   
}

                    out.write(Integer. toHexString(System. identityHashCode(focusedWindow)));
                    out.write( ' ' );
                   
out.append(focusName);
                }
                out.write( '\n' );
               
out.flush();
            } catch (Exception e) {
       
        result = false ;
           
} finally {
               
if (out!= null ) {
                   
try {
                       
out.close();
                    } catch (IOException e) {
                       
result = false ;
                   
}
                }
            }

            return result;
       
}

        public void windowsChanged() {
           
synchronized ( mLock ){
               
mNeedWindowListUpdate = true ;
               
mLock .notifyAll();
           
}
        }

         publicvoid focusChanged() {
           
synchronized ( mLock ){
               
mNeedFocusedWindowUpdate = true ;
               
mLock .notifyAll();
           
}
        }

        private boolean windowManagerAutolistLoop() {
           
addWindowListener( this );
           
BufferedWriter out = null ;
           
try {
               
out = new BufferedWriter( new OutputStreamWriter( mClient .getOutputStream()));
               
while (!Thread.interrupted()) {
                   
boolean needWindowListUpdate = false ;
                   
boolean needFocusedWindowUpdate = false ;
                   
synchronized ( mLock ){
                       
while (! mNeedWindowListUpdate && ! mNeedFocusedWindowUpdate ) {
                           
mLock .wait();
              
         }
                        if ( mNeedWindowListUpdate ) {
                           
mNeedWindowListUpdate = false ;
                           
needWindowListUpdate = true ;
                       
}
                        if ( mNeedFocusedWindowUpdate ) {
                           
mNeedFocusedWindowUpdate = false ;
                           
needFocusedWindowUpdate = true ;
                       
}
                    }
                    if (needWindowListUpdate){
                       
out.write( "LIST UPDATE\n" );
                       
out.flush();
                    }
                    if (needFocusedWindowUpdate){
                       
out.write( "FOCUS UPDATE\n" );
                       
out.flush();
                    }
                }
            } catch (Exception e) {
               
Log. w( LOG_TAG , "Connectionerror: " ,e);
           
} finally {
               
if (out!= null ) {
                   
try {
                       
out.close();
                    } catch (IOException e) {
                       
// Ignore
                   
}
               
}
                removeWindowListener( this );
           
}
            return true ;
       
}
    }

    private static class UncloseableOutputStream extends OutputStream {
 
       private final OutputStream mStream ;

       
UncloseableOutputStream(OutputStream stream) {
            mStream = stream;
       
}

        public void close() throws IOException {
           
// Don't close the stream
       
}

       
public boolean equals(Object o) {
           
return mStream .equals(o);
       
}

        public void flush() throws IOException {
           
mStream .flush();
       
}

        public int hashCode() {
           
return mStream .hashCode();
       
}

        public String toString() {
           
return mStream .toString();
       
}

        public void write( byte [] buffer, int offset, int count)
               
throws IOException {
           
mStream .write(buffer, offset, count);
       
}

        public void write( byte [] buffer) throws IOException {
           
mStream .write(buffer);
       
}

        public void write( int oneByte) throws IOException {
           
mStream .write(oneByte);
       
}
    }

    /**
    
* 一个空的ViewServer
    
*/
   
private static class NoopViewServer extends ViewServer {
       
private NoopViewServer() {
       
}

        @Override
       
public boolean start() throws IOException {
           
return false ;
       
}

        @Override
       
public boolean stop() {
        
    returnfalse ;
       
}

        @Override
       
public boolean isRunning() {
           
return false ;
       
}

        @Override
       
public void addWindow(Activity activity) {
       
}

        @Override
       
public void removeWindow(Activity activity) {
       
}

        @Override
       
public void addWindow(View view, String name) {
       
}

        @Override
       
public void removeWindow(View view) {
       
}

        @Override
       
public void setFocusedWindow(Activity activity) {
       
}

        @Override
       
public void setFocusedWindow(View view) {
       
}

        @Override
       
public void run() {
       
}
    }

}

参考:http://blog.csdn.net/kdsde/article/details/52984444


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值