NDK层获取Application对象
来源:互联网 发布:徐州淘宝打包员招聘 编辑:程序博客网 时间:2024/06/05 00:20
参考了一位大牛的博客,在Java层通过RuntimeInit获取的方式实现的,先贴原链接:
http://blog.csdn.net/l173864930/article/details/46919457
https://github.com/boyliang/Hijack_AMS_broadIntent
说明缘由,可能会有人提出调用NDK层方法时,自动会获得JNIEnv指针和jobject对象,其中jobject对应的便是Context,可现在的需求是可能出现得不到JNIEnv指针和jobject对象,比如so一加载的时候,就想获取一些系统服务,此时还没有开始调用方法,便得不到这两个需要的对象。
首先说明JNIEnv指针,这个网上有很多的方法获得,我的做法是调用JNI_OnLoad函数,获取JavaVM(当然有其他方式获取),调用GetEnv方法便可获取...比较熟知,不再赘述。贴下代码:
jint JNI_OnLoad(JavaVM* jVm, void* reserved) { jint result = JNI_ERR; JNIEnv* env; if ((*jVm)->GetEnv(jVm,(void**) &env, JNI_VERSION_1_6) != JNI_OK) { return result; } result = JNI_VERSION_1_6; return result;}
对于Application对象,大牛的博客已经实现了Java层的获取,这里贴下伪代码:
Applicatioin app = RuntimeInit.mApplicationObject.this$0.mInitialApplication;
详细的过程可以去看看
NDK层中如何获取呢?
我想到了两种做法
第一种做法,既然Java层代码(翻查上面链接)能够获取了,直接编个APK,通过DexClassLoader加载APK,调用其中的类方法...但是一直提示找不到类,之前使用AS编译出来的一直有问题,后来使用Eclipse编译出来的apk没有问题,应该是dex文件结构有所变化...有空再细看
jobject SerachContextByJava(JNIEnv *env){ jstring js_apkpath = (*env)->NewStringUTF(env,"/sdcard/getApplicationContext.apk"); jstring js_odexpath = (*env)->NewStringUTF(env,"/data/data/com.ndk/"); jclass cls_dexloader = (*env)->FindClass(env,"dalvik/system/DexClassLoader"); snprintf(sig_buffer, 512, "(%s%s%s%s)V", JSTRING, JSTRING, JSTRING, "Ljava/lang/ClassLoader;"); jmethodID met_dexloader_init = (*env)->GetMethodID(env,cls_dexloader, "<init>", sig_buffer); snprintf(sig_buffer, 512, "(%s)%s", JSTRING, JCLASS); jmethodID met_loadClass = (*env)->GetMethodID(env,cls_dexloader, "loadClass", sig_buffer); jclass cls_classloader = (*env)->FindClass(env,"java/lang/ClassLoader"); snprintf(sig_buffer, 512, "()%s", "Ljava/lang/ClassLoader;"); jmethodID met_getSystemClassLoader = (*env)->GetStaticMethodID(env,cls_classloader, "getSystemClassLoader", sig_buffer); jobject obj_systemclassloader = (*env)->CallStaticObjectMethod(env,cls_classloader, met_getSystemClassLoader); (*env)->DeleteLocalRef(env,cls_classloader); if(ObjIsNull(obj_systemclassloader,"obj_systemclassloader")) { return NULL; } jobject obj_dexclassloader = (*env)->NewObject(env,cls_dexloader, met_dexloader_init, js_apkpath, js_odexpath, NULL, obj_systemclassloader); (*env)->DeleteLocalRef(env,js_apkpath); (*env)->DeleteLocalRef(env,js_odexpath); (*env)->DeleteLocalRef(env,cls_dexloader); (*env)->DeleteLocalRef(env,obj_systemclassloader); if(ObjIsNull(obj_dexclassloader,"obj_dexclassloader")) { (*env)->DeleteLocalRef(env,obj_dexclassloader); return NULL; } jstring js_GetContext = (*env)->NewStringUTF(env,"com.example.runjni.GetContext"); jobject cls_GetContext = ((*env)->CallObjectMethod(env,obj_dexclassloader, met_loadClass, js_GetContext)); (*env)->DeleteLocalRef(env,obj_dexclassloader); (*env)->DeleteLocalRef(env,js_GetContext); if(ObjIsNull(cls_GetContext,"cls_GetContext")) { (*env)->DeleteLocalRef(env,cls_GetContext); return NULL; } jmethodID met_searchContextForZygoteProcess = (*env)->GetStaticMethodID(env,cls_GetContext, "searchContextForZygoteProcess", "()Landroid/content/Context;"); jobject applicationcontext = (*env)->CallStaticObjectMethod(env,cls_GetContext, met_searchContextForZygoteProcess); (*env)->DeleteLocalRef(env,cls_GetContext); if(ObjIsNull(applicationcontext,"applicationcontext")) { (*env)->DeleteLocalRef(env,applicationcontext); return NULL; } __android_log_print(ANDROID_LOG_ERROR,"r-ndk","END Serach Context By Java"); return applicationcontext;}
第二种做法,也是基于Java层代码,通过C层API调用Java层的方法来实现。
jobject SearchContextByC(JNIEnv *env){ jstring js_RuntimeInit = (*env)->NewStringUTF(env,"com.android.internal.os.RuntimeInit"); jclass cls_class = (*env)->FindClass(env, "java/lang/Class"); snprintf(sig_buffer, 512, "(%s)%s", JSTRING,JCLASS); jmethodID met_forName = (*env)->GetStaticMethodID(env,cls_class, "forName", sig_buffer); jobject obj_runtime = (*env)->CallStaticObjectMethod(env,cls_class, met_forName,js_RuntimeInit); (*env)->DeleteLocalRef(env,js_RuntimeInit); if(ObjIsNull(obj_runtime,"obj_runtime")) { (*env)->DeleteLocalRef(env,cls_class); (*env)->DeleteLocalRef(env,obj_runtime); return NULL; } jstring js_getApplicationObject = (*env)->NewStringUTF(env,"getApplicationObject"); snprintf(sig_buffer, 512, "(%s%s)%s", JSTRING,JCLASS_ARR,JMETHOD); jmethodID met_getDeclaredMethod = (*env)->GetMethodID(env,cls_class, "getDeclaredMethod", sig_buffer); jobject obj_sGetApplicationObject_method = (*env)->CallObjectMethod(env, obj_runtime, met_getDeclaredMethod,js_getApplicationObject,NULL); (*env)->DeleteLocalRef(env,js_getApplicationObject); (*env)->DeleteLocalRef(env,obj_runtime); if(ObjIsNull(obj_sGetApplicationObject_method,"obj_sGetApplicationObject_method")) { (*env)->DeleteLocalRef(env,obj_sGetApplicationObject_method); (*env)->DeleteLocalRef(env,cls_class); return NULL; } jclass cls_method = (*env)->FindClass(env, "java/lang/reflect/Method"); snprintf(sig_buffer, 512, "(%s%s)%s", JOBJECT,JOBJECT_ARR,JOBJECT); jmethodID met_invoke = (*env)->GetMethodID(env,cls_method, "invoke", sig_buffer); jobject obj_applicationobj = (*env)->CallObjectMethod(env,obj_sGetApplicationObject_method, met_invoke,NULL,NULL); (*env)->DeleteLocalRef(env,cls_method); (*env)->DeleteLocalRef(env,obj_sGetApplicationObject_method); if(ObjIsNull(obj_applicationobj,"obj_applicationobj")) { (*env)->DeleteLocalRef(env,cls_class); (*env)->DeleteLocalRef(env,obj_applicationobj); return NULL; } jclass cls_object = (*env)->FindClass(env, "java/lang/Object"); snprintf(sig_buffer, 512, "()%s", JCLASS); jmethodID met_getClass = (*env)->GetMethodID(env,cls_object, "getClass", sig_buffer); jobject obj_ApplicatioinThread_class = (*env)->CallObjectMethod(env,obj_applicationobj, met_getClass); (*env)->DeleteLocalRef(env,cls_object); if(ObjIsNull(obj_ApplicatioinThread_class,"ApplicatioinThread_class")) { (*env)->DeleteLocalRef(env,cls_class); (*env)->DeleteLocalRef(env,obj_ApplicatioinThread_class); (*env)->DeleteLocalRef(env,obj_applicationobj); return NULL; } jstring this0 = (*env)->NewStringUTF(env,"this$0"); snprintf(sig_buffer, 512, "(%s)%s", JSTRING,JFIELD); jmethodID getDeclaredField = (*env)->GetMethodID(env,cls_class, "getDeclaredField", sig_buffer); jobject obj_sThis0_field = (*env)->CallObjectMethod(env, obj_ApplicatioinThread_class, getDeclaredField,this0); (*env)->DeleteLocalRef(env,obj_ApplicatioinThread_class); (*env)->DeleteLocalRef(env,this0); (*env)->DeleteLocalRef(env,cls_class); if(ObjIsNull(obj_sThis0_field,"obj_sThis0_field")) { (*env)->DeleteLocalRef(env,obj_sThis0_field); (*env)->DeleteLocalRef(env,obj_applicationobj); return NULL; } jclass cls_accessibleObject = (*env)->FindClass(env, "java/lang/reflect/AccessibleObject"); snprintf(sig_buffer, 512, "(Z)V"); jmethodID setAccessible = (*env)->GetMethodID(env,cls_accessibleObject, "setAccessible", sig_buffer); jboolean bool_true = 0x1; (*env)->CallVoidMethod(env,obj_sThis0_field,setAccessible,bool_true); (*env)->DeleteLocalRef(env,cls_accessibleObject); jclass cls_field = (*env)->FindClass(env, "java/lang/reflect/Field"); snprintf(sig_buffer, 512, "(%s)%s",JOBJECT,JOBJECT); jmethodID get_field = (*env)->GetMethodID(env,cls_field, "get", sig_buffer); jobject obj_activityObjThr = (*env)->CallObjectMethod(env, obj_sThis0_field, get_field,obj_applicationobj); (*env)->DeleteLocalRef(env,obj_sThis0_field); (*env)->DeleteLocalRef(env,obj_applicationobj); (*env)->DeleteLocalRef(env,cls_field); if(ObjIsNull(obj_activityObjThr,"obj_activityObjThr")) { (*env)->DeleteLocalRef(env,obj_activityObjThr); return NULL; } snprintf(sig_buffer, 512, "()%s", JCLASS); jobject obj_ActivityThread_class = (*env)->CallObjectMethod(env,obj_activityObjThr, met_getClass); if(ObjIsNull(obj_ActivityThread_class,"obj_ActivityThread_class")) { (*env)->DeleteLocalRef(env,obj_activityObjThr); (*env)->DeleteLocalRef(env,obj_ActivityThread_class); return NULL; } jstring mInitialApplication = (*env)->NewStringUTF(env,"mInitialApplication"); jobject sInitialApplication_field = (*env)->CallObjectMethod(env, obj_ActivityThread_class, getDeclaredField,mInitialApplication); (*env)->DeleteLocalRef(env,obj_ActivityThread_class); (*env)->DeleteLocalRef(env,mInitialApplication); if(ObjIsNull(sInitialApplication_field,"sInitialApplication_field")) { (*env)->DeleteLocalRef(env,obj_activityObjThr); (*env)->DeleteLocalRef(env,sInitialApplication_field); return NULL; } (*env)->CallVoidMethod(env,sInitialApplication_field,setAccessible,bool_true); jobject applicationContext = (*env)->CallObjectMethod(env, sInitialApplication_field, get_field,obj_activityObjThr); (*env)->DeleteLocalRef(env,obj_activityObjThr); (*env)->DeleteLocalRef(env,sInitialApplication_field); if(ObjIsNull(applicationContext,"applicationContext")) { (*env)->DeleteLocalRef(env,applicationContext); return NULL; } __android_log_print(ANDROID_LOG_VERBOSE,"r-ndk","END Search Context from C"); return applicationContext;}
做法不难,就是写着挺麻烦,测试5.1,6.0都没问题,贴出来方便大家使用,有更好的方法欢迎推荐。
遇到了一个其他的问题,感觉似乎无法解决,当在fork出一个子进程时,通过此方法去获取系统服务时,进一步操作会出现崩溃的情况,提示的是Couldn't find ProcessRecord for pid xxx
pid对应是子进程id,查了一下相关的资料,搜到了这篇讲述的情况,大概是因为会根据pid查找自己的前世ProcessRecord,ProcessRecord会对应实例app,因此找不到。
http://blog.csdn.net/maxleng/article/details/5621345
转载请注明出处。
1 0
- NDK层获取Application对象
- 反射获取 application对象
- 获取层对象
- 获取全局的Application对象
- Struts2中获取request,session,application对象
- 【insigma】获取request、session、application的对象
- 如何获取request、session和application对象
- struts2 获取request,seesion,application对象
- Struts2中获取request,session,application对象
- Flex中获取Application对象的方式
- ActionContext获取request、session和application对象
- Struts2中获取request,session,application对象
- java 层调用Jni(Ndk) 持久化c c++ 对象
- android ndk jni层访问java对象小结
- dwr 获取持久层对象报错
- cocos2dx tile地图获取对象层数据
- WebSocket获取service层对象,操作数据库
- NDK Application.mk使用手册
- Android数据库高手秘籍(一)——SQLite命令
- UITextView修改能容 自动滚动到最后一行
- openssl 简单的https验证 自签名证书
- MySQL服务器性能(通过Sysbench测试cpu、io、内存以及mysql服务等)
- HDOJ 2011-多项式求和
- NDK层获取Application对象
- CXF系列之JAX-RS:CXF发布与调用REST服务
- 微型气泵最大启动压力试验报告
- 记录一次MongoDB3.0.6版本wiredtiger与MMAPv1引擎的写入耗时对比
- jquery的几种异步请求,ajax
- NNU_20161103_7
- leetcode解题集锦之 Remove Element
- 点android源码点击不进去?
- libevent参考手册第四章:与事件一起工作