您的位置:首页 > 移动开发 > Android开发

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


新手上路,大家多多关照

走过路过,点个赞哟。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android java apk c语言