近期学了一点python,然后正好有一个手机同步工具方面的预研工作要完成。
要实现pc与手机的通信,首先要找到他们的通信协议,还好的是android有完善的协议:adb
adb的代码是开源的,而且支持windows平台,有现成的dll可以调用:adbwinapi.dll,adbwinusbapi.dll
好了,可以用vc搞定,但我想用python试一下,于是开始了苦逼的查资料+实验的过程。
实验过程就不多说了,由于上面的两个dll都是用c实现的,提供的头文件也是c语言的,所以有了下面这个python测试程序(python2.7):
import ctypes
#自定义的guid结构,有兴趣的可以自己研究用uuid模块
class guid(ctypes.structure):
_fields_ = [(“data1”, ctypes.c_ulong),
(“data2”, ctypes.c_ushort),
(“data3”, ctypes.c_ushort),
(“data4”, ctypes.c_ubyte*8)]
#自己定义的一个结构体,便于使用dll接口
class adbinterfaceinfo(ctypes.structure):
_fields_ = [(“class_id”, guid),
(“flags”, ctypes.c_ulong),
(“device_name”, ctypes.c_wchar*800)]
def strguid(guid):
string = ”
string = string + ‘%x’ % buff.class_id.data1 + ‘-%x’ % buff.class_id.data2 + ‘-%x’ %buff.class_id.data3
string = string + ‘-%x’ % buff.class_id.data4[0]
string = string + ‘%x’ % buff.class_id.data4[1]
string = string + ‘%x’ % buff.class_id.data4[2]
string = string + ‘%x’ % buff.class_id.data4[3]
string = string + ‘%x’ % buff.class_id.data4[4]
string = string + ‘%x’ % buff.class_id.data4[5]
string = string + ‘%x’ % buff.class_id.data4[6]
string = string + ‘%x’ % buff.class_id.data4[7]
return string
dll = ctypes.cdll.loadlibrary(‘adbwinapi.dll’)
usb_class_id = guid(0xf72fe0d4, 0xcbcb, 0x407d, (0x88, 0x14, 0x9e, 0xd6, 0x73, 0xd0, 0xdd, 0x6b))
enum_handle = dll.adbenuminterfaces(usb_class_id, ctypes.c_bool(‘true’), ctypes.c_bool(‘true’), ctypes.c_bool(‘true’))
while(1):
buff = adbinterfaceinfo()
size = ctypes.c_ulong(ctypes.sizeof(buff))
status = dll.adbnextinterface(enum_handle, ctypes.byref(buff), ctypes.byref(size))
if status==1:
#print “guid = ” + strguid(buff.class_id)
#print “status = ” + str(status)
#print “name = ” + str(buff.device_name)
hadbapi = dll.adbcreateinterfacebyname(buff.device_name);
if hadbapi == 0:
print ‘adbcreateinterfacebyname fail’
else:
serial = ‘ ‘*128
pserial = ctypes.c_char_p()
pserial.value = serial
serial_len = ctypes.c_ulong(len(serial))
ret = dll.adbgetserialnumber(hadbapi, pserial, ctypes.byref(serial_len), ctypes.c_bool(‘false’));
if ret == 1:
print ‘device name: ‘ + ‘%s’% serial
else:
print ‘get device name fail’
else:
print ‘finished’
break
import ctypes
#自定义的guid结构,有兴趣的可以自己研究用uuid模块
class guid(ctypes.structure):
_fields_ = [(“data1”, ctypes.c_ulong),
(“data2”, ctypes.c_ushort),
(“data3”, ctypes.c_ushort),
(“data4”, ctypes.c_ubyte*8)]
#自己定义的一个结构体,便于使用dll接口
class adbinterfaceinfo(ctypes.structure):
_fields_ = [(“class_id”, guid),
(“flags”, ctypes.c_ulong),
(“device_name”, ctypes.c_wchar*800)]
def strguid(guid):
string = ”
string = string + ‘%x’ % buff.class_id.data1 + ‘-%x’ % buff.class_id.data2 + ‘-%x’ %buff.class_id.data3
string = string + ‘-%x’ % buff.class_id.data4[0]
string = string + ‘%x’ % buff.class_id.data4[1]
string = string + ‘%x’ % buff.class_id.data4[2]
string = string + ‘%x’ % buff.class_id.data4[3]
string = string + ‘%x’ % buff.class_id.data4[4]
string = string + ‘%x’ % buff.class_id.data4[5]
string = string + ‘%x’ % buff.class_id.data4[6]
string = string + ‘%x’ % buff.class_id.data4[7]
return string
dll = ctypes.cdll.loadlibrary(‘adbwinapi.dll’)
usb_class_id = guid(0xf72fe0d4, 0xcbcb, 0x407d, (0x88, 0x14, 0x9e, 0xd6, 0x73, 0xd0, 0xdd, 0x6b))
enum_handle = dll.adbenuminterfaces(usb_class_id, ctypes.c_bool(‘true’), ctypes.c_bool(‘true’), ctypes.c_bool(‘true’))
while(1):
buff = adbinterfaceinfo()
size = ctypes.c_ulong(ctypes.sizeof(buff))
status = dll.adbnextinterface(enum_handle, ctypes.byref(buff), ctypes.byref(size))
if status==1:
#print “guid = ” + strguid(buff.class_id)
#print “status = ” + str(status)
#print “name = ” + str(buff.device_name)
hadbapi = dll.adbcreateinterfacebyname(buff.device_name);
if hadbapi == 0:
print ‘adbcreateinterfacebyname fail’
else:
serial = ‘ ‘*128
pserial = ctypes.c_char_p()
pserial.value = serial
serial_len = ctypes.c_ulong(len(serial))
ret = dll.adbgetserialnumber(hadbapi, pserial, ctypes.byref(serial_len), ctypes.c_bool(‘false’));
if ret == 1:
print ‘device name: ‘ + ‘%s’% serial
else:
print ‘get device name fail’
else:
print ‘finished’
break
上面这个简单的python代码,可以通过adbwinapi.dll和adbwinusbapi.dll这两个dll来找到你pc上正连接着的android设备。
只调用了3个dll接口,但目的已经达到,可以得出下面的结论:
使用python调用dll的方式来实现adb工具是可行的,当然麻烦是不会少的了。
写在最后,python调用c写的dll还是比较麻烦的,特别是参数传递,尤其是指针的处理,这方面还得依靠ctypes模块。。。