APK 与 Android Native Service 通信
2016-06-23 17:26
585 查看
apk(java binder client) 与 Native Service 通信
Android 4.4无需JNI Client
Native service (具有root权限)
通过Parcel在java与c++传输数据
IBinder.onTransact 通信原理
仅适用于系统开发人员(能够拿到源码编译后的android库)
native service 的编写
首先展示下目录结构NativeService.h
#include <utils/RefBase.h> #include <binder/IInterface.h> #include <binder/Parcel.h> #include <binder/IBinder.h> #define TRANSACTION_execCmd FIRST_CALL_TRANSACTION + 1 using namespace android; namespace nativeservice { class NativeService : public BBinder { private: public: static int Instance(); NativeService(); virtual ~NativeService(); virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t); }; }
NativeService.cpp
#include <binder/IServiceManager.h> #include <binder/IPCThreadState.h> #include "NativeService.h" namespace nativeservice { int NativeService::Instance() { sp<IServiceManager> SM = defaultServiceManager(); String16 str16Key = String16("nativeservice"); sp<IBinder> nativeService = new NativeService(); //注册服务 return SM -> addService(str16Key, nativeService); } NativeService::NativeService() { LOGV("NativeService create\n"); } NativeService::~NativeService() { LOGV("NativeService destory\n"); } //重点在这,处理client(可以是c++/java)来的的请求 status_t NativeService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { case TRANSACTION_execCmd: { LOGV("execCmd\n"); //读取client传过来的key,可用作安全判断,这里不做处理,但是一定要调用这段代码,把数据指针偏移到下个数据端,对于Parcel,客户端与服务端都要一一对应,否则数据传递会出错!!!! data.enforceInterface(String16(REMOTE_KEY)); //读取client传过来的参数(命令) String16 cmd = data.readString16(); char cResult[1024] = {0}; //这里是我自己的操作,根据自己的情况调用 m_SystemCommand.execCmd(cmd, cResult, 1024); String16 str16Result = String16(cResult); //写入异常code,"0"表示没有异常 reply -> writeInt32(0); //写入返回到client的返回数据 reply -> writeString16(str16Result); return NO_ERROR; } default: return BBinder::onTransact(code, data, reply, flags); } }
NativeServiceMain.cpp
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <grp.h> #include <binder/IPCThreadState.h> #include <binder/ProcessState.h> #include <binder/IServiceManager.h> #include "NativeService.h" using namespace nativeservice; int main(int arg, char** argv) { sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); int ret = NativeService::Instance(); if(!ret) { LOGV("add service success!\n"); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); } return 0; }
Android.mk
LOCAL_PATH:=$(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= NativeService.cpp \ NativeServiceMain.cpp LOCAL_SHARED_LIBRARIES:=libutils \ libbinder \ liblog #LOCAL_STATIC_LIBRARIES:=liburee_meta_drmkeyinstall #LOCAL_CFLAGS += -DRELEASE 这里可以相当于 #define RELEASE LOCAL_MODULE_TAGS:=optional LOCAL_MODULE:=NativeService include $(BUILD_EXECUTABLE)
到这里一个native services的框架已经写好了。对于c++,我之前没有学过,只有c语言和java的基础。写的不好,大家见谅!
来到java端
相信aidl大家都用过package com.example.nativeservicetest; import android.os.RemoteException; import android.util.Log; public interface INativeService extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements INativeService { private static final java.lang.String DESCRIPTOR = "nativeservice"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an * com.example.nativeservicetest.INativeService_s interface, generating * a proxy if needed. */ public static INativeService asInterface( android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof INativeService))) { return ((INativeService) iin); } return new INativeService.Stub.Proxy( obj); } @Override public android.os.IBinder asBinder() { return this; } private static class Proxy implements INativeService { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } @SuppressWarnings("unused") public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } // Public API @Override public String execCmd(String strCmd) throws RemoteException { //这里是将要传到native的参数 android.os.Parcel _data = android.os.Parcel.obtain(); //这里将会保存native返回的数据 android.os.Parcel _reply = android.os.Parcel.obtain(); String _result = ""; try { //写入key("nativeservice") _data.writeInterfaceToken(DESCRIPTOR); //写入了一个java的String类型的参数,也就是我们要在底层执行命令 _data.writeString(strCmd); //注意这个方法,android已经为我们实现好了,调用了这个方法,则直接调用了我们在nativeservice中的onTransact mRemote.transact(Stub.TRANSACTION_execCmd, _data, _reply, 0); //读取native发生的异常 _reply.readException(); //读取返回值 _result = _reply.readString(); // _result = (0 != _reply.readInt()); } finally { _reply.recycle(); _data.recycle(); } return _result; } } //nativeservice与java接口必须相等 static final int TRANSACTION_execCmd = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); } // Public API public String execCmd(String strCmd) throws android.os.RemoteException; }
在应用中的使用方法
... //ServiceManager为隐藏api IBinder binder = ServiceManager.getService("nativeservices"); final INativeService nativeService = INativeService.Stub.asInterface(binder); String result = nativeService.execCmd("ping -I eth0 -c 4 -i 0.2 -W1 -s 1000 192.168.5.1"); ...
好的一个自定义的nativeservice的框架已经完成,剩下的可以自由发挥!
稍微看看Parcel
Parcel.h
frameworks\native\include\binder\Parcel.h... bool enforceInterface(const String16& interface, IPCThreadState* threadState = NULL) const; bool checkInterface(IBinder*) const; void freeData(); const size_t* objects() const; size_t objectsCount() const; status_t errorCheck() const; void setError(status_t err); status_t write(const void* data, size_t len); void* writeInplace(size_t len); status_t writeUnpadded(const void* data, size_t len); status_t writeInt32(int32_t val); status_t writeInt64(int64_t val); status_t writeFloat(float val); status_t writeDouble(double val); status_t writeIntPtr(intptr_t val); //传说中的char型,但是在java中不能使用createCharArray,你懂得(java中的char也是16位?) status_t writeCString(const char* str); status_t writeString8(const String8& str); //这里对应java中的String status_t writeString16(const String16& str); status_t writeString16(const char16_t* str, size_t len); status_t writeStrongBinder(const sp<IBinder>& val); status_t writeWeakBinder(const wp<IBinder>& val); status_t writeInt32Array(size_t len, const int32_t *val); status_t writeByteArray(size_t len, const uint8_t *val); template<typename T> status_t write(const Flattenable<T>& val); template<typename T> status_t write(const LightFlattenable<T>& val); // Place a native_handle into the parcel (the native_handle's file- // descriptors are dup'ed, so it is safe to delete the native_handle // when this function returns). // Doesn't take ownership of the native_handle. status_t writeNativeHandle(const native_handle* handle); // Place a file descriptor into the parcel. The given fd must remain // valid for the lifetime of the parcel. // The Parcel does not take ownership of the given fd unless you ask it to. status_t writeFileDescriptor(int fd, bool takeOwnership = false); // Place a file descriptor into the parcel. A dup of the fd is made, which // will be closed once the parcel is destroyed. status_t writeDupFileDescriptor(int fd); // Writes a blob to the parcel. // If the blob is small, then it is stored in-place, otherwise it is // transferred by way of an anonymous shared memory region. // The caller should call release() on the blob after writing its contents. status_t writeBlob(size_t len, WritableBlob* outBlob); status_t writeObject(const flat_binder_object& val, bool nullMetaData); // Like Parcel.java's writeNoException(). Just writes a zero int32. // Currently the native implementation doesn't do any of the StrictMode // stack gathering and serialization that the Java implementation does. status_t writeNoException(); void remove(size_t start, size_t amt); status_t read(void* outData, size_t len) const; const void* readInplace(size_t len) const; int32_t readInt32() const; status_t readInt32(int32_t *pArg) const; int64_t readInt64() const; status_t readInt64(int64_t *pArg) const; float readFloat() const; status_t readFloat(float *pArg) const; double readDouble() const; status_t readDouble(double *pArg) const; intptr_t readIntPtr() const; status_t readIntPtr(intptr_t *pArg) const; const char* readCString() const; String8 readString8() const; String16 readString16() const; const char16_t* readString16Inplace(size_t* outLen) const; sp<IBinder> readStrongBinder() const; wp<IBinder> readWeakBinder() const; template<typename T> status_t read(Flattenable<T>& val) const; template<typename T> status_t read(LightFlattenable<T>& val) const; // Like Parcel.java's readExceptionCode(). Reads the first int32 // off of a Parcel's header, returning 0 or the negative error // code on exceptions, but also deals with skipping over rich // response headers. Callers should use this to read & parse the // response headers rather than doing it by hand. int32_t readExceptionCode() const; ...
新手上路,大家多多关照
走过路过,点个赞哟。
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法