mpython 直接访问_如何从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 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include "binder_wrap.h"

using namespace android;

void* binder_getbinder(const char *name)

{

android::sp<:iservicemanager> sm = android::defaultServiceManager();

sp *binder = new sp();

do {

*binder = sm->getService(android::String16(name));

if (binder != 0)

{

break;

}

usleep(500000); // 0.5 s

} while(true);

return reinterpret_cast(binder);

}

int binder_releasebinder(void* binder)

{

sp *bp = reinterpret_cast *>(binder);

if(bp == 0)

{

return 0;

}

delete bp;

return 1;

}

//Vector    listServices() = 0;

int binder_listServices(vector_visitor visitor,void *data)

{

android::sp<:iservicemanager> sm = android::defaultServiceManager();

Vector list = sm->listServices();

for (int i=0;i

{

visitor(list[i].string(),list[i].size(),data);

}

return list.size();

}

int binder_getInterfaceDescriptor(void *binder,char16_t *descriptor,size_t size)

{

sp *bp = reinterpret_cast *>(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 *bp = reinterpret_cast *>(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);

if(p == 0)

{

return 0;

}

return p->writeInterfaceToken(String16(interface));

}

int parcel_writeInt32(void *parcel,int val)

{

Parcel *p = reinterpret_cast(parcel);

if(p == 0)

{

return 0;

}

return p->writeInt32(val);

}

int parcel_writeCString(void *parcel,const char* str)

{

Parcel *p = reinterpret_cast(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);

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);

if(p == 0)

{

return 0;

}

return p->readInt32();

}

long parcel_readInt64(void *parcel)

{

Parcel *p = reinterpret_cast(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);

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);

if(p == 0)

{

return 0;

}

return p->readExceptionCode();

}

int parcel_readInplace(void *parcel,void* data, int len)

{

Parcel *p = reinterpret_cast(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);

if(p == 0)

{

return 0;

}

return p->dataAvail();

}

正如代码中所示,这里对C++的IBinder和Parcel两个对象进行了封装,而Java的Service的底层实现也正是对这两个类进行封装的结果,具体的可以看

frameworksbasecorejniandroid_util_Binder.cpp

的代码,

再来看下如何在Python中使用这些代码,这里用cython来封装这些C接口:

binder.pyxcdef 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 = data

o = PyUnicode_FromUnicode(str16,length)

arr.append(o)

def listServices():

arr = []

Py_INCREF(arr)

binder_listServices(visitor,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(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,dataPtr,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 = nativePtr

def __dealloc__(self):

if not self.nativePtr:

parcel_destroy(self.ptr)

def getNativePtr(self):

return self.ptr

def writeInterfaceToken(self,const char *interface):

return parcel_writeInterfaceToken(self.ptr,interface)

def writeInt(self,int val):

self.writeInt32(val)

def writeInt32(self,int val):

return parcel_writeInt32(self.ptr,val)

def writeCString(self,const char* cstr):

return parcel_writeCString(self.ptr,cstr)

def writeString16(self,ustr):

cdef char16_t *un

cdef int size

if isinstance(ustr,unicode):

un = PyUnicode_AS_UNICODE(ustr)

size = PyUnicode_GetSize(ustr)

return parcel_writeString16(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(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.pyfrom 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.pyimport 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代码,并通过测试才能得到结果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/504877.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python中attr_python中hasattr()、getattr()、setattr()函数的使用

引言&#xff1a;在阅读高手写的代码时&#xff0c;有很多简写的形式&#xff0c;如果没有见过还真的看不太懂是什么意思&#xff0c;其中一个比较常用的就是getattr()用来调用一个类中的变量或者方法&#xff0c;相关联的hasattr()、getattr()、setattr()函数的使用也一并学习…

python前n项和存为一个数组_在Python中存储多个数组

我正在编写一个程序来模拟像Gallup或Rasmussen这样的公司每天发布的实际投票数据&#xff1a;www.gallup.com和www.rassmussenreports.com我正在使用强力方法,计算机生成一些随机的每日轮询数据,然后计算三天平均值,以查看随机数据的平均值是否与民意测验数字相匹配. (大多数公…

织梦数据库改mysql前缀_织梦快速批量修改MYSQL数据库表前缀与表名实例操作

这篇文章主要为大家详细介绍了织梦快速批量修改MYSQL数据库表前缀与表名实例操作&#xff0c;具有一定的参考价值&#xff0c;感兴趣的小伙伴们可以参考一下,有需要的朋友可以收藏方便以后借鉴。我们在安装织梦系统的时候&#xff0c;有一次批量修改mysql数据库表前缀的机会&am…

python实时绘图暂停_Python实时绘图

我在两个数组中获取了一些数据&#xff1a;一个用于时间,一个用于值.当我达到1000点时,我触发一个信号并绘制这些点(x 时间,y 值).我需要在前面的图中保持相同的数字,但只是一个合理的数字,以避免减慢过程.例如,我想在我的图表上保留10,000点.matplotlib交互式绘图工作正常,但我…

python 读文件写数据库_python读文件写数据库

Python 读文件&#xff0c;写数据库Python 读文件打开文件Python读写文件在计算机语言中被广泛的应用&#xff0c;如果你想了解其应用的程序&#xff0c;以下的文章会给你详细的介绍相关内容&#xff0c;会你在以后的学习的过程中有所帮助&#xff0c;下面我们就详细介绍其应用…

python怎么用gamma函数_如何通俗的理解伽马(gamma)函数

如何通俗的理解伽马(gamma)函数 - 直觉&#xff0c;求导和示例我为什么要在乎garmma分布&#xff1f;使用伽马函数定义了许多概率分布&#xff0c;例如伽马分布&#xff0c;Beta分布&#xff0c;狄利克雷分布&#xff0c;卡方分布和学生t分布等。 对于数据科学家&#xff0c;机…

mysql支持表情输入_让MySQL支持Emoji表情 mysql 5.6

在做微信公众号开发过程中&#xff0c;经常碰到用户的昵称中有表情&#xff0c;在MySQL保存时常用的utf8 字符集根本无法存储表情&#xff0c;提示错误如下&#xff1a;java.sql.SQLException: Incorrect string value: \xF0\x9F\x92\x94 for column nick_name at row 1at com.…

graphpad如何检测方差齐_如何选择方差分析的多重比较方法?资料集锦

欢迎订阅SPSS训练营号方差分析时&#xff0c;如果因素主效应有显著影响&#xff0c;则需要对因素水平进行两两比较&#xff0c;以确认因素水平间的具体差异。这个过程也叫作多重比较。SPSS提供14种用于方差齐次的多重比较方法&#xff0c;还有4种方差不齐情况下的多重比较方法&…

编程真好玩python_(两本套)编程真好玩+教孩子学编程(Python语言版)

第1 章 Python 基础&#xff1a;认识环境 1 11 认识Python 3 12 用Python 编写程序 5 13 运行Python 程序 5 14 本章小结 6 15 编程挑战 7 第2 章 海龟作图&#xff1a;用Python 绘图 9 21 **个海龟程序 10 211 程序是如何工作的 10 212 发生了什么 12 22 旋转的海龟 13 23 海龟…

反转链表 python 递归_LeetCode 206.反转链表(Python3)

题目&#xff1a;反转一个单链表。示例:输入: 1->2->3->4->5->NULL输出: 5->4->3->2->1->NULL进阶:你可以迭代或递归地反转链表。你能否用两种方法解决这道题&#xff1f;解答&#xff1a;方法一&#xff1a;原地反转。# Definition for singly-…

java image 透明_java的BufferedImage对象透明化背景

近用到Java动态生成背景透明的图片功能&#xff0c;从gif和png中选择了png格式&#xff0c;个中缘由就不说了&#xff0c;于是动手到网上搜索有用的代码。现把搜索结果总结如下&#xff1a;1. 生成png图片int width 400;int height 300;// 创建BufferedImage对象BufferedImag…

【MySQL学习笔记009】事务

一、事务简介 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求&#xff0c;即这些操作要么同时成功&#xff0c;要么同时失败。 二、事务操作 1、操作1 查看/设置事务提交方式 select a…

python的pypi安装_python pip及安装包安装

python 微信聊天D:\untitled\hello.py 入口 web禁止登陆。。安装命令&#xff1a;手动安装&#xff1a;D:\python\setuptools-41.2.0>python setup.py install下载下来手动安装pipD:\python\pip-1.4.1\pip-1.4.1>python setup.py installD:\python\setuptools-41.2.0>…

python 爬取生意参谋数据_如何爬取生意参谋数据?是不是违规操作?

1、在淘宝选项卡中&#xff0c;打开【生意参谋】工具。2、在【生意参谋数据拷贝】中&#xff0c;点击【打开生意参谋】按钮。3、在调用的IE浏览器中输入账号和密码。4、登陆好后&#xff0c;找到竞品&#xff0c;并点击【查看详情】。5、进入到竞品详情后&#xff0c;注意修改日…

c mysql 视图_MySQL入门教程(七)之视图

相关阅读&#xff1a;视图是从一个或多个表中导出来的虚拟表。视图就像一个窗口&#xff0c;通过这个窗口可以看到系统专门提供的数据。1、视图简介1.1 视图的含义视图是从一个或多个表中导出来的虚拟表&#xff0c;还可以从已经存在的视图的基础上定义。数据库中只存放视图的定…

tensorflow gpu安装_tensorflow-gpu安装配置

1 介绍目前&#xff0c;主流版本是tensorflow-gpu 1.12.0&#xff0c;线上安装这个版本&#xff0c;和这个版本搭配的cuda是9.0版本&#xff0c;cudnn版本是7.0.5。2 cuda和cudnn安装cuda驱动地址&#xff1a;cuda_9.0.176_384.81_linux.runcudnn库地址: cudnn-9.0-linux-x64-v…

hibernate mysql autocommit_Hibernate4 中为什么我没有用commit()方法直接用save就存到数据库了?...

求大神讲解下Hibernate4 中为什么我没有用commit()方法直接用save就存到数据库了&#xff1f;public class Main {public static void main(String[] args) {SessionFactory sessionFactory new Configuration().configure().buildSessionFactory();Student student new Stud…

java ee文件下载_JavaEE实现文件下载

我们先来看一个最简单的文件下载的例子&#xff1a;package com.yyz.response;import java.io.FileInputStream;import java.io.IOException;import java.io.OutputStream;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.…

python输出jpg_利用python实现.dcm格式图像转为.jpg格式

如下所示&#xff1a;import pydicomimport matplotlib.pyplot as pltimport scipy.miscimport pandas as pdimport numpy as npimport osdef Dcm2jpg(file_path):#获取所有图片名称c []names os.listdir(file_path) #路径#将文件夹中的文件名称与后边的 .dcm分开for name in…

java联合主键_hibernate联合主键映射(注解版)

1、联合主键的映射三种写法实体类&#xff1a;package com.zhouwei.po;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.IdClass;import javax.persistence.Table;//联合主键(通过id和name确定一个人)EntityTable(name"t_person&q…