写在前面的话:
?? 这篇文章很早就发表在我自己原先的那个blog中,因为忍受不了原先blog的乱码问题所以才在这里开了这个blog,现在把它正式地移到这个blog上来,不要说我抄袭哦^-^。
?
练习:从jni层获得一个字符串,在屏幕上显示,当然是手机屏幕 
要求:
1.需要包含三层结构:JNI, java framework, java application 
2.字符串的内容为“Hello from JNI !”,必须在JNI层定义
 
这个练习是在Android的源码工程下做的,我的Android源代码路径为/Android/android-1.6_r2
 
开工:
1.? 
JNI层
 :在
 /Android/android-1.6_r2/frameworks/base/core/jni
 路径下创建例子
 android_mytest_hellojni.cpp
 文件,这个文件就是在
 JNI
 层实现接口。文件内容如下:(可参考同一目录下的
 android_debug_JNITest.cpp
 文件编写)
 
| 
 #
define
 LOG_TAG "HelloJNI"
 #
include
 "jni.h"
 #
include
 "nativehelper/JNIHelp.h"
 #
include
 "utils/Log.h"
 #
include
 "utils/misc.h"
  namespace
 android {
 static
 jstring android_mytest_hellojni_displayString(
JNIEnv *
env,
 jclass clazz)
 {
 
?return
 env-
>
NewStringUTF(
"Hello from JNI!"
)
;
 }
 
  /* 
?* JNI registration. 
?*/
 static
 JNINativeMethod gMethods[
]
 =
 {
 
????/* name, signature, funcPtr */
 
????{
 "displayString"
,
 "()Ljava/lang/String;"
,
 
????????????(
void
*
)
 android_mytest_hellojni_displayString }
,
 
???? }
;
 int
 register_android_mytest_hellojni(
JNIEnv*
 env)
 {
 //此处的目录结构就是在Javaframework层的文件目录,且必须一致 
 return
 jniRegisterNativeMethods(
env,
 "android/mytest/hellojni"
,
  
????????gMethods,
 NELEM(
gMethods)
)
;
 }
 }
;
 
 | 
2. 
JNI
 层:对编译的修改配置
 
? 2.1修改/Android/android-1.6_r2/frameworks/base/core/jni目录下的Android.mk
 文件,在LOCAL_SRC_FILES:= \
 下面加上
android_mytest_hellojni.cpp \
 
?? 2.2修改/Android/android-1.6_r2/frameworks/base/core/jni目录下的AndroidRuntime.cpp
 文件在extern int
 后面添加
extern int register_android_mytest_hellojni(JNIEnv* env);
 
然后在static const RegJNIRec gRegJNI[] =
 {下面添加
REG_JNI(register_android_mytest_hellojni),
 
这样,JNI层的修改就到此为止了。
?
3. ? 
Javaframework
 层:在
 /Android/android-1.6_r2/frameworks/base/core/java/android/ 
新建文件目录
 mytest
 ,在该目录下新建文件
 hellojni.java
 声明接口。内容如下:(可以参考
 android-1.6_r2/frameworks/base/core/java/android/debug
 目录下的
 JNITest.java
 文件编写)
 
| 
 package
 android.
mytest;
 public
 class
 hellojni{
 
????public
 hellojni(
)
{
}
 //此处声明为public所以才可以被application调用 
 
????public
 static
 native
 String
 displayString(
)
;
  }
 
 | 
4
 .下面我们要对我们做过更改的
 libandroid_runtime.so
 和
 framework.jar
 进行重新编译。
 
在源代码工程目录下输入
 make libandroid_runtime
 重新编译生成
 libandroid_runtime.so
 
…
 
target thumb C++: libandroid_runtime <= frameworks/base/core/jni/android_mytest_hellojni.cpp
 
target thumb C++: libandroid_runtime <= frameworks/base/core/jni/AndroidRuntime.cpp
 
target
 SharedLib: libandroid_runtime 
(out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_runtime_intermediates/LINKED/libandroid_runtime.so)
 
target Prelink: libandroid_runtime (out/target/product/generic/symbols/system/lib/libandroid_runtime.so)
 
target Strip: libandroid_runtime (out/target/product/generic/obj/lib/libandroid_runtime.so)
 
Install: out/target/product/generic/system/lib/libandroid_runtime.so
 
然后再输入
 make framework
 重新编译生成
 framework.jar
 
…
 
Install: out/target/product/generic/system/framework/framework.jar
 
5. ? 
然后在
 eclipse
 里面或者在记事本等编辑器(这么说只是为了说明只需要源代码),新建
 Android project
 ,例子的结构如下:
在
 testApp.java
 文件中的内容如下:
 
| 
 package
 com.
integration.
test;
 import
 android.
app.
Activity
;
 import
 android.
os.
Bundle;
 import
 android.
widget.
TextView;
 //需要import自己定义的包,包名可以根据文件目录结构得到 
  import
 android.
mytest.
hellojni;
  public
 class
 testAPP extends
 Activity
 {
 
????/** Called when the activity is first created. */
 
????private
 TextView tv;
 
????@Override
 
????public
 void
 onCreate(
Bundle savedInstanceState)
 {
 
????????super
.
onCreate(
savedInstanceState)
;
 
????????setContentView(
R.
layout
.
main)
;
 
????????tv =
 (
TextView)
findViewById(
R.
id
.
tv)
;
 
????????hellojni hello =
 new
 hellojni(
)
;
 //调用自己写的JNI 
 
????????tv.
setText
(
hello.
displayString(
)
+
""
)
;
 
????}
 }
 
 | 
然后将上述文件复制到
 /Android/android1.6_r2/packages/apps
 ,然后看教程《在源码中编译自己的
 
Android project
 
》就可以在模拟器中看到该应用运行如下图: