• Kivy A to Z -- 怎样从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 <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的底层实现也正是对这两个类进行封装的结果,详细的能够看

    frameworksasecorejniandroid_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,
    gateway %s,
    netmask %s,
    dns1 %s,
    dns2 %s,
    serverAddress %s,
    leaseDuration %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代码。并通过測试才干得到结果。





  • 相关阅读:
    .Net中的装箱和拆箱
    使用GetThumbnailImage进行图片缩放操作
    潭州课堂25班:Ph201805201 第二课:数据类型和序列类型 (课堂笔记)
    公开课 之 心蓝 数据分析 (课堂笔记)
    潭州课堂25班:Ph201805201 第一课:环境搭建 (课堂笔记)
    Maven笔记
    java中Swing编程再度练习篇
    Swing编程练习。可能这篇会有错误哦
    Swing
    Swing编程把图片放入frame里。先不作为背景图片
  • 原文地址:https://www.cnblogs.com/yxwkf/p/5347209.html
Copyright © 2020-2023  润新知