Python实现利用socket连接adb控制android设备

最近在搞利用socket连接adb控制android设备,主要问题在于socket client在与adb server建立连接后,在读写socket时就会发生10053错误,在github上面找到一个工程相当符合自己的需求,以最精简的方式重新做实现,终于搞定,值得庆贺


import socket


HOSTNAME= 'localhost'
PORT=5037
TIMEOUT=15
OKAY = 'OKAY'
FAIL = 'FAIL'
DEBUG = 1


class AdbClient:
    def __init__(self,hostname=HOSTNAME,port=PORT):
        if DEBUG:
            print "\t__init__."
        self.hostname = hostname
        self.port = port
        self.reconnect = False
        self._connect()
        #self.checkVersion(True)
        
        
    def _connect(self):
        if DEBUG:
            print "\t_connect()"
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.settimeout(TIMEOUT)
        try:
            self.socket.connect((self.hostname, self.port))
        except socket.error, ex:
            raise RuntimeError("ERROR: Connecting to %s:%d: %s.\nIs adb running on your computer?" % (self.socket, self.port, ex))
        if DEBUG:
            print "\t\t_connect success."
        
           
    def _send(self,msg,checkok,reconnect):
        if DEBUG:
            print "\t_send(%s, checkok=%s, reconnect=%s)" % (msg, checkok, reconnect)
        self.checkConnected()
        b = bytearray(msg, 'utf-8')
        self.socket.send('%04X%s' % (len(b), b))
        if checkok:
            self._checkOk()
        if reconnect:
            if DEBUG:
                print "\t\t__send: reconnecting"
            self._connect()
 

    def _receive(self, nob=None):
        if DEBUG:
            print "\t_receive()"
        self.checkConnected()
        if nob is None:
            nob = int(self.socket.recv(4), 16)
        if DEBUG:
            print "\t\t__receive: receiving", nob, "bytes"
        recv = bytearray()
        nr = 0
        while nr < nob:
            chunk = self.socket.recv(min((nob - nr), 4096))
            recv.extend(chunk)
            nr += len(chunk)
        if DEBUG:
            print "\t\t__receive: returning len=", len(recv)
        return str(recv)

    

    def _checkOk(self):
        if DEBUG:
            print "\t_checkOk()"
        self.checkConnected()
        recv = self.socket.recv(4)
        if DEBUG:
            print "\t\t_checkOk: recv=", repr(recv)
        try:
            if recv != OKAY:
                error = self.socket.recv(1024)
                raise RuntimeError("ERROR: %s %s" % (repr(recv), error))
        finally:
            if DEBUG:
                 print "\t\t_checkOk() return True"
            return True

    def setReconnect(self, val):
        self.reconnect = val

    def close(self):
        print "close()"
        if self.socket:
            self.socket.close()
        
 
    def checkConnected(self):
        if DEBUG:
            print "checkConnected()"
        if not self.socket:
            raise RuntimeError("ERROR: Not connected")
        if DEBUG:
            print "\tcheckConnected: returning True"
        return True

    def checkVersion(self, reconnect):
        if DEBUG:
            print "checkVersion(reconnect=%s)" % reconnect
        self._send('host:version',checkok=True,reconnect=False)
        version = self.socket.recv(8)
        if DEBUG:
            print "\t\tcheckVersion: recv=", repr(version)
        VERSION = '0004001f'
        if version != VERSION:
            raise RuntimeError("ERROR: Incorrect ADB server version %s (expecting %s)" % (version, VERSION))

    def resetDevice(self,name):
         if DEBUG:
            print  "resetDevice()"
         self._send('host:devices-l', checkok=False,reconnect=True)
         self._send('host:transport:%s'%name,True,False)
        
    
    def getDevices(self):
        if DEBUG:
            print  "getDevices()"
        self._send('host:devices-l', checkok=False,reconnect=True)

        ###
        #fixme:for select device
        self._send('host:transport:YT9109B4UV',True,False)
        device = Device()
        device.index = 0
        device.name = "YT9109B4UV"
        device.adbc = self
        return device

class Device:
    index = 0
    name = ""
    adbc = AdbClient()
    def getIndex(self):
        return self.mIndex
    
    def shell(self, cmd=None):
        if DEBUG:
            print "shell(cmd:%s)" % cmd
        self.adbc.resetDevice(self.name)
        if cmd:
            self.adbc._send('shell:%s' % cmd,checkok=True,reconnect=False)
            out = ''
            while True:
                _str = None
                try:
                    _str = self.adbc.socket.recv(4096)
                except Exception, ex:
                    print >> sys.stderr, "ERROR:", ex
                if not _str:
                    break
                out += _str
            if self.adbc.reconnect:
                print >> sys.stderr, "Reconnecting..."
                self.adbc.close()
                self.adbc._connect()
            return out
        else:
            self.adbc._send('shell:',checkok=True,reconnect=False)
            # sin = self.socket.makefile("rw")
            # sout = self.socket.makefile("r")
            # return (sin, sin)
            sout = self.adbc.socket.makefile("r")
            return sout

if __name__ == '__main__':
    adbClient = AdbClient()

    device = adbClient.getDevices()       
    device.shell('input text aa')

    device.shell("sendevent /dev/input/event8 0003 57 00000295");
    device.shell("sendevent /dev/input/event8 0003 53 00000013");
    device.shell("sendevent /dev/input/event8 0003 58 0000002b");
    device.shell("sendevent /dev/input/event8 0000 0000 00000000");
    device.shell("sendevent /dev/input/event8 0003 57 ffffffff");
    device.shell("sendevent /dev/input/event8 0000 0000 00000000");

    
    adbClient.close()

你可能感兴趣的:(跨平台相关,网络技术,问题解决)