模仿android_debug_JNITest实现apk 调用framework java JNI中方法
首先整个实现需要有Android源码编译环境。这里我用的是froyo2.2.
1.JNI层--C++代码部分
在目录frameworks/base/core/jni 下创建android_jnidemo_Hello.cpp(文件名称对应后面java实现的包名)代码内容可参考android_debug_JNITest.cpp。注:如果把函数声明单独放到.h文件中,Hello.h可放到base/include/android_runtime目录或者自己创建的目录base/include/...../ 在.cpp文件中引入#include "android_runtime/Hello.h"
#define LOG_TAG "Demo Jni" #include "jni.h" #include "nativehelper/JNIHelp.h" #include "utils/Log.h" #include "utils/misc.h" namespace android {//android 命名空间 /* *return string to app */ static jstring android_jnidemo_Hello_getString(JNIEnv *env, jclass clazz) { ALOGI("jni return a string!"); return env->NewStringUTF("Hello framework JNI!");//创建返回一个字符串 } /** *registtration */ static JNINativeMethod gMethods[] = { {"getString", "()Ljava/lang/String;", (void *) android_jnidemo_Hello_geString}, }; int register_android_jnidemo_Hello(JNIEnv* env) { return jniRegisterNativeMethods(env, "android/jnidemo/Hello", gMethods, NELEM(gMethods)); } }
1.1 执行编译处理实现
修改android_jnidemo_Hello.cpp同目录的Android.mk文件。变量LOCAL_SRC_FILES:= \后加入android_jnidemo_Hello \
修改同目录下的AndroidRuntime.cpp 文件在extern int 后面添加
extern int register_android_jnidemo_Hello(JNIEnv* env);
然后在static const RegJNIRec gRegJNI[] = {
添加
REG_JNI(register_android_jnidemo_Hello),这样整个JNI 部分就完成了。
2.添加Java 代码
frameworks/base/core/java/android/jnidemo 自己创建目录jnidemo,java 类Hello.java
package android.jnidemo;//包名对应.cpp文件 public class Hello { public Hello() {} //app will call this native method public static native String getString(); }
这里的java类中并不需要想,app java结合NDK实现JNI使用那样需加入
static {
System.loadLibrary("xxx");//动态库
}
应该是上面添加到AndroidRuntime 动态库,使虚拟机启动后就载入了。
3.创建一个apk项目Android project Hello
package com.integration.test; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; import android.jnidemo.Hello; //import自己定义的包 public class HelloActivity 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); Hello hello = new Hello(); //创建自己写的framework java 对象 tv.setText(hello.getString());//调用native method } }
3.1保留Hello项目下res/ src/ AndroidManifest.xml 文件,并拷贝项目到源码目录package/apps/下,在项目根目录下添加Android.mk文件
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-subdir-java-files) #HelloJNI project name LOCAL_PACKAGE_NAME := HelloJNI include $(BUILD_PACKAGE)
4.将Hello项目加入到系统编译中
在build/target/product/generic.mk文件 变量PRODUCT_PACKAGES := \后面加上HelloJNI \(对应Android.mk文件的LOCAL_PACKAGE_NAME
值)
5.编译
5.1切换到源码根目录下执行. build/envsetup.sh 初始化编译环境(若在此之前没执行过编译命令)
在执行lunch 1 选择编译的产品-----这里我的是默认编译generic
5.2编译前面添加的JNI代码,Android 的编译都是以模块位单位的,Android_Runtime是一个独立模块。
执行命令mm Android_Runtime 重新生成libandroid_runtime.so库,看到Install: out/target/product/generic/system/lib/libandroid_runtime.so结果
编译framework java部分,执行 mm framework
重新编译生成 framework.jar
Install: out/target/product/generic/system/framework/framework.jar
5.3编译Hello apk项目
执行命令mmm package/apps/Hello或者mm HelloJNI 生成HelloJNI.apk out/target/product/generic/system/app目录下
6.重新生成system.img文件
执行命令 make snod 得到新的 out/target/product/generic/system.img
7.启动emulator 打开HelloJNI apk查看结果(不截图了)
执行命令emulator& (前提在PATH环境变量中加入system.img ..... 镜像路径和emulator可执行文件路径
/usr/froyo/out/host/linux-x86/bin:/usr/froyo/out/target/product/generic)
也可以
emulator -kernel ./prebuilt/android-arm/kernel/kernel-qemu -sysdir ./out/target/product/generic -system system.img -data userdata.img -ramdisk ramdisk.img