个人网站如何进行网络推广,跨境网站,上海 建设工程质量监督站网站,wordpress可视化模板编辑器在Kivy中#xff0c;通过pyjnius扩展可以间接调用Java代码#xff0c;而pyjnius利用的是Java的反射机制。但是在Python对象和Java对象中转来转去总让人感觉到十分别扭。好在android提供了binder这个进程间通信的功能#xff0c;Java中的Service也是基于Binder的C代码封装来实…在Kivy中通过pyjnius扩展可以间接调用Java代码而pyjnius利用的是Java的反射机制。但是在Python对象和Java对象中转来转去总让人感觉到十分别扭。好在android提供了binder这个进程间通信的功能Java中的Service也是基于Binder的C代码封装来实现进程间通信的这也为从Python代码中绕开pyjnius直接访问Java代码提供了可能既然Java的Service是基于C的封装来实现的也同样可以在Python中封装同样的C代码这篇文章讲解了如何通过binder在Python代码中直接访问Java的Service如WifiService。binder_wrap.h#ifndef BINDER_WRAP_H#define BINDER_WRAP_H#ifdef __cplusplusextern C {#endiftypedef int (*vector_visitor)(const char16_t* str16,int length,void *data);typedef int (*fnOnTransact)(uint32_t code,const void *data,void *reply,uint32_t flags,void *userData);int server_create(const char *name,const char *descriptor,fnOnTransact onTrans,void *data);void* binder_getbinder(const char *name);int binder_releasebinder(void* binder);int binder_listServices(vector_visitor visitor,void *data);int binder_getInterfaceDescriptor(void *binder,char16_t *descriptor,size_t size);int binder_transact(void* binder,int code,const void *data,void* reply,int flags);void* parcel_new();int parcel_destroy(void* parcel);int parcel_writeInterfaceToken(void* parcel,const char *interface);int parcel_writeInt32(void *parcel,int val);int parcel_writeCString(void *parcel,const char* str);int parcel_writeString16(void *parcel,const char16_t* str, size_t len);int parcel_readInt32(void *parcel);long parcel_readInt64(void *parcel);int parcel_readString16(void *parcel,char16_t* str, size_t len);int parcel_readInplace(void *parcel,void* data, int len);int parcel_readExceptionCode(void *parcel);int parcel_dataAvail(void *parcel);#ifdef __cplusplus}#endif#endifbinder_wrap.cpp#include #include #include #include #include #include #include #include #include binder_wrap.husing namespace android;void* binder_getbinder(const char *name){android::sp:iservicemanager sm android::defaultServiceManager();sp *binder new sp();do {*binder sm-getService(android::String16(name));if (binder ! 0){break;}usleep(500000); // 0.5 s} while(true);return reinterpret_cast(binder);}int binder_releasebinder(void* binder){sp *bp reinterpret_cast *(binder);if(bp 0){return 0;}delete bp;return 1;}//Vector listServices() 0;int binder_listServices(vector_visitor visitor,void *data){android::sp:iservicemanager sm android::defaultServiceManager();Vector list sm-listServices();for (int i0;i{visitor(list[i].string(),list[i].size(),data);}return list.size();}int binder_getInterfaceDescriptor(void *binder,char16_t *descriptor,size_t size){sp *bp reinterpret_cast *(binder);if(bp 0){return 0;}if (descriptor NULL || size 0){return 0;}String16 des (*bp)-getInterfaceDescriptor();if (size des.size()){size des.size();}memcpy(descriptor,des.string(),size*2);return size;}//int binder_transact(void* binder,int code,const Parcel data,Parcel* reply,int flags 0)int binder_transact(void* binder,int code,const void *data,void* reply,int flags){sp *bp reinterpret_cast *(binder);if(bp 0 || data 0 || reply 0){return 0;}return (*bp)-transact(code,*(Parcel*)data,(Parcel*)reply,flags);}void* parcel_new(){return (void*)new Parcel();}int parcel_destroy(void* parcel){if(parcel 0){return 0;}delete (Parcel*)parcel;return 1;}int parcel_writeInterfaceToken(void* parcel,const char *interface){Parcel *p reinterpret_cast(parcel);if(p 0){return 0;}return p-writeInterfaceToken(String16(interface));}int parcel_writeInt32(void *parcel,int val){Parcel *p reinterpret_cast(parcel);if(p 0){return 0;}return p-writeInt32(val);}int parcel_writeCString(void *parcel,const char* str){Parcel *p reinterpret_cast(parcel);if(p 0){return 0;}return p-writeCString(str);}int parcel_writeString16(void *parcel,const char16_t* str, size_t len){Parcel *p reinterpret_cast(parcel);if(p 0){return 0;}if (str 0 || len 0){return 0;}return p-writeString16(str,len);}int parcel_readInt32(void *parcel){Parcel *p reinterpret_cast(parcel);if(p 0){return 0;}return p-readInt32();}long parcel_readInt64(void *parcel){Parcel *p reinterpret_cast(parcel);if(p 0){return 0;}return p-readInt64();}int parcel_readString16(void *parcel,char16_t* str, size_t len){Parcel *p reinterpret_cast(parcel);if(p 0){return 0;}if (str NULL || len 0){return 0;}String16 str16 p-readString16();if (len str16.size()){len str16.size();}memcpy(str,str16.string(),len*2);return len;}int parcel_readExceptionCode(void *parcel){Parcel *p reinterpret_cast(parcel);if(p 0){return 0;}return p-readExceptionCode();}int parcel_readInplace(void *parcel,void* data, int len){Parcel *p reinterpret_cast(parcel);if(p 0){return 0;}if (len 0 len (int32_t)p-dataAvail()){const void *d p-readInplace(len);memcpy(data,d,len);return len;}return 0;}int parcel_dataAvail(void *parcel){Parcel *p reinterpret_cast(parcel);if(p 0){return 0;}return p-dataAvail();}正如代码中所示这里对C的IBinder和Parcel两个对象进行了封装而Java的Service的底层实现也正是对这两个类进行封装的结果具体的可以看frameworksbasecorejniandroid_util_Binder.cpp的代码再来看下如何在Python中使用这些代码这里用cython来封装这些C接口binder.pyxcdef extern from utils/Unicode.h:ctypedef short char16_tctypedef unsigned int uint32_tcdef extern from Python.h:ctypedef short Py_UNICODEctypedef size_t Py_ssize_tobject PyString_FromStringAndSize(const char *v, Py_ssize_t len)int PyString_AsStringAndSize(object obj, char **buffer, Py_ssize_t *length)object PyUnicode_FromUnicode(const Py_UNICODE *u, Py_ssize_t size)Py_UNICODE* PyUnicode_AS_UNICODE(object)Py_ssize_t PyUnicode_GetSize(object)void Py_INCREF(object)void Py_DECREF(object)cdef extern from binder_wrap.h:ctypedef int (*vector_visitor)(const char16_t* str16,int length,void *data)int binder_listServices(vector_visitor visitor,void *data)ctypedef int (*fnOnTransact)(uint32_t code,const void *data,void *reply,uint32_t flags,void *userData)int server_create(const char *name,const char *descriptor,fnOnTransact onTrans,void *data)void* binder_getbinder(const char *name)int binder_releasebinder(void* binder)int binder_getInterfaceDescriptor(void *binder,char16_t *descriptor,int size)int binder_transact(void* binder,int code,const void *data,void* reply,int flags)void* parcel_new()int parcel_destroy(void* parcel)int parcel_writeInterfaceToken(void* parcel,const char *interface)int parcel_writeInt32(void *parcel,int val)int parcel_writeCString(void *parcel,const char* str)int parcel_writeString16(void *parcel,const char16_t* str, size_t len)int parcel_readInt32(void *parcel)int parcel_readInt64(void *parcel)int parcel_readString16(void *parcel,char16_t* str, size_t len)int parcel_readExceptionCode(void *parcel)int parcel_readInplace(void *parcel,void* data, int len)int parcel_dataAvail(void *parcel)cdef int visitor(const char16_t* str16,int length,void *data):arr datao PyUnicode_FromUnicode(str16,length)arr.append(o)def listServices():arr []Py_INCREF(arr)binder_listServices(visitor,arr)Py_DECREF(arr)return arrcdef class Binder:cdef void *ptrdef __cinit__(self,char *name): #, sp[IBinder] service):self.ptr binder_getbinder(name)def __dealloc__(self):binder_releasebinder(self.ptr)def getInterfaceDescriptor(self):cdef char16_t descriptor[256]cdef int retret binder_getInterfaceDescriptor(self.ptr,descriptor,sizeof(descriptor))if not ret:return Nonereturn PyUnicode_FromUnicode(descriptor,ret)def transact(self,int code,data,reply,int flags):cdef int dataPtr data.getNativePtr()cdef int replyPtr reply.getNativePtr()binder_transact(self.ptr,code,dataPtr,replyPtr,flags)return replycdef class Parcel:cdef void *ptrcdef int nativePtrdef __cinit__(self,unsigned int nativePtr0): #, sp[IBinder] service):self.nativePtr nativePtrif not nativePtr:self.ptr parcel_new()else:self.ptr nativePtrdef __dealloc__(self):if not self.nativePtr:parcel_destroy(self.ptr)def getNativePtr(self):return self.ptrdef writeInterfaceToken(self,const char *interface):return parcel_writeInterfaceToken(self.ptr,interface)def writeInt(self,int val):self.writeInt32(val)def writeInt32(self,int val):return parcel_writeInt32(self.ptr,val)def writeCString(self,const char* cstr):return parcel_writeCString(self.ptr,cstr)def writeString16(self,ustr):cdef char16_t *uncdef int sizeif isinstance(ustr,unicode):un PyUnicode_AS_UNICODE(ustr)size PyUnicode_GetSize(ustr)return parcel_writeString16(self.ptr,un,size)def readInt32(self):return parcel_readInt32(self.ptr)def readInt(self):return self.readInt32()def readInt64(self):return parcel_readInt64(self.ptr)def readExceptionCode(self):return parcel_readExceptionCode(self.ptr)def readString16(self):cdef char16_t str16[256]cdef int retret parcel_readString16(self.ptr,str16,sizeof(str16))if not ret:return Nonereturn PyUnicode_FromUnicode(str16,ret)def readByteArray(self):return self.createByteArray()def createByteArray(self):length self.readInt()print createByteArray:,lengthreturn self.readInplace(length)# int parcel_readInplace(void *parcel,void* data, size_t len)def readInplace(self,length):cdef char arr[512]ret parcel_readInplace(self.ptr,arr,length)if ret length:return PyString_FromStringAndSize(arr,length)else:return None# int parcel_dataAvail(void *parcel)def dataAvail(self):return parcel_dataAvail(self.ptr)def createTypedArrayList(self,creator):N self.readInt()if N 0:return Nonearr []for i in range(N):if self.readInt() 0:continueelse:result creator.createFromParcel(self)arr.append(result)return arrclassmethoddef obtain(cls):return Parcel()classmethoddef recycle(cls):pass好再来看看如何来实现访问WifiService的功能WifiService.pyfrom binder import Binder,ParcelWIFI_SERVICE wifi;DESCRIPTOR android.net.wifi.IWifiManager;FIRST_CALL_TRANSACTION 1TRANSACTION_getConfiguredNetworks (FIRST_CALL_TRANSACTION 0);TRANSACTION_addOrUpdateNetwork (FIRST_CALL_TRANSACTION 1);TRANSACTION_removeNetwork (FIRST_CALL_TRANSACTION 2);TRANSACTION_enableNetwork (FIRST_CALL_TRANSACTION 3);TRANSACTION_disableNetwork (FIRST_CALL_TRANSACTION 4);TRANSACTION_pingSupplicant (FIRST_CALL_TRANSACTION 5);TRANSACTION_startScan (FIRST_CALL_TRANSACTION 6);TRANSACTION_getScanResults (FIRST_CALL_TRANSACTION 7);TRANSACTION_disconnect (FIRST_CALL_TRANSACTION 8);TRANSACTION_reconnect (FIRST_CALL_TRANSACTION 9);TRANSACTION_reassociate (FIRST_CALL_TRANSACTION 10);TRANSACTION_getConnectionInfo (FIRST_CALL_TRANSACTION 11);TRANSACTION_setWifiEnabled (FIRST_CALL_TRANSACTION 12);TRANSACTION_getWifiEnabledState (FIRST_CALL_TRANSACTION 13);TRANSACTION_setCountryCode (FIRST_CALL_TRANSACTION 14);TRANSACTION_setFrequencyBand (FIRST_CALL_TRANSACTION 15);TRANSACTION_getFrequencyBand (FIRST_CALL_TRANSACTION 16);TRANSACTION_isDualBandSupported (FIRST_CALL_TRANSACTION 17);TRANSACTION_saveConfiguration (FIRST_CALL_TRANSACTION 18);TRANSACTION_getDhcpInfo (FIRST_CALL_TRANSACTION 19);TRANSACTION_acquireWifiLock (FIRST_CALL_TRANSACTION 20);TRANSACTION_updateWifiLockWorkSource (FIRST_CALL_TRANSACTION 21);TRANSACTION_releaseWifiLock (FIRST_CALL_TRANSACTION 22);TRANSACTION_initializeMulticastFiltering (FIRST_CALL_TRANSACTION 23);TRANSACTION_isMulticastEnabled (FIRST_CALL_TRANSACTION 24);TRANSACTION_acquireMulticastLock (FIRST_CALL_TRANSACTION 25);TRANSACTION_releaseMulticastLock (FIRST_CALL_TRANSACTION 26);TRANSACTION_setWifiApEnabled (FIRST_CALL_TRANSACTION 27);TRANSACTION_getWifiApEnabledState (FIRST_CALL_TRANSACTION 28);TRANSACTION_getWifiApConfiguration (FIRST_CALL_TRANSACTION 29);TRANSACTION_setWifiApConfiguration (FIRST_CALL_TRANSACTION 30);TRANSACTION_startWifi (FIRST_CALL_TRANSACTION 31);TRANSACTION_stopWifi (FIRST_CALL_TRANSACTION 32);TRANSACTION_addToBlacklist (FIRST_CALL_TRANSACTION 33);TRANSACTION_clearBlacklist (FIRST_CALL_TRANSACTION 34);TRANSACTION_getWifiServiceMessenger (FIRST_CALL_TRANSACTION 35);TRANSACTION_getWifiStateMachineMessenger (FIRST_CALL_TRANSACTION 36);TRANSACTION_getConfigFile (FIRST_CALL_TRANSACTION 37);TRANSACTION_captivePortalCheckComplete (FIRST_CALL_TRANSACTION 38);mRemote Binder(WIFI_SERVICE)def transact(TRANSACTION):_data Parcel()_reply Parcel()_data.writeInterfaceToken(DESCRIPTOR)mRemote.transact(TRANSACTION, _data, _reply, 0)_reply.readExceptionCode()return _reply.readInt32()def getConfiguredNetworks():passdef addOrUpdateNetwork():passdef removeNetwork():passdef enableNetwork(netId,disableOthers):_data Parcel()_reply Parcel()_data.writeInterfaceToken(DESCRIPTOR)_data.writeInt32(netId)if disableOthers:_data.writeInt32(1)else:_data.writeInt32(0)mRemote.transact(TRANSACTION_enableNetwork, _data, _reply, 0)_reply.readExceptionCode()return _reply.readInt32() ! 0def disableNetwork(netId):_data Parcel()_reply Parcel()_data.writeInterfaceToken(DESCRIPTOR)_data.writeInt32(netId)mRemote.transact(TRANSACTION_disableNetwork, _data, _reply, 0)_reply.readExceptionCode()return _reply.readInt32() ! 0def pingSupplicant():_data Parcel()_reply Parcel()_data.writeInterfaceToken(DESCRIPTOR)mRemote.transact(TRANSACTION_pingSupplicant, _data, _reply, 0)_reply.readExceptionCode()return _reply.readInt32() ! 0def startScan(forceActive):_data Parcel()_reply Parcel()ret 0try:_data.writeInterfaceToken(DESCRIPTOR)if forceActive:_data.writeInt(1)else:_data.writeInt(0)mRemote.transact(TRANSACTION_startScan, _data, _reply, 0)ret _reply.readExceptionCode()finally:_reply.recycle()_data.recycle()return ret 0class ScanResult:def __init__(self,ssid,bssid,caps,level,frequency,timestamp):self.ssid ssidself.bssid bssidself.caps capsself.level levelself.frequency frequencyself.timestamp timestampclassmethoddef createFromParcel(cls,reply):has_ssid reply.readInt32()ssid Noneif has_ssid:ssid_lengt reply.readInt()ssid reply.readByteArray()BSSID reply.readString16()caps reply.readString16()level reply.readInt()frequency reply.readInt()timestamp reply.readInt64()print BSSID:,BSSIDprint caps:,capsprint level:,levelprint frequency:,frequencyprint timestamp:,timestampreturn ScanResult(ssid,BSSID,caps,level,frequency,timestamp)def getScanResults():_data Parcel.obtain()_reply Parcel.obtain()_result Nonetry:_data.writeInterfaceToken(DESCRIPTOR)mRemote.transact(TRANSACTION_getScanResults, _data, _reply, 0)if 0 ! _reply.readExceptionCode():return None_result _reply.createTypedArrayList(ScanResult)finally:_reply.recycle()_data.recycle()return _resultdef disconnect():return transact(TRANSACTION_disconnect) ! 0def reconnect():return transact(TRANSACTION_reconnect) ! 0def reassociate():return transact(TRANSACTION_reassociate) ! 0class WifiInfo:def __init__():passclassmethoddef createFromParcel(cls,r):info WifiInfo();info.networkId r.readInt32()info.rssi r.readInt32()info.linkSpeed r.readInt32()if r.readByte() 1:info.setInetAddress(InetAddress.getByAddress(in.createByteArray()))if r.readInt() 1:info.mWifiSsid WifiSsid.CREATOR.createFromParcel(r)info.mBSSID r.readString16()info.mMacAddress r.readString16()info.mMeteredHint r.readInt32() ! 0def getConnectionInfo():passdef setWifiEnabled(enable):_data Parcel()_reply Parcel()_data.writeInterfaceToken(DESCRIPTOR)if enable:_data.writeInt32(1)else:_data.writeInt32(0)mRemote.transact(TRANSACTION_setWifiEnabled, _data,_reply,0)_reply.readExceptionCode()_result (0!_reply.readInt32())return _result;def getWifiEnabledState():return transact(TRANSACTION_getWifiEnabledState)def setCountryCode(country,persist):_data Parcel()_reply Parcel()_data.writeInterfaceToken(DESCRIPTOR)if isinstance(country,str):country unicode(contry)_data.writeString16(country)if persist:_data.writeInt32(1)else:_data.writeInt32(0)mRemote.transact(TRANSACTION_setCountryCode, _data,_reply,0)_reply.readExceptionCode()_result (0!_reply.readInt32())return _result;def setFrequencyBand(band, persist):_data Parcel()_reply Parcel()_data.writeInterfaceToken(DESCRIPTOR)if isinstance(country,str):country unicode(contry)_data.writeInt32(band)if persist:_data.writeInt32(1)else:_data.writeInt32(0)mRemote.transact(TRANSACTION_setFrequencyBand, _data,_reply,0)_reply.readExceptionCode()_result (0!_reply.readInt32())return _result;def getFrequencyBand():return transact(TRANSACTION_getFrequencyBand)def isDualBandSupported():return transact(TRANSACTION_isDualBandSupported) ! 0def saveConfiguration():passdef get_readable_address(addr):return %d:%d:%d:%d%(addr0xff,(addr8)0xff,(addr16)0xff,(addr24)0xff)def getDhcpInfo():_data Parcel()_reply Parcel()_data.writeInterfaceToken(DESCRIPTOR)mRemote.transact(TRANSACTION_getDhcpInfo, _data,_reply,0)_reply.readExceptionCode()if 0 _reply.readInt32():return NoneipAddress get_readable_address(reply.readInt32());gateway get_readable_address(reply.readInt32());netmask get_readable_address(reply.readInt32());dns1 get_readable_address(reply.readInt32());dns2 get_readable_address(reply.readInt32());serverAddress get_readable_address(reply.readInt32());leaseDuration get_readable_address(reply.readInt32());info (ipAddress,gateway,netmask,dns1,dns2,serverAddress,leaseDuration)print ipAddress %s,ngateway %s,nnetmask %s,ndns1 %s,ndns2 %s,nserverAddress %s,nleaseDuration %s%inforeturn infodef acquireWifiLock():passdef updateWifiLockWorkSource():passdef releaseWifiLock():passdef initializeMulticastFiltering():passdef isMulticastEnabled():passdef acquireMulticastLock():passdef releaseMulticastLock():passdef setWifiApEnabled(wifiConfig,enable):_data Parcel()_reply Parcel()_data.writeInterfaceToken(DESCRIPTOR)if wifiConfig:_data.writeInt32(1)wifiConfig.writeToParcel(_data)else:_data.writeInt32(0)if enable:_data.writeInt32(1)else:_data.writeInt32(0)mRemote.transact(TRANSACTION_setWifiApEnabled, _data,_reply,0)_reply.readExceptionCode()def getWifiApEnabledState():return transact(TRANSACTION_getWifiApEnabledState)def getWifiApConfiguration():passdef setWifiApConfiguration():passdef startWifi():return transact(TRANSACTION_startWifi)def stopWifi():return transact(TRANSACTION_stopWifi)def addToBlacklist(bssid):_data Parcel()_reply Parcel()_data.writeInterfaceToken(DESCRIPTOR)if isinstance(bssid,str):bssid unicode(bssid)_data.writeString16(bssid)mRemote.transact(TRANSACTION_addToBlacklist, _data,_reply,0)_reply.readExceptionCode()def clearBlacklist():return transact(TRANSACTION_clearBlacklist)def getWifiServiceMessenger():passdef getWifiStateMachineMessenger():passdef getConfigFile():_data Parcel()_reply Parcel()_data.writeInterfaceToken(DESCRIPTOR)mRemote.transact(TRANSACTION_getConfigFile, _data,_reply,0)_reply.readExceptionCode()return _reply.readString16()def captivePortalCheckComplete():return transact(TRANSACTION_captivePortalCheckComplete) ! 0目前并没有实现所有的WifiService的功能但是像startScangetScanResults,setWifiEnabled,getWifiEnabledState,getDhcpInfo,setWifiApEnabled这些主要的接口已经实现了其它接口没有实现并非是因为不能实现而是比较繁琐暂时未实现而己后面会不断的完善。再来看下测试代码test.pyimport WifiServiceWifiService.setWifiEnabled(True)WifiService.startScan(True)print WifiService.pingSupplicant()print WifiService.getConfigFile()for i in range(10):time.sleep(1.0)result WifiService.getScanResults()if result:print resultbreak执行后将会打印出搜索到的Wifi信息。另外就是代码的编译问题了。代码必须在android的源代码下进行编译。我试过在ndk上进行编译经过一番努力通过链接事先编译好的C binder库也成功编译通过但是程序不能正常运行这应该是预先编译出来的库和ndk的库存在兼容性问题造成的或许通过在ndk上编译binder库可以避免这个问题但是目前还没有作过尝试。 但是编译出来的代码应该可以运行在各个不同的版本我在4.0和4.2版本的设备上作了简单的测试事实证明在4.2上编译的代码可以在4.0上运行但是考虑到android的诸多版本各个版本多多少少有些兼容性问题更详细的还必须比较各个版本的binder代码并通过测试才能得到结果。