背景:
一步步摸索着开发走来,本着能走通就继续往前走的原则,将dlna项目做到了现在,做到了出产品。
可是一直有一个问题困扰着我,为什么我们的程序不能覆盖安装?其他的android应用程序,无论带不带动态库,都可以实现覆盖安装,不用很麻烦地一步步进行手动清除数据/手动卸载/然后才能安装的问题。否则,如果直接安装,可能会导致so包更新失败的问题,会继续使用旧的so包。更搞笑的是,即便把某个so包删除,程序也不会报错,即便用到了该so包中的某个库函数,仍会继续运行下去。这个问题无法容忍。
过程:
在网上搜索android上需要手动清除数据/手动卸载的原因及解决方法,发现根本找不到这方面的资料。
反思:
在一个开源平台上,别人都不会碰到同样的问题吗?只能说明一个问题,这个问题,要么太深奥,要么太简单。我想到了自从一开始就一直萦绕在我心头的一个初始化函数的实现:JNI_OnLoad
解决:
又一次详细地看了JNI_OnLoad这个函数可能带来的好处:初始化,定义最低JNI版本,注册方法。 抱着试试看的心态,试着写这个函数,梦想着能够解决问题。
结果,大功告成!^_^
小结:
(1)这次dms/dmr/dmc三个JNI文件中的native方法很多,工作量不小,但是效率却比较高。我想这是平时积累见到的成效。
(2) 关于获取env及规定最低版本,以前尝试写在JNI_OnLoad里,但是出错,但是现在却对了;直接获取类的ID的方法FindClass,以前没有JNI_OnLoad方法的时候,将它用在nativesetup方法里,出错,在nativesetup方法里,就只能用FindObjectClass可用了。以前不能用,现在可用,应该是某个地方细微的差别导致的。如果学艺不精,解决问题会很浪费时间,什么都要查资料。累积的知识到了一定的程度,即便碰到问题,也能很快找出原因并解决。
(3)在开发过程中碰到方法注册失败的问题。如果Java文件里没有相应的native方法,在底层接口中最好将其注释掉,免得导致注册失败。这个问题的解决关键,在于从C++代码跳到Java代码来解决问题的思路。
做开发,多积累,准没错,它的成效会比你想象的还要好。
现在贴上部分代码,以备留念。
代码:
[cpp] view plain copy print ?
1. <code class="language-cpp">//methods table
2. static
3. "A", "(Ljava/lang/Object;)V", (void
4. "B", "(Ljava/lang/String;)I", (void
5. "C", "(Ljava/lang/String;)I", (void
6. "D", "()I", (void
7. "E", "()Ljava/lang/String;", (void
8. "F", "()Ljava/lang/String;", (void
9. "G", "(Ljava/lang/String;Ljava/lang/String;)V", (void
10. "H", "(Ljava/lang/String;)I", (void
11. "I", "(Ljava/lang/String;)Ljava/lang/String;", (void
12. "J", "()Z", (void
13. };
14.
15. /* define the minimum version
16. * initialization
17. * register native methods.
18. * */
19. jint JNI_OnLoad(JavaVM* vm, void* reserved)
20. {
21. "plist:.level=INFO;.handlers=ConsoleHandler;.ConsoleHandler.colors=off;.ConsoleHandler.filter=42");
22. JNIEnv* env = NULL;
23. jint result = -1;
24. if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
25. {
26. "JNI version error!");
27. return
28. }
29. //assert(env != NULL);
30. if
31. {
32. "JNI-----getEnv fail.");
33. return
34. }
35.
36. //gJavaVM
37. env->GetJavaVM(&gJavaVM);
38. if
39. {
40. "JNI-----GetJavaVM fail.");
41. return
42. }
43.
44. clazz = env->FindClass(classPathName);
45. if
46. {
47. "JNI Cannot find %s!", classPathName);
48. return
49. }
50.
51. //get MethodID
52. "postEvent", "(Ljava/lang/Object;ILjava/lang/String;Ljava/lang/String;)V");
53.
54. //if ExceptionOccurred
55. if
56. {
57. "JNI-----GetStaticMethodID fail.");
58. return
59. }
60.
61. //register methods.
62. if (env->RegisterNatives(clazz, gMethods, sizeof(gMethods)/sizeof(gMethods[0])) < 0)
63. {
64. "JNI-----RegisterNatives fail.");
65. return
66. }
67. "JNI_OnLoad-----sucess!");
68. return
69.
70. }
71.
72. /* UnregisterNatives */
73. void JNI_OnUnload(JavaVM* vm, void* reserved)
74. {
75. JNIEnv* env = NULL;
76. if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
77. {
78. "JNI UnregisterNatives: get env fail");
79. return;
80. }
81. else
82. {
83. "JNI_OnUnload Unregister!");
84. env-> UnregisterNatives(clazz);
85. return;
86. }
87. }
88. </code>
//methods table static JNINativeMethod gMethods[] = { {"A", "(Ljava/lang/Object;)V", (void *)Java_com_hr_renderer_dmr_A}, {"B", "(Ljava/lang/String;)I", (void *)Java_com_hr_renderer_dmr_B}, {"C", "(Ljava/lang/String;)I", (void *)Java_com_hr_renderer_dmr_C}, {"D", "()I", (void *)Java_com_hr_renderer_dmr_D}, {"E", "()Ljava/lang/String;", (void *)Java_com_hr_renderer_dmr_E}, {"F", "()Ljava/lang/String;", (void *)Java_com_hr_renderer_dmr_F}, {"G", "(Ljava/lang/String;Ljava/lang/String;)V", (void *)Java_com_hr_renderer_dmr_G}, {"H", "(Ljava/lang/String;)I", (void *)Java_com_hr_renderer_dmr_H}, {"I", "(Ljava/lang/String;)Ljava/lang/String;", (void *)Java_com_hr_renderer_dmr_I}, {"J", "()Z", (void *)Java_com_hr_renderer_dmr_J}, }; /* define the minimum version * initialization * register native methods. * */jint JNI_OnLoad(JavaVM* vm, void* reserved){ NPT_LogManager::GetDefault().Configure("plist:.level=INFO;.handlers=ConsoleHandler;.ConsoleHandler.colors=off;.ConsoleHandler.filter=42"); JNIEnv* env = NULL; jint result = -1; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { NPT_LOG_INFO("JNI version error!"); return result; } //assert(env != NULL); if (env == NULL) { NPT_LOG_INFO("JNI-----getEnv fail."); return result; } //gJavaVM env->GetJavaVM(&gJavaVM); if (env->ExceptionOccurred()) { NPT_LOG_INFO("JNI-----GetJavaVM fail."); return result; } clazz = env->FindClass(classPathName); if (clazz == NULL) { NPT_LOG_INFO_1("JNI Cannot find %s!", classPathName); return result; } //get MethodID postEventMethodID = env->GetStaticMethodID(clazz, "postEvent", "(Ljava/lang/Object;ILjava/lang/String;Ljava/lang/String;)V"); //if ExceptionOccurred if (env->ExceptionOccurred()) { NPT_LOG_INFO("JNI-----GetStaticMethodID fail."); return result; } //register methods. if (env->RegisterNatives(clazz, gMethods, sizeof(gMethods)/sizeof(gMethods[0])) < 0) { NPT_LOG_INFO("JNI-----RegisterNatives fail."); return result; } NPT_LOG_INFO("JNI_OnLoad-----sucess!"); return JNI_VERSION_1_4;}/* UnregisterNatives */void JNI_OnUnload(JavaVM* vm, void* reserved){ JNIEnv* env = NULL; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { NPT_LOG_INFO("JNI UnregisterNatives: get env fail"); return; } else { NPT_LOG_INFO("JNI_OnUnload Unregister!"); env-> UnregisterNatives(clazz); return; } }
//methods table static JNINativeMethod gMethods[] = { {"A", "(Ljava/lang/Object;)V", (void *)Java_com_hr_renderer_dmr_A}, {"B", "(Ljava/lang/String;)I", (void *)Java_com_hr_renderer_dmr_B}, {"C", "(Ljava/lang/String;)I", (void *)Java_com_hr_renderer_dmr_C}, {"D", "()I", (void *)Java_com_hr_renderer_dmr_D}, {"E", "()Ljava/lang/String;", (void *)Java_com_hr_renderer_dmr_E}, {"F", "()Ljava/lang/String;", (void *)Java_com_hr_renderer_dmr_F}, {"G", "(Ljava/lang/String;Ljava/lang/String;)V", (void *)Java_com_hr_renderer_dmr_G}, {"H", "(Ljava/lang/String;)I", (void *)Java_com_hr_renderer_dmr_H}, {"I", "(Ljava/lang/String;)Ljava/lang/String;", (void *)Java_com_hr_renderer_dmr_I}, {"J", "()Z", (void *)Java_com_hr_renderer_dmr_J}, }; /* define the minimum version * initialization * register native methods. * */jint JNI_OnLoad(JavaVM* vm, void* reserved){ NPT_LogManager::GetDefault().Configure("plist:.level=INFO;.handlers=ConsoleHandler;.ConsoleHandler.colors=off;.ConsoleHandler.filter=42"); JNIEnv* env = NULL; jint result = -1; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { NPT_LOG_INFO("JNI version error!"); return result; } //assert(env != NULL); if (env == NULL) { NPT_LOG_INFO("JNI-----getEnv fail."); return result; } //gJavaVM env->GetJavaVM(&gJavaVM); if (env->ExceptionOccurred()) { NPT_LOG_INFO("JNI-----GetJavaVM fail."); return result; } clazz = env->FindClass(classPathName); if (clazz == NULL) { NPT_LOG_INFO_1("JNI Cannot find %s!", classPathName); return result; } //get MethodID postEventMethodID = env->GetStaticMethodID(clazz, "postEvent", "(Ljava/lang/Object;ILjava/lang/String;Ljava/lang/String;)V"); //if ExceptionOccurred if (env->ExceptionOccurred()) { NPT_LOG_INFO("JNI-----GetStaticMethodID fail."); return result; } //register methods. if (env->RegisterNatives(clazz, gMethods, sizeof(gMethods)/sizeof(gMethods[0])) < 0) { NPT_LOG_INFO("JNI-----RegisterNatives fail."); return result; } NPT_LOG_INFO("JNI_OnLoad-----sucess!"); return JNI_VERSION_1_4;}/* UnregisterNatives */void JNI_OnUnload(JavaVM* vm, void* reserved){ JNIEnv* env = NULL; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { NPT_LOG_INFO("JNI UnregisterNatives: get env fail"); return; } else { NPT_LOG_INFO("JNI_OnUnload Unregister!"); env-> UnregisterNatives(clazz); return; } }