2012年6月25日 星期一

Eclipse+Android SDK/NDK 開發環境的過程 (2/2)

接...Eclipse+Android SDK/NDK 開發環境的過程 (1/2)

接著要整合 NDK 產生的 lib (as xx.so) 能在 Eclipse 專案裡使用...

---------------------------------------------------------------------

46. 測試 NDK 與 Eclipse 整合 (僅開發 C/C++ libraries 需要)

47. 執行 Eclipse.exe

48. 開啟 step 25~31 的專案為基礎, 如果沒有請重做

49. 在 Package Explorer 下新增一個目錄 'jni'

50. 在 'jni' 目錄下新增一個 'File' 命名為 Andriod.mk, 編輯內容如下

    LOCAL_PATH := $(call my-dir)

    include $(CLEAR_VARS)

    # Here we give our module name and source file(s)
    LOCAL_MODULE    := hello
    LOCAL_SRC_FILES := hello.c

    include $(BUILD_SHARED_LIBRARY)

    P.S. 如果 C 文件不只一個可以在 LOCAL_SRC_FILES 裡面列出



51. 在 'jni' 目錄下新增一個 'File' 命名為 hello.c, 編輯內容如下

    #include <string.h>
    #include <jni.h>

    jstring Java_com_xx_hello_HelloActivity_stringFromJNI(
        JNIEnv* env, jobject javaThis)
    {
    return (*env)->NewStringUTF(env, "Hello from native C code!");
    }

    NOTE: 以上函數命名的方式, 不能隨便取, 必須符合 java 的規範, 規則是:

          在呼叫 C 的 Java 程式中是

      package com.xx.hello;
          ...
      public class HelloActivity extends Activity {
      ...

          所以函數命名開頭是:

      1) package com.xx.hello ->
          Java_com_xx_hello_...
          接者
      2) public class HelloActivity extends Activity ->
          HelloActivity_...
          最後
      3) stringFromJNI 是在 java 中實際要呼叫的函數名稱

      以上 Java_com_xx_hello_ + HelloActivity_ + stringFromJNI 三個
      組合起來, 請依真實情況修改函數名字

52. 修改 HelloActivity.java, 如下參見 1,2,3,4,5

    ...
    // 1. need to use AlertDialog later (just for verifying)
    import android.app.AlertDialog;

    public class HelloActivity extends Activity {

    // 2. load the library - name matches jni/Android.mk
    static {
        System.loadLibrary("hello");
    }

    // 3. declare the native code function - must match hello.c
    private native String stringFromJNI();

    ...
    public void onCreate(Bundle savedInstanceState) {
    ...
        // 4. this is where we call the native code
        String hello = stringFromJNI();

        // 5. show this string (just for verifying)
        new AlertDialog.Builder(this).setMessage(hello).show();
    }
    ...

---------------------------------------------------------------------

53. (1)(用手動建立 libhello.so) 或 (2)

54. 執行 cygwin.bat (step 35 安裝目錄下)

55. 切換當前目錄到 project 所在的目錄下, 如 C:\oo\workspace\hello\

    NOTE: 請依真實情況修改路徑名

    命令列提示字元 $ 下, 請輸入 cd /cygdrive/c/oo/workspace\hello
    後, 按 Enter 鍵執行

    如果正確, 當前目錄提示會改為以上路徑

56. 執行 ndk-build

    命令列提示字元 $ 下, 請輸入 /cygdrive/c/xx/android-ndk/ndk-build
    後, 按 Enter 鍵執行

    NOTE: 請依真實情況修改路徑名

    如果正確, 此時 NDK 開始編譯 c 並做出 so (為 library)

    P.S. 檢查 C:\oo\workspace\hello\libs\armeabi\ 下有沒有做出
         libhello.so

57. 結束 cygwin 視窗, 回到 Eclipse, menu-> 'Run' -> 'Run'

    如果一切順利, AVD 上面會有正確的結果 (彈出 AlertDialog 顯示 C 程式  
    庫的指定的字串), 如果不正常結束, 可能是 Library 沒有正確連結, 請檢
    查一下執行時期的 log 訊息,

    menu -> 'Window' -> 'Show View' -> 'LogCat'

    ...
    AndroidRuntime: Caused by: java.lang.UnsatisfiedLinkError: Library
    hello not found
    ...

---------------------------------------------------------------------


58. (2) (用 Eclipse 每次編譯(refresh)時自動建立 libhello.so)

59. menu -> 'Project' -> 'Properties', 開啟 Properties for xx 對話盒

60. 點選 Builders 項目, 按下 'New...', 開啟 Choose configuration type
    對話盒

61. 點選 Program 項目, 按下 'OK', 開啟 Edit launch configuration
    properties 對話盒

    Name: 隨你高興        (建議取有意義的字, NDK Builder likes)
  
    Main 標籤頁下:

        Location: C:\cygwin\bin\bash.exe
        Working Directory: (留白)
        Arguments:
        --login -c "cd '${project_loc}' && /cygdrive/c/android-ndk/ndk-build"

    NOTE: 以上 cygwin 及 android-ndk 路徑, 請依真實情況修改

    Refresh 標籤頁下:

        Refresh resources upon completion    打勾
  
    ??  選取下方的
        The Entire workspace
        或
        Specific resources 項目
        按 'Specify Resources...' 按鈕, 將專案中的 libs 目錄(*)打勾

        P.S. (*) 第一次建立 jni 時還沒編譯過可能沒有 libs 目錄

        Recursive include sub-folders       打勾      
  
    Environment 標籤頁下:

        (留白)

    Build Options 標籤頁下:

        Allocate Console       打勾
        File                   不勾

        Launch in background   打勾

        After a "Clean"        打勾 (或不勾看你習慣)
        During manual builds   打勾
        During auto builds     打勾
        During a "Clean"       不勾 (或勾看你習慣)

        Specify working set of relevant resources  打勾
        按 'Specify Resources...' 按鈕, 將專案中的 jni 目錄打勾

    設置好後, 按 'OK' 回到上一層對話盒, 再按 'OK'

62. 此時, 你的 hello.c 會依 Run the builder 指定時機自動編譯, 或修改一
    下 hello.c 內容, 按 F5 Refresh

    Eclipse 的 Console 視窗會同手動一樣顯示 ndk-build 結果

---------------------------------------------------------------------

最後: 有圖有真相






Q&A:
---------------------------------------------------------------------
Q1: It appeared "Android requires compiler compliance level 5.0 or 6.0.
    Found '1.7' instead. Please use Android Tools > Fix Project
    Properties" message

A:  (from stackoverflow)

    That isn't the problem, Android SDK isn't x64, but works ok with
    x64 jvm (and x64 eclipse IDE).

    As it said, you must set project compatibility to Java 5.0 or
    Java 6.0.

    Right-click on your project and select "Properties", pick
    "Java Compiler", check "Enable project specific settings" and
    select 1.5 or 1.6 from "Compiler compliance settings" select box
    and click Apply.

Q2: After apk compiled can't run, it said "This selection cannot be
    launched and there are no recent launches"
   
A:  Use 'Run As" 'Andriod application'

Q3: After run as it said "Android library projects cannot be launched"

A:  Please don't run as library.

    Right-click on your project and select "Properties", pick
    "Andriod", unselect the "is Library" checkbox and click Apply.

沒有留言:

張貼留言