Kivy A to Z — 怎样从python代码中直接訪问Android的Service「建议收藏」

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/115506.html原文链接:https://javaforall.net

(0)
上一篇 2022年2月3日 下午3:00
下一篇 2022年2月3日 下午4:00


相关推荐

  • 差分进化算法总结

    差分进化算法总结基本介绍 DE Differential 算法于 1997 年由 RainerStorn 和 KennethPrice 在遗传算法等进化思想的基础上提出的 本质是一种多目标 连续变量 优化算法 用于求解多维空间中整体最优解 其基本思想即是来源于遗传算法 模拟遗传算法中的杂交 变异 复制来设计算子 DE 算法和 GA 算法的相同点 随机生成初始种群以种群中个体适应度值为选择标准主要过

    2026年3月18日
    1
  • typescript 多继承_说明类的继承和多态有什么作用

    typescript 多继承_说明类的继承和多态有什么作用前言对于传统的JavaScript程序我们会使用函数和基于原型的继承来创建可重用的组件,但对于熟悉使用面向对象方式的程序员使用这些语法就有些棘手,因为他们用的是基于类的继承并且对象是由类构建出来

    2022年7月31日
    8
  • nonlocal怎么用_result的用法

    nonlocal怎么用_result的用法这个nonlocal是py3.x中才有的关键词第一种情况,不使用nonlocal的情况:#-*-encoding:utf-8-*-importsysreload(sys)sys.setdefaultencoding(‘utf-8’)deftest():x=1print(“test=”+str(x))#####################

    2025年9月20日
    7
  • webform激活成功教程及汉化

    webform激活成功教程及汉化首先现在官网上下载最新版本 webstorm 需要的可以私信我 自己最好下最新的 安装直接下一步就可以了 安装完成后会弹出一个注册框 先不要管也不要关闭 打开下载的激活成功教程包 根据你的电脑系统运行相应的服务器模拟程序 32 位系统的 xp win7 win10 运行 dvt jb licsrv 386 exe64 位系统的 win10 amd 运行 dvt jb licsrv amd64 exe

    2026年3月18日
    2
  • 基于RT-Thread操作系统的 基础四轮组智能车设计与实践

    基于RT-Thread操作系统的 基础四轮组智能车设计与实践这是一个很好的window,可以多少的。英俊的训练的场地的情况测window。简介:这是一个很好的window,可以多少的。英俊的训练的场地的情况测window。关键词:window

    2022年7月25日
    12
  • Redis应用-异步消息队列与延时队列

    Redis应用-异步消息队列与延时队列

    2022年2月18日
    42

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号