Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 兩分鐘學會Android平台NDK編程(無須Eclipse和cygwin,可使用命令行打包多個so)

兩分鐘學會Android平台NDK編程(無須Eclipse和cygwin,可使用命令行打包多個so)

編輯:關於Android編程

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

1.創建Android項目

創建一個Android項目 , 包名是com.example.hellojni,創建一個Activity作為程序進入的Acitivity,命名為HelloJni。

2.創建 C 文件

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

#include 
#include 

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文件夾下面來。如下:

vcWxvqOsy/y1xNPvt6jU2jogTkRLsLLXsMS/wrwvZG9jcy9BTkRST0lELU1LLmh0bWyjrM/CzsS0+sLr0rK21NK70Km7+bG+yvTQ1MztvNPBy9eiys2hozwvcD4KPHA+PC9wPgo8cHJlIGNsYXNzPQ=="brush:java;">#返回當前文件在系統中的路徑,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包等。

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平台。

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函數命名等,這些都是有規則的。



  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved