mpython 直接访问_如何从python代码中直接访问Android的Service
在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?__cplusplus
extern?"C"?{
#endif
typedef?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
#endif
binder_wrap.cpp#include?
#include?
#include?
#include?
#include?
#include?
#include?
#include?
#include?"binder_wrap.h"
using?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?i=0;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_t
ctypedef?unsigned?int?uint32_t
cdef?extern?from?"Python.h":
ctypedef?short?Py_UNICODE
ctypedef?size_t?Py_ssize_t
object?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?=?data
o?=?PyUnicode_FromUnicode(str16,length)
arr.append(o)
def?listServices():
arr?=?[]
Py_INCREF(arr)
binder_listServices(visitor,arr)
Py_DECREF(arr)
return?arr
cdef?class?Binder:
cdef?void?*ptr
def?__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?ret
ret?=?binder_getInterfaceDescriptor(self.ptr,descriptor,sizeof(descriptor))
if?not?ret:
return?None
return?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?reply
cdef?class?Parcel:
cdef?void?*ptr
cdef?int?nativePtr
def?__cinit__(self,unsigned?int?nativePtr=0):?#,?sp[IBinder]?service):
self.nativePtr?=?nativePtr
if?not?nativePtr:
self.ptr?=?parcel_new()
else:
self.ptr?=?nativePtr
def?__dealloc__(self):
if?not?self.nativePtr:
parcel_destroy(self.ptr)
def?getNativePtr(self):
return?self.ptr
def?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?*un
cdef?int?size
if?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?ret
ret?=?parcel_readString16(self.ptr,str16,sizeof(str16))
if?not?ret:
return?None
return?PyUnicode_FromUnicode(str16,ret)
def?readByteArray(self):
return?self.createByteArray()
def?createByteArray(self):
length?=?self.readInt()
print?'createByteArray:',length
return?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?None
arr?=?[]
for?i?in?range(N):
if?self.readInt()?==?0:
continue
else:
result?=?creator.createFromParcel(self)
arr.append(result)
return?arr
@classmethod
def?obtain(cls):
return?Parcel()
@classmethod
def?recycle(cls):
pass
好,再來看看如何來實現訪問WifiService的功能:
WifiService.pyfrom?binder?import?Binder,Parcel
WIFI_SERVICE?=?"wifi";
DESCRIPTOR?=?"android.net.wifi.IWifiManager";
FIRST_CALL_TRANSACTION?=?1
TRANSACTION_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():
pass
def?addOrUpdateNetwork():
pass
def?removeNetwork():
pass
def?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()?!=?0
def?disableNetwork(netId):
_data?=?Parcel()
_reply?=?Parcel()
_data.writeInterfaceToken(DESCRIPTOR)
_data.writeInt32(netId)
mRemote.transact(TRANSACTION_disableNetwork,?_data,?_reply,?0)
_reply.readExceptionCode()
return?_reply.readInt32()?!=?0
def?pingSupplicant():
_data?=?Parcel()
_reply?=?Parcel()
_data.writeInterfaceToken(DESCRIPTOR)
mRemote.transact(TRANSACTION_pingSupplicant,?_data,?_reply,?0)
_reply.readExceptionCode()
return?_reply.readInt32()?!=?0
def?startScan(forceActive):
_data?=?Parcel()
_reply?=?Parcel()
ret?=?0
try:
_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?==?0
class?ScanResult:
def?__init__(self,ssid,bssid,caps,level,frequency,timestamp):
self.ssid?=?ssid
self.bssid?=?bssid
self.caps?=?caps
self.level?=?level
self.frequency?=?frequency
self.timestamp?=?timestamp
@classmethod
def?createFromParcel(cls,reply):
has_ssid?=?reply.readInt32()
ssid?=?None
if?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:',BSSID
print?'caps:',caps
print?'level:',level
print?'frequency:',frequency
print?'timestamp:',timestamp
return?ScanResult(ssid,BSSID,caps,level,frequency,timestamp)
def?getScanResults():
_data?=?Parcel.obtain()
_reply?=?Parcel.obtain()
_result?=?None
try:
_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?_result
def?disconnect():
return?transact(TRANSACTION_disconnect)?!=?0
def?reconnect():
return?transact(TRANSACTION_reconnect)?!=?0
def?reassociate():
return?transact(TRANSACTION_reassociate)?!=?0
"""
class?WifiInfo:
def?__init__():
pass
@classmethod
def?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()?!=?0
"""
def?getConnectionInfo():
pass
def?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)?!=?0
def?saveConfiguration():
pass
def?get_readable_address(addr):
return?"%d:%d:%d:%d"%(addr&0xff,(addr>>8)&0xff,(addr>>16)&0xff,(addr>>24)&0xff)
def?getDhcpInfo():
_data?=?Parcel()
_reply?=?Parcel()
_data.writeInterfaceToken(DESCRIPTOR)
mRemote.transact(TRANSACTION_getDhcpInfo,?_data,_reply,0)
_reply.readExceptionCode()
if?0?==?_reply.readInt32():
return?None
ipAddress?=?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"%info
return?info
def?acquireWifiLock():
pass
def?updateWifiLockWorkSource():
pass
def?releaseWifiLock():
pass
def?initializeMulticastFiltering():
pass
def?isMulticastEnabled():
pass
def?acquireMulticastLock():
pass
def?releaseMulticastLock():
pass
def?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():
pass
def?setWifiApConfiguration():
pass
def?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():
pass
def?getWifiStateMachineMessenger():
pass
def?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的功能,但是像startScan,getScanResults,setWifiEnabled,getWifiEnabledState,getDhcpInfo,setWifiApEnabled這些主要的接口已經實現了,其它接口沒有實現并非是因為不能實現,而是比較繁瑣,暫時未實現而己,后面會不斷的完善。
再來看下測試代碼:
test.pyimport?WifiService
WifiService.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?result
break
執行后將會打印出搜索到的Wifi信息。
另外就是代碼的編譯問題了。代碼必須在android的源代碼下進行編譯。我試過在ndk上進行編譯,經過一番努力,通過鏈接事先編譯好的C++ binder庫,也成功編譯通過,但是程序不能正常運行,這應該是預先編譯出來的庫和ndk的庫存在兼容性問題造成的,或許通過在ndk上編譯binder庫可以避免這個問題,但是目前還沒有作過嘗試。 但是編譯出來的代碼應該可以運行在各個不同的版本,我在4.0和4.2版本的設備上作了簡單的測試,事實證明在4.2上編譯的代碼可以在4.0上運行,但是考慮到android的諸多版本,各個版本多多少少有些兼容性問題,更詳細的還必須比較各個版本的binder代碼,并通過測試才能得到結果。
總結
以上是生活随笔為你收集整理的mpython 直接访问_如何从python代码中直接访问Android的Service的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: css响应式布局_用 CSS Grid
- 下一篇: java rpm包安装_rpm包安装ja