Android平臺NDK編程

轉自:http://blog.csdn.net/wangbin_jxust/article/details/37389383html

以前在進行cocos2dx開發時,已經詳細介紹瞭如何將win32的c++代碼移植到Android平臺,當再次回顧時,發現一些基礎的東西理解並非很完全,今天使用Android NDK提供的一個例子作一個簡單的移植。在進行該demo前,請確認你已經配置了Android開發環境和安裝了最新的Android NDK。java

1.建立Android項目

建立一個Android項目 , 包名是com.example.hellojni,建立一個Activity做爲程序進入的Acitivity,命名爲HelloJni。c++

2.建立 C 文件

建立一個C文件,放一個函數,該函數的做用是獲取當前cpu架構並以字符串的形式返回。請注意該函數的格式: Java_包名的下劃線鏈接_Java文件名_java函數名。架構

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

jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )
{
#if defined(__arm__)
  #if defined(__ARM_ARCH_7A__)
    #if defined(__ARM_NEON__)
      #define ABI "armeabi-v7a/NEON"
    #else
      #define ABI "armeabi-v7a"
    #endif
  #else
   #define ABI "armeabi"
  #endif
#elif defined(__i386__)
   #define ABI "x86"
#elif defined(__mips__)
   #define ABI "mips"
#else
   #define ABI "unknown"
#endif

    return (*env)->NewStringUTF(env, "Hello from JNI !  Compiled with ABI " ABI ".");
}

 

3.配置JNI

在該Android項目的根目錄(即AndroidManifest.xml文件所在目錄)下建立一個文件夾,命名爲jni(注意,文件名不能寫錯哦)函數

在jni目錄下,建立Android.mk和Application.mk兩個文件,同時將C文件也放進jni文件夾下面來。以下:ui

這裏的nick文件夾,能夠先忽略不看,這是爲後面的打包多個so準備的。spa

a.配置Android.mk文件

Android.mk文件實際上一個很小的NDK構建腳本,它的語法在: NDK安裝目錄/docs/ANDROID-MK.html,下文代碼也對一些基本屬性添加了註釋。.net

#返回當前文件在系統中的路徑,mk文件開始時必須定義該變量
LOCAL_PATH := $(call my-dir)

#CLEAR_VARS 變量由構建系統提供,由於有大量的全局變量,在本次構建前,清除上一次的
include $(CLEAR_VARS)
#LOCAL_MODULE 實際是項目名,用於區分各個項目,名字必須是惟一的並且不包含空格,最終的so庫,命名也會是   lib項目名.so
LOCAL_MODULE    := hello-jni
#要編譯的c or cpp文件,注意不須要在這裏列舉頭文件或者include的文件,構建系統會自動幫你依賴這些文件
LOCAL_SRC_FILES := hello-jni.c
#構建系統提供的變量
include $(BUILD_SHARED_LIBRARY)

 

b.配置Application.mk文件

Application.mk文件其實是對應用程序自己描述的文件,它定義了應用程序須要的功能模塊的列表、針對不一樣cpu架構打包不一樣的so]、要構建release或者debug包等。debug

APP_ABI := XXX,這裏的XXX就是指不一樣的平臺,能夠選填的有x86,armeabi,armeabi-v7a,mips,all,值得一提的是,選擇all,則會構建出全部平臺的so,若是不填該項,默認構建爲armeabi的。同時,做者也作過一個實驗,構建armeabi平臺的so是能夠運行在intel x86架構cpu平臺的,可是構建x86平臺的so則不能在armeabi平臺上運行的,這樣看來,應該是intel針對armeabi作了兼容,可是若是想要so  以最小的能耗運行在intel x86平臺,仍是要指定構建的so爲x86平臺。code

4.打包so以及如何打包多個so

在當前Android項目的根目錄下,運行 NDK安裝路徑/ndk-build,則開始打包so。

另外,若是運行    NDK安裝路徑/ndk-build clean,會clean當前全部的so;

運行 NDK安裝路徑/ndk-build -B V=1,則強制從新打包,

若是想要打包多個so,則能夠在Android.mk定義多個modules,或者寫多個Android.mk,每一個Android.mk定義一個modules,我這裏在jni目錄下又建立了一個nick文件夾,用於放置新的C文件。

此時,只須要改動jni目錄下的Android.mk,再次對nick文件夾的C代碼打包便可。jni下的Android.mk文件:

#返回當前文件在系統中的路徑,mk文件開始時必須定義該變量
LOCAL_PATH := $(call my-dir)

#CLEAR_VARS 變量由構建系統提供,由於有大量的全局變量,在本次構建前,清除上一次的
include $(CLEAR_VARS)
#LOCAL_MODULE 實際是項目名,用於區分各個項目,名字必須是惟一的並且不包含空格,最終的so庫,命名也會是   lib項目名.so
LOCAL_MODULE    := hello-jni
#要編譯的c or cpp文件,注意不須要在這裏列舉頭文件或者include的文件,構建系統會自動幫你依賴這些文件
LOCAL_SRC_FILES := hello-jni.c
#構建系統提供的變量
include $(BUILD_SHARED_LIBRARY)

#對nick文件夾下的代碼打包so
include $(CLEAR_VARS)
LOCAL_MODULE    := hello-jni-mine
LOCAL_SRC_FILES := nick/hello-jni.c
include $(BUILD_SHARED_LIBRARY)

 

是的,你沒看錯,從新加上LOCAL_MODULE和LOCAL_SRC_FILES變量從新配置一下便可。

5.jni調用

在Activity中,咱們使用static 關鍵詞將加載so放在函數體中,以保證直接先加載so.

static {
        System.loadLibrary("hello-jni");
    }

要注意的是,System.loadLibrary()中填寫的並非完整的so名,而是去掉前綴lib和後綴.so的,也就是Android.mk中的LOCAL_MODULE變量。

 

java層的函數要用native關鍵詞聲明此次調用native層的函數,若是該java函數是public native String  XXXX(),那麼在這裏就是調用C代碼中的Java_com_example_hellojni_HelloJni_stringFromJNI()函數。

以上就是Android平臺打包so和調用的一個最基本的demo,其實整個流程仍是比較簡單的,有一些規定的命名是不能隨便修改的,若是jni文件夾名,Android.mk,Application.mk文件名,被java層調用的C函數命名等,這些都是有規則的。

相關文章
相關標籤/搜索