首先整個實現需要有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