视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Python手机开发调用DLL实现部分ADB功能
2020-11-27 14:28:31 责编:小采
文档


近期学了一点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模块。。

下载本文
显示全文
专题