최근에 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 도구를 구현하는 것이 가능합니다. 물론 문제는 덜할 것입니다.
마지막에 작성했는데, C로 작성된 DLL을 Python이 호출하는 것은 꽤 번거로운 일입니다. 특히 매개변수 전달, 특히 ctypes 모듈이 필요한 포인터 처리는 더욱 그렇습니다. . .