在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 <sys/types.h>
#include <unistd.h>
#include <grp.h> #include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h> #include <binder/Parcel.h> #include "binder_wrap.h" using namespace android; void* binder_getbinder(const char *name)
{
android::sp<android::IServiceManager> sm = android::defaultServiceManager();
sp<IBinder> *binder = new sp<IBinder>();
do {
*binder = sm->getService(android::String16(name));
if (binder != 0)
{
break;
}
usleep(500000); // 0.5 s
} while(true);
return reinterpret_cast<void *>(binder);
} int binder_releasebinder(void* binder)
{
sp<IBinder> *bp = reinterpret_cast<sp<IBinder> *>(binder); if(bp == 0)
{
return 0;
} delete bp; return 1;
} //Vector<String16> listServices() = 0;
int binder_listServices(vector_visitor visitor,void *data)
{
android::sp<android::IServiceManager> sm = android::defaultServiceManager(); Vector<String16> list = sm->listServices(); for (int i=0;i<list.size();i++)
{
visitor(list[i].string(),list[i].size(),data);
} return list.size();
} int binder_getInterfaceDescriptor(void *binder,char16_t *descriptor,size_t size)
{
sp<IBinder> *bp = reinterpret_cast<sp<IBinder> *>(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<IBinder> *bp = reinterpret_cast<sp<IBinder> *>(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 *>(parcel); if(p == 0)
{
return 0;
}
return p->writeInterfaceToken(String16(interface));
} int parcel_writeInt32(void *parcel,int val)
{
Parcel *p = reinterpret_cast<Parcel *>(parcel); if(p == 0)
{
return 0;
} return p->writeInt32(val);
} int parcel_writeCString(void *parcel,const char* str)
{
Parcel *p = reinterpret_cast<Parcel *>(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 *>(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 *>(parcel); if(p == 0)
{
return 0;
}
return p->readInt32();
} long parcel_readInt64(void *parcel)
{
Parcel *p = reinterpret_cast<Parcel *>(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 *>(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 *>(parcel); if(p == 0)
{
return 0;
}
return p->readExceptionCode();
} int parcel_readInplace(void *parcel,void* data, int len)
{
Parcel *p = reinterpret_cast<Parcel *>(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 *>(parcel); if(p == 0)
{
return 0;
} return p->dataAvail(); }

正如代码中所看到的,这里对C++的IBinder和Parcel两个对象进行了封装,而Java的Service的底层实现也正是对这两个类进行封装的结果,详细的能够看

frameworks\base\core\jni\android_util_Binder.cpp

的代码。

再来看下怎样在Python中使用这些代码,这里用cython来封装这些C接口:

binder.pyx

cdef 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 = <object>data
o = PyUnicode_FromUnicode(<Py_UNICODE*>str16,length)
arr.append(o) def listServices():
arr = []
Py_INCREF(arr)
binder_listServices(visitor,<void *>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(<Py_UNICODE*>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,<void *>dataPtr,<void*>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 = <void *>nativePtr def __dealloc__(self):
if not self.nativePtr:
parcel_destroy(self.ptr) def getNativePtr(self):
return <int>self.ptr def writeInterfaceToken(self,const char *interface):
return parcel_writeInterfaceToken(<void *>self.ptr,interface) def writeInt(self,int val):
self.writeInt32(val)
def writeInt32(self,int val):
return parcel_writeInt32(<void *>self.ptr,val) def writeCString(self,const char* cstr):
return parcel_writeCString(<void *>self.ptr,cstr) def writeString16(self,ustr):
cdef char16_t *un
cdef int size
if isinstance(ustr,unicode):
un = <char16_t*>PyUnicode_AS_UNICODE(ustr)
size = PyUnicode_GetSize(ustr)
return parcel_writeString16(<void *>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(<Py_UNICODE*>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.py

from 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.py

import 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代码。并通过測试才干得到结果。

Kivy A to Z -- 怎样从python代码中直接訪问Android的Service的更多相关文章

  1. pycharm运行Pytest,有没有将Pytest写入Python代码中的区别

    初学pytest. 将pytest写进Python代码中 不同运行方式都可正常运行     =======================**********************========= ...

  2. python代码中判断版本

    在python代码中判断python版本: if sys.version_info < (3, 0): lib.make_flows.argtypes = [c_char_p, c_char_p ...

  3. 怎样从C++代码直接訪问android framework层的WifiService

    说究竟,Java层的service就是就C++层的binder的封装.所以从原理上来讲通过C++代码直接訪问android framework层的service是全然可能的,这篇文章以訪问WifiSe ...

  4. 如何在创建hive表格的python代码中导入外部文件

    业务场景大概是这样的,我要对用户博文进行分词(这个步骤可以看这篇文章如何在hive调用python的时候使用第三方不存在的库-how to use external python library in ...

  5. Python 面试中可能会被问到的30个问题

    第一家公司问的题目 1 简述解释型和编译型编程语言? 解释型语言编写的程序不需要编译,在执行的时候,专门有一个解释器能够将VB语言翻译成机器语言,每个语句都是执行的时候才翻译.这样解释型语言每执行一次 ...

  6. Python代码中func(*args, **kwargs)

    这是Python函数可变参数 args及kwargs *args表示任何多个无名参数,它是一个tuple **kwargs表示关键字参数,它是一个dict 测试代码如下: def foo(*args, ...

  7. python代码中pass的用法

    我们有时会在方法中写一些注释代码,用来提示这个方法是干嘛的之类,看下面代码: class Game_object: def __init__(self, name): self.name = name ...

  8. 解决python代码中含有中文报错

    python中写入中文时报错如下图所示: 依照网上解决方法:在py文件中加入:#encoding=utf-8 然后继续报错如下图所示: 解决方法: 在py文件中加入: import sysreload ...

  9. 生成.m文件的python代码中出现的错误

    错误代码 import tempfile import subprocess import shlex import os import numpy as np import scipy.io scr ...

随机推荐

  1. Jmeter 日志设置---如何设置java协议中被测jar的日志?

    先转载一下Jmeter的日志设置: Jmeter运行出现问题可以通过调整jmeter的日志级别定位问题,但运行测试时建议关闭jmeter日志,jmeter打印日志耗费系统性能. Jmeter日志默认存 ...

  2. [TSP+floyd]POJ3311 Hie with the Pie

    题意: 给i到j花费的地图 1到n编号   一个人要从1遍历n个城市后回到1 求最小的花费(可以重复走) 分析 http://www.cnblogs.com/Empress/p/4039240.htm ...

  3. JNI 多线程

    一.概述 JNI编程和Linux上的C/C++编程还是挺相似的,每次java调用JNI中的函数时都会传入有关JVM的一些参数(如JNIEnv,jobject),每次JNI回调java中的方法时都要通过 ...

  4. linux多线程驱动中调用udelay()对整个系统造成的影响(by liukun321咕唧咕唧)

    以前没考虑过这个问题,而且之前可能运气比较好,虽然用了udelay但也没出什么奇怪的问题,今天在 CSDN上看到了一篇关于此问题帖子,觉得很受用,再此做简要的记录和分析: 驱动开的是内核线程 跟普通进 ...

  5. WPF——控件之间的绑定

    一.启动窗口 二.控件绑定(注意看光标的位置,一个是单向绑定,一个是双向绑定) 注意看单向绑定与双向绑定的绑定方法:

  6. Samba ‘dcerpc_read_ncacn_packet_done’函数缓冲区溢出漏洞

    漏洞名称: Samba ‘dcerpc_read_ncacn_packet_done’函数缓冲区溢出漏洞 CNNVD编号: CNNVD-201312-169 发布时间: 2013-12-12 更新时间 ...

  7. [light oj 1013] Love Calculator

    1013 - Love Calculator Yes, you are developing a 'Love calculator'. The software would be quite comp ...

  8. OpenXml操作Word的一些操作总结.无word组件生成word.

    OpenXml相对于用MS提供的COM组件来生成WORD,有如下优势: 1.相对于MS 的COM组件,因为版本带来的不兼容问题,及各种会生成WORD半途会崩溃的问题. 2.对比填满一张30多页的WOR ...

  9. CLR via C# 读书笔记 6-2 不同AppDomain之间的通信 z

    跨AppDomain通信有两种方式 1.Marshal By reference : 传递引用 2.Marshal By Value : 把需要传递的对象 通过序列化反序列化的方式传递过去(值拷贝) ...

  10. 016专家视图测试脚本开发_utility对象

    utility对象(1)这个例子是:Extendtest使用Extend对象加载DLL,我们可以使用它来丰富windows api函数,能够编写更为强大和灵活的测试代码 实例代码: '声明FindWi ...