android studio上HierarchyViewer的使用实例

来源:互联网 发布:3d雕塑软件 编辑:程序博客网 时间:2024/05/29 08:19

使用方法:

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

 

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

2<applicationandroid: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类(拷贝过去就可以):

packagecom.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 ViewServerimplements 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 StringBUILD_TYPE_USER ="user";

   
// Debug facility
   
private static final StringLOG_TAG ="ViewServer";

   
private static final StringVALUE_PROTOCOL_VERSION ="4";
   
private static final StringVALUE_SERVER_VERSION ="4";

   
// Protocol commands
   
// Returns the protocol version
   
private static final StringCOMMAND_PROTOCOL_VERSION ="PROTOCOL";
   
// Returns the server version
   
private static final StringCOMMAND_SERVER_VERSION ="SERVER";
   
// Lists all of the available windows in thesystem
   
private static final StringCOMMAND_WINDOW_MANAGER_LIST = "LIST";
   
// Keeps a connection open and notifies when thelist of windows changes
   
private static final StringCOMMAND_WINDOW_MANAGER_AUTOLIST = "AUTOLIST";
   
// Returns the focused window
   
private static final StringCOMMAND_WINDOW_MANAGER_GET_FOCUS = "GET_FOCUS";

   
private ServerSocketmServer;
   
private final int mPort;

   
private ThreadmThread;
   
private ExecutorServicemThreadPool;

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

   
private final HashMap<View, String>mWindows =newHashMap<View,String>();
   
private final ReentrantReadWriteLockmWindowsLock =newReentrantReadWriteLock();

   
private ViewmFocusedWindow;
   
private final ReentrantReadWriteLockmFocusLock =newReentrantReadWriteLock();

   
private static ViewServersServer;

   
/**
    
* 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 =newViewServer(ViewServer.VIEW_SERVER_DEFAULT_PORT);
           
}

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

        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(intport) {
       
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 =newThread(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 =newServerSocket(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(newViewServerWorker(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(newOutputStreamWriter(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 ViewServerWorkerimplements Runnable, WindowListener {
       
private SocketmClient;
       
private boolean mNeedWindowListUpdate;
       
private boolean mNeedFocusedWindowUpdate;

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

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

        public void run() {
           
BufferedReader in = null;
           
try {
               
in = new BufferedReader(newInputStreamReader(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(newOutputStreamWriter(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(inthashCode) {
           
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(newOutputStreamWriter(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(newOutputStreamWriter(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(newOutputStreamWriter(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 UncloseableOutputStreamextends OutputStream {
 
      private final OutputStreammStream;

       
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(intoneByte) throwsIOException {
           
mStream.write(oneByte);
       
}
    }

    /**
    
* 一个空的ViewServer
    
*/
   
private static class NoopViewServerextends 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


1 1