实现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