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

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 深入理解卷积层,全连接层的作用意义「建议收藏」

    深入理解卷积层,全连接层的作用意义「建议收藏」有部分内容是转载的知乎的,如有侵权,请告知,删除便是,但由于是总结的,所以不一一列出原作者是who。再次感谢,也希望给其他小白受益。首先说明:可以不用全连接层的。理解1:卷积取的是局部特征,全连接就是把以前的局部特征重新通过权值矩阵组装成完整的图。因为用到了所有的局部特征,所以叫全连接。理解2:从卷积网络谈起,卷积网络在形式上有一点点像咱们正在召开的“人民代表大会制度”。卷积核的个数相当于候选人,…

  • Java中高级工程师面试题及答案,Java面试题及答案汇总(二

    Java中高级工程师面试题及答案,Java面试题及答案汇总(二需要注意Jdk1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn)24.说一下HashSet的实现原理?HashSet底层由HashMap实现HashSet的值存放于HashMap的key上HashMap的value统一为PRESENT25.ArrayList和LinkedList的区别是什么?最明显的区别是ArrrayList底层的数据结构是数组,支持随机访问,而Linke

  • python的进制转换器,Python进制转换[通俗易懂]

    python的进制转换器,Python进制转换[通俗易懂]进制转换:进制转换是人们利用符号来计数的方法。进制转换由一组数码符号和两个基本因素“基数”与“位权”构成。基数是指,进位计数制中所采用的数码(数制中用来表示“量”的符号)的个数。位权是指,进位制中每一固定位置对应的单位值。简单转换理念:把二进制三位一组分开就是八进制,四位一组就是十六进制二进制与十进制:(1)二进制转十进制:“按权展开求和”(1011)2=1×2**3+0x2**2+1x…

  • 基于Ubuntu20.04 Linux系统安装 Microsoft Edge浏览器 详细步骤

    基于Ubuntu20.04 Linux系统安装 Microsoft Edge浏览器 详细步骤目录1.MicrosoftEdge注意:最近在学习强度学习,作为刚起步的小白啥也不懂就先安装了最新的Ubuntu20.04,听很多人说这个版本相对之前的版本可以很方便的链接网络,个人感觉还不错。  个人之前一直使用Windows系统,初次接触Linux有不足之处请读者多多包含。在Windows系统的时候使用的浏览器,我还是比较喜欢使用MicrosoftEdge,之前用过一段时间的Chrome的参考资料:基于Linux的MicrosoftEdge浏览器1.Microsoft

  • Mybatis学习地址总结整理-持续更新……「建议收藏」

    MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

  • apachestruts2是什么_apache免费吗

    apachestruts2是什么_apache免费吗 1.org.apache.struts2.dispatcher.FilterDispatcher?    是Struts2的主要的Filter,负责四个方面的功能:        (1)执行Actions        (2)清除ActionContext        (3)维护静态内容        (4)清除request生命周期内的XWork的interceptors    另注

发表回复

您的电子邮箱地址不会被公开。

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