上篇文章添加了一个自定义的系统服务,并且可以获取使用该服务。这篇文章在上篇文章的基础上,
利用JNI机制实现该系统服务对应的C++文件,本篇文章基于android 6.0。
目标:
1,java通过JNI机制可以调用C++中的方法
2,C++调用java中的方法
1, MyService创建方法
frameworks/base/services/core/java/com/android/server/路径下的MyService.java如下,
package com.android.server;
import android.os.IMyService;
import android.util.Log;
class MyService extends IMyService.Stub {
private String myName ;
private String myCName ;
public MyService(){
}
@Override
public void setName(String mname){
myName = mname;
}
@Override
public String getName(){
getNameNative();
return myCName;
}
public void getCName(String str){
myCName = myName + " C_Java " + str;
Log.d("android ", "myCName: " + myCName);
}
public native void ();
}
新添加一个getNameNative方法,调用对应的C++的getNameNative方法。
新添加一个getCName方法,供C++的进行调用。
2,添加对应的C++文件
1,在frameworks/base/services/core/jni路径下添加com_android_server_MyService.cpp文件,主要内容如下,
namespace android
{
static void getNameNative(JNIEnv *env, jobject object) { //调用
LOGI("native getNameNative");
jclass clazz = env->FindClass("com/android/server/MyService");
jmethodID methodID = env->GetMethodID(clazz, "getCName", "(Ljava/lang/String;)V");
env->CallVoidMethod(object,methodID,env->NewStringUTF(" Java_C is successed"));
}
static JNINativeMethod sMethods[] = {
{"getNameNative", "()V", (void*)getNameNative},
};
int register_android_server_MyService(JNIEnv* env) //注册
{
LOGI("register_android_server_MyService");
return jniRegisterNativeMethods(env, "com/android/server/MyService",
sMethods, NELEM(sMethods));
}
}
2,在frameworks/base/services/core/jni路径下Android.mk文件LOCAL_SRC_FILES中添加如下内容,
LOCAL_SRC_FILES += \
•••
$(LOCAL_REL_DIR)/com_android_server_MyService.cpp \
•••
3,frameworks/base/services/core/jni路径下的onload.cpp文件中,
在namespace android 中最后添加
int register_android_server_MyService(JNIEnv* env);
在extern "C" jintJNI_OnLoad(JavaVM* vm, void* /* reserved */)中添加
register_android_server_MyService(env);
当然这些文件的路径根据实际情况有所不同。
3,代码分析
在apk中,
mMyServiceManager = (MyServiceManager)getSystemService("MyService");
mMyServiceManager.setName("my_stystem_service");
Log.d("android " , "getName" + mMyServiceManager.getName());
最后输出:
my_stystem_service C_Java Java_C is successed
调用的逻辑如下,
1,首先调用系统服务MyService的getName方法。
2,系统服务MyService通过JNI机制调用com_android_server_MyService.cpp的getNameNative方法。
3,在com_android_server_MyService.cpp的getNameNative方法中调用系统服务MyService的getCName方法为变量myCName赋值。
4,最后返回系统服务MyService的变量myCName。