模仿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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章