在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#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_tcdef 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 arrcdef 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 replycdef 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,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 = 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 == 0class 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 _resultdef disconnect():    return transact(TRANSACTION_disconnect) != 0def reconnect():    return transact(TRANSACTION_reconnect) != 0def 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():    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"%(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():    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的功能,但是像startScan,getScanResults,setWifiEnabled,getWifiEnabledState,getDhcpInfo,setWifiApEnabled这些主要的接口已经实现了,其它接口没有实现并非是因为不能实现,而是比较繁琐,暂时未实现而己,后面会不断的完善。


再来看下测试代码:

test.py

import 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 result        break

执行后将会打印出搜索到的Wifi信息。


另外就是代码的编译问题了。代码必须在android的源代码下进行编译。我试过在ndk上进行编译,经过一番努力,通过链接事先编译好的C++ binder库,也成功编译通过,但是程序不能正常运行,这应该是预先编译出来的库和ndk的库存在兼容性问题造成的,或许通过在ndk上编译binder库可以避免这个问题,但是目前还没有作过尝试。 但是编译出来的代码应该可以运行在各个不同的版本,我在4.0和4.2版本的设备上作了简单的测试,事实证明在4.2上编译的代码可以在4.0上运行,但是考虑到android的诸多版本,各个版本多多少少有些兼容性问题,更详细的还必须比较各个版本的binder代码,并通过测试才能得到结果。





更多相关文章

  1. 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
  2. 使用VS2015调试Android的C++动态链接库
  3. Android(安卓)如何动态的控制Toast的显示与隐藏
  4. android api code学习之ActivityManager
  5. Android(安卓)开发经验汇总
  6. Android封装自定义Toast
  7. Android官方开发文档Training系列课程中文版:高效显示位图之管理
  8. 《第一行代码--Android》读书笔记之数据存储
  9. 与Android热更新方案Amigo的再次接触

随机推荐

  1. Android录音与播放
  2. 【Android】解决FloatMath类中方法在API
  3. 【Mood-12】Android开发相关书籍推荐
  4. 搞Android的伤不起啊
  5. Android(安卓)手机 Google Play 商店“从
  6. Android自带倒计时控件Chronometer使用方
  7. Android(安卓)adb不是内部或外部命令 (转)
  8. Android(安卓)Widget点击事件
  9. Android常用开源项目库
  10. 第三方Android(安卓)模拟器流畅速度快,适