(Android) NDK

Android NDK | Android Developers 下載 Android NDK (我在 Ubuntu 所以下載 android-ndk-r5c-linux-x86.tar.bz2) 並挑選一個地方解壓縮(此例爲 ~/android-ndk-r5c),除此之外要把 Android SDK 更新至最新版,如果已經安裝好 Android 開發環境,更新方式透過 Eclipse -> [Window]-> [Android SDK and AVD Manager] -> [Installed packages] -> [Update All...]

接着要進行 NDK 環境設置,可查看 android-ndk-r5c/docs/INSTALL.html,可以得知 Android NDK 至少需使用 Android 1.5 系統,而編譯環境至少是 GNU Make 3.8.1,除此之外還需要 Nawk 或 GNU Awk 工具,而常見的 awk 則不適用。

在 Ubuntu 10.04 64-bit desktop 環境上:

$ awk -W version
GNU Awk 3.1.6
Copyright (C) 1989, 1991-2007 Free Software Foundation.
~$ make -version
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc

透過Eclipse 建立一個 android 2.3.3 project,例如 MyNDK:

Project name: MyNDK
Build Target: Android 2.3.3/Android Open Source Project/2.3.3/10
Application name: MyNDK
Package name: com.example.ndk
Create Activity: MyNDK
Min SDK Version: 3

接著,在 Eclipse 左邊 Project Explorer 建立 jni 和 libs 兩個目錄,位置擺在剛剛的 Project 裏(點一下 MyNDK,接着按右鍵選 New -> Folder 輸入 jni,之後在建立 libs 目錄):

MyNDK/jni
MyNDK/libs

在 MyNDK/jni 裏頭新增兩個檔案,分別是 JNI 程式碼和 Android.mk,結構如下:

MyNDK/jni
MyNDK/jni/Android.mk
MyNDK/jni/my-jni.c

其中 Android.mk 和 .c 可以從 android-ndk-r5c/samples/hello-jni/jni 裏頭尋得範例:

MyNDK/jni/Android.mk (參考 android-ndk-r5c/samples/hello-jni/jni/Android.mk)

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := my-jni
LOCAL_SRC_FILES := my-jni.c
include $(BUILD_SHARED_LIBRARY)

MyNDK/jni/my-jni.c (參考 android-ndk-r5c/samples/hello-jni/jni/hello-jni.c)

#include <string.h>
#include <jni.h>
jstring Java_com_example_ndk_MyNDK_stringFromJNI( JNIEnv* env, jobject thiz )
{
    return (*env)->NewStringUTF(env, "Hello from My JNI !");
}

其中要留意 function name,裏頭包括 packages name 和 Activity name 等信息,此例是 com_example_ndk 和 MyNDK。

接著要透過 android ndk 去編譯 my-jni.c,除了在 Command line 可以切換到 MyNDK 目錄,用 android-ndk-r5c/ndk-build 進行編譯外,還可以透過 Eclipse 設定好,讓你每次自動編譯好:

Properties for MyNDK

在 Eclipse 左邊 Project Explorer 點選 MyNDK,選右鍵 -> Properties -> Builders -> New -> Program

在 Main 分頁:

Name: NDK_Builder
Location(ndb-build位置): /home/user/android-ndk-r5c/ndk-build
Working Directory:(project位置): ${workspace_loc:${project_path}}

Builders

在 Refresh 分頁:

將 Refresh resources upon completion 打勾,並且在 Specific resources 選擇 MyNDK/libs 目錄

在 Build Options 分頁:

勾選 Allocate Console(necessary for input)、Launch in backgroud、After a "Clean"、During manual builds、During auto builds 和 Specify working set of relevant resources

在 Specific resources 選擇 MyNDK/jni

如此一來,只要編譯或清除時,自動會編譯jni 的部份,可以使用 Build all(快捷鍵Ctrl+B) 試試,可以看到 Console 的輸出:

Compile thumb  : my-jni <= my-jni.c
SharedLibrary  : libmy-jni.so
Install        : libmy-jni.so => libs/armeabi/libmy-jni.so

接着,才正式要寫 Java 程式部份,切換到 MyNDK.java:

package com.example.ndk;

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

public class MyNDK extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.main);
        TextView  tv = new TextView(this);
        tv.setText( stringFromJNI() );
        setContentView(tv);

    }
    public native String  stringFromJNI();
    static {
        System.loadLibrary("my-jni");
    }

}

其中特別的是要宣告 jni 使用到的函數,這跟 my-jni.c 的宣告有關,以及 System.loadLibrary 的部份,跟 jni/Android.mk 設定的編譯結果也有關係,如果都不相符,執行時會出現 exception。

最後跑起來的效果:

MyJNI

整個Project結構:

Project Explorer




One Error on NDK-r8d

failed. d:/Development/android/android-ndk-r8d/build/gmsl/__gmsl:512: *** non-numeric second argument to `wordlist' function: ''. Stop.

Solution:

int_encode = $(__gmsl_tr1)$(wordlist 1, $1,$(__gmsl_input_int))
=>
int_encode = $(__gmsl_tr1)$(wordlist 1,$(words $1),$
(__gmsl_input_int))




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