Pages

2012/07/20

建立自己的Android JNI程式


本篇介紹如何重頭開始建立自己的Android JNI程式.

1.開啟Eclipse, 並進入之前建立好的Workspace.
2.在此Workspace建立新專案, Eclipse 功能表->File->New->Android Project.
3.填入專案資訊, 注意最好將專案位置放在Cygwin中, 因為才可以讓 Android NDK自動編譯.




















4.按下Finish,回到Eclipse主畫面, 看到Package Explorer中新增MyFirstJNI專案,會自動建立幾個APK專案的目錄.

















5.接下來手動新增2個目錄, JNI與libs, JNI目錄是用來放C/C++的JNI source code, libs則是放產生的.so 動態連結函式庫.
6.在JNI中需要建立基本的2個檔案, Android.mk與你的C/C++檔案.
   Android.mk的內容如下
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := first-jni
LOCAL_SRC_FILES := first-jni.cpp
include $(BUILD_SHARED_LIBRARY)


first-jni.cpp是你的C++原始檔檔名, first-jni則是會被compile成函式庫的名稱,最後的檔案名稱就會是libfirst-jni.so

7.C與C++檔案需要再詳細解說一下, 如果是用C檔案,副檔名使用.c,使用C++檔案則是用.cpp,
有什麼差別呢? 有很大差別,會跟你的 code有關係, 因為JAVA 呼應JNI時是使用C的函式來呼叫使用, 所以如果是用C++檔案時, JNI的函式介面需要轉換成C函式才行.以下是範例.

/*
*  first-jni.c
*/
#include <string.h>
#include <jni.h>

jstring
Java_my_project_MyFirstJNI_MyFirstJNI_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )
{
    return (*env)->NewStringUTF(env, "My first JNI!");
}
/*
*  first-jni.cpp
*/
#include <string.h>
#include <jni.h>

extern "C"
jstring
Java_my_project_MyFirstJNI_MyFirstJNI_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )
{
    return env->NewStringUTF("My first JNI!");
}

C++的函式需要使用extern "C"的方式來export.參數env的使用方法也不一樣.

8.JNI export的函式命名也是有規則的,此連結有說明, 規則如下
Java_{Package名稱,點換成底線}_{Class name}_{function name}()
以我們要建立的範例來看"Java_my_project_MyFirstJNI_MyFirstJNI_stringFromJNI"
"my_project_MyFirstJNI"就會是我們的package名稱, "package  my.project.MyFirstJNI;"
"MyFirstJNI"就會是我們建立的class名稱.
"stringFromJNI"就是我們在JAVA code中要呼叫的函式名稱了.

9.在Eclipse的Package Explorer中按下F5 refresh, 會出現我們建立的2個目錄(JNI,libs)與2個檔案.


















10.接下來設定自動編譯, 在專案名稱上按右鍵,
     進入Properties.選擇Builders.
     在Builders右邊畫面選擇New.
     在跳出視窗中選擇Program,按下OK.
     接下來設定Builder, 可以參考此篇文章.

     Name: MyFirstJNI_Builder
     Locations:I:\cygwin\bin\bash.exe
     Working Directory:I:\cygwin\bin
     Arguments: --login -c "cd /JNI/MyFirstJNI && ndk-build"
     這裡的 /JNI/MyFirstJNI 目錄位置.不同專案需要設定不同的路徑.是相對於在Cygwin中login的home目錄位置.


11.同樣在此視窗中切換到Refresh頁面.勾選Refresh resources upon completion.選擇Specific resources.
12.在跳出的視窗(Edit Working Set)中, 選擇MyFirstJNI下的libs目錄.按下Finish離開.
















13.切換到Build Options, 勾選下列設定:
     Allocate Console
     Launch in background
     After a "Clean"
     During manual builds
     During auto builds
     Specify working set if relevant resources.
14.點選Specify Resources, 選擇 MyFirstJNI下的JNI目錄, 當此目錄中檔案有變動時, 即啟動編譯.
15.設定完成後, 回到Eclipse, 打開我們的JNI檔案,first-jni.cpp, 隨便編輯一下後存檔.即可開始自動編譯, 完成後會出現函式庫檔案.










16.目前為止以成功產生我們的函式庫了, 但JAVA端還沒有來呼叫使用.
17.編輯 MyFirstJNI.java, 如以下程式.
package my.project.MyFirstJNI;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MyFirstJNI extends Activity 
{
    // Called when the activity is first created.
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        TextView  tv = new TextView(this);
        tv.setText( stringFromJNI() );
        setContentView(R.layout.main);
    }
    // A native method that is implemented by the
    // 'first-jni' native library, which is packaged
    // with this application.
    //

    public native String  stringFromJNI();
    
    // this is used to load the 'first-jni' library on application
    // startup. The library has already been unpacked into
    // /data/data/my.project.MyFirstJNI/libs/libfirst-jni.so at
    // installation time by the package manager.
    //
    static 
    {
        System.loadLibrary("first-jni");
    }
}
18.編輯完成後,在Emulator中執行程式,會出現"My first JNI!"字串.

No comments:

Post a Comment