前几天研究截屏,查看ddmlib源码,发现adb通信是通过socket完成的,通过流传输可以提高效率。

adb 命令:adb forward,可以创建socket,官方解释如下

Forwarding Ports

You can use the forwardcommand to set up arbitrary port forwarding — forwarding of requests ona specific host port to a different port on an emulator/deviceinstance. Here's how you would set up forwarding of host port 6100 toemulator/device port 7100:

adb forward tcp:6100 tcp:7100
我的理解就是pc机端口127.0.0.1:6100映射到Android设备的7100端口。
模型图
我以PC为客户端,Android设备为服务端写个例子。
PC端口为1352,Android设备端口为2235,这是我的电话号码前几位。
Android服务端:
写一个监听2235端口的服务
首先添加权限
Java代码
服务端监听连接,连接后发一个ack "you connect me"给pc客户端,等待用户发过来的消息。
   protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_test);        try {            mServerSocket = new ServerSocket(2235);        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }        protected void onDestroy()    {        bRun = false;    }        public void onClick(View vt)    {        Log.i(TAG, "start listen socket accept");        acceptThread();    }        private void acceptThread(){        if (bRun)            return;                bRun = true;        Runnable r = new Runnable() {                        @Override            public void run() {                                // TODO Auto-generated method stub                while(bRun) {                    Socket sock = accept();                    if (sock != null) {                        Log.i(TAG, "sock is not null ptr:" + sock.getPort() + " is connect");                        new SocketChild(sock).start();                                            } else {                        //Log.i(TAG, "sock is null");                    }                    try {                        Thread.sleep(100);                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }            }        };        new Thread(r).start();    }        private Socket accept() {        Socket sock = null;        try {            sock = mServerSocket.accept();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return sock;    }    public class SocketChild extends Thread{        private Socket mSocket;        public  SocketChild(Socket sock) {            // TODO Auto-generated constructor stub            mSocket = sock;            ack("you connect me");                }                private void ack(String ack) {            try {                mSocket.getOutputStream().write(ack.getBytes());            } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }                @Override        public void run() {            while(bRun) {                try {                    sleep(100);                    read();                } catch (InterruptedException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                } catch (IOException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }            try {                mSocket.close();            } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }                private void read() throws IOException {            InputStream input;            byte [] buffer = new byte[1024];            input = mSocket.getInputStream();            int len = input.read(buffer, 0, 1024);            Log.i(TAG, new String(buffer).substring(0, len));        }    }

PC端
准备条件:
1、配置好adb环境
2、使用TCP调试工具
建立连接,在PC端CMD输入:adb forward tcp:1352 tcp:2235
代开TCP调试工具,连接1352端口,发送"hello world",得到Android设备回传的"you connect me".
   
再看Android服务端
我这边偷懒,直接用Locat打印Android服务端显示
这就完成了一个完整的连接,发送,应答的过程。
通过这个命令可以引申很多东西,如果你想使用screencap -p持续生成图像,再使用adb pull导出来,一次过程也得几秒,使用这种流的方式就高效多了,可以参考/system/core/adb/framebuffer_service.c的方式把图像数据导出来,这样就可以保证图像的流畅度。framebuffer_service.c 执行screencap获取原始的图像数据,再写到socket。
以下是framebuffer_service.c的参考代码:
void framebuffer_service(int fd, void *cookie){    struct fbinfo fbinfo;    unsigned int i;    char buf[640];    int fd_screencap;    int w, h, f;    int fds[2];    if (pipe(fds) < 0) goto done;    pid_t pid = fork();    if (pid < 0) goto done;    if (pid == 0) {        dup2(fds[1], STDOUT_FILENO);        close(fds[0]);        close(fds[1]);        const char* command = "screencap";        const char *args[2] = {command, NULL};        execvp(command, (char**)args);        exit(1);    }    fd_screencap = fds[0];    /* read w, h & format */    if(readx(fd_screencap, &w, 4)) goto done;    if(readx(fd_screencap, &h, 4)) goto done;    if(readx(fd_screencap, &f, 4)) goto done;    fbinfo.version = DDMS_RAWIMAGE_VERSION;    /* see hardware/hardware.h */    switch (f) {        case 1: /* RGBA_8888 */            fbinfo.bpp = 32;            fbinfo.size = w * h * 4;            fbinfo.width = w;            fbinfo.height = h;            fbinfo.red_offset = 0;            fbinfo.red_length = 8;            fbinfo.green_offset = 8;            fbinfo.green_length = 8;            fbinfo.blue_offset = 16;            fbinfo.blue_length = 8;            fbinfo.alpha_offset = 24;            fbinfo.alpha_length = 8;            break;        case 2: /* RGBX_8888 */             ......        default:            goto done;    }    /* write header */    if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done;    /* write data */    for(i = 0; i < fbinfo.size; i += sizeof(buf)) {      if(readx(fd_screencap, buf, sizeof(buf))) goto done;      if(writex(fd, buf, sizeof(buf))) goto done;    }    if(readx(fd_screencap, buf, fbinfo.size % sizeof(buf))) goto done;    if(writex(fd, buf, fbinfo.size % sizeof(buf))) goto done;done:    TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0));    close(fds[0]);    close(fds[1]);    close(fd);}

有耐心的朋友可以看看adb源码、ddmlib源码
adb源码:android源码内/system/core/adb
ddmlib源码:http://www.boyunjian.com/javasrc/com.google.android.tools/ddmlib/r13/_/com/android/ddmlib/

更多相关文章

  1. Android(安卓)-- Camera源码简析,启动流程
  2. Android中如何自己制作su
  3. Android(安卓)sdk manager更新 下载API源码
  4. Android(安卓)DLNA
  5. android 4.1源码下载方法
  6. eclipse上调试android里的程序。
  7. Android中 LED 系统架构
  8. [Android]Toolbar使用详解(三)——源码解析
  9. 用adb抓取log

随机推荐

  1. Android 实现图片轮播的三种方法
  2. android休眠运行
  3. Intent Server Environment
  4. android中获取SHA1的代码
  5. android 网络
  6. Android中声音处理流程
  7. android中重写onTouchEvent分别实现点击
  8. android渲染网页时onPageFinished不触发
  9. Android 自定义View 横向翻页
  10. Android圆环形自定义进度条控件的绘制