在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。

專業(yè)從事成都網站建設、成都網站制作,高端網站制作設計,小程序制作,網站推廣的成都做網站的公司。優(yōu)秀技術團隊竭力真誠服務,采用H5網站設計+CSS3前端渲染技術,響應式網站建設,讓網站在手機、平板、PC、微信下都能呈現。建站過程建立專項小組,與您實時在線互動,隨時提供解決方案,暢聊想法和感受。
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
#endifbinder_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
執(zhí)行后將會打印出搜索到的Wifi信息。
另外就是代碼的編譯問題了。代碼必須在android的源代碼下進行編譯。我試過在ndk上進行編譯,經過一番努力,通過鏈接事先編譯好的C++ binder庫,也成功編譯通過,但是程序不能正常運行,這應該是預先編譯出來的庫和ndk的庫存在兼容性問題造成的,或許通過在ndk上編譯binder庫可以避免這個問題,但是目前還沒有作過嘗試。 但是編譯出來的代碼應該可以運行在各個不同的版本,我在4.0和4.2版本的設備上作了簡單的測試,事實證明在4.2上編譯的代碼可以在4.0上運行,但是考慮到android的諸多版本,各個版本多多少少有些兼容性問題,更詳細的還必須比較各個版本的binder代碼,并通過測試才能得到結果。
文章標題:如何從python代碼中直接訪問Android的Service
標題來源:http://www.chinadenli.net/article30/pgdepo.html
成都網站建設公司_創(chuàng)新互聯,為您提供網站導航、標簽優(yōu)化、網站策劃、靜態(tài)網站、、企業(yè)網站制作
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯