上篇文章添加了一个自定义的系统服务,并且可以获取使用该服务。这篇文章在上篇文章的基础上,
利用JNI机制实现该系统服务对应的C++文件,本篇文章基于android 6.0。
目标:
1,java通过JNI机制可以调用C++中的方法
2,C++调用java中的方法
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++的进行调用。
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);当然这些文件的路径根据实际情况有所不同。
在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。