在 Android 上運行 C 語言
Android的應用程式主要是透過Java來開發,而Java本身提供了JNI(Java Native Interface)這個機制,讓使用Java寫出來的應用程式可以跟其他語言的函式庫做溝通。本篇文章就來介紹如何透過JNI讓Android運行C語言。
參考資料:
在Android使用JNI
Add C and C++ Code to your project
Android Native Development Kit Cookbook - Feipeng Liu
泰勞本身的作業環境如下:
OS: Ubuntu 16.04
IDE: Android Studio 2.1.2
Java: Open JDK 1.8.0_111
NDK: android-ndk-r12b
前置作業:
到官網下載Android NDK並將路徑設定好。
#設定NDK路徑
開啟新專案 > 打開local.properties加入NDK路徑 > ndk.dir=/xxx/yyy/zzz/android-ndk-r12b
#創建JNI目錄
在main目錄底下創建JNI Folder。
#新增Android.mk檔
在JNI目錄下創建一個Android.mk檔,內容如下:
#新增Application.mk檔
在JNI目錄下創建一個Application.mk檔,內容如下:
#修改build.gradle(Module:app)
打開build.gradle, 在defaultConfig裡面加入以下內容:
#新增main.c 在JNI目錄下創建main.c,依照JNI的語法寫入簡單的方法。
#指定Library並宣告Native方法
在Java裡指定Library並宣告Native方法。
接著只需在主程式裡呼叫StringFromJNI這個Native方法,即可得到C語言回傳的字串"Hello JNI!"
打鐵要趁熱,再多做一些簡單的練習吧!
#加入運算方法
在JNI目錄下創建math.c,一樣依照JNI的語法寫入簡單的方法。
別忘了在Android.mk裡的LOCAL_SRC_FILES後面加上math.c
並於主程式宣告新增的Native方法。
此時於程式裡呼叫並將參數帶入NativeAddition這個Native方法,就會得到透過C語言運算的結果。
#錯誤訊息
如果很不幸的在編譯時出現以下錯誤訊息:
Set "android.useDeprecatedNdk=true" in gradle.properties to continue using the current NDK integration.
請在gradle.properties檔案裡加入
#Debug
有時後會需要加入Log至C語言的部份來做Debug,需要遵循以下步驟。
參考資料:
Android-JNI中的log打印
1.加入以下標頭檔
2.定義LOG標籤與類型
3.修改Android.mk
加入以下內容:
4.修改build.gradle(app)
5.使用方式
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdIjBtetRQW44FRYEHK0TOaxnHU5s0A0fs81sKCbyooM9nkE3nz87dub0S58ZMm7Z3aWVIcJBGs9dZ6q8YROfdfjjyq_bnR_k3eODzJTqaitv-iRh4fB3XrWTk0kb0Rn3sYkeYW8sCGWvi/s640/jni_log_use.png)
以上就是簡單的實作方式與步驟,大家快去動手做作看吧!
參考資料:
在Android使用JNI
Add C and C++ Code to your project
Android Native Development Kit Cookbook - Feipeng Liu
泰勞本身的作業環境如下:
OS: Ubuntu 16.04
IDE: Android Studio 2.1.2
Java: Open JDK 1.8.0_111
NDK: android-ndk-r12b
前置作業:
到官網下載Android NDK並將路徑設定好。
#設定NDK路徑
開啟新專案 > 打開local.properties加入NDK路徑 > ndk.dir=/xxx/yyy/zzz/android-ndk-r12b
#創建JNI目錄
在main目錄底下創建JNI Folder。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm9ZOCK2pvdQg-oGmPDbessi6S3vUYlUNYPbC0-ogoSxGGuup5bV1Us_gpeUZ5EjCVFzU4rVfmGITX8ouTH3EmThylDTrdmegfNoAeTHxBeF_RyesqkMa8kI60kSkh8nw22mC4TsmI8n9y/s320/JNIfolder.png)
#新增Android.mk檔
在JNI目錄下創建一個Android.mk檔,內容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := jni_hello (java要呼叫的名稱)
LOCAL_SRC_FILES := main.c (對應的檔案)
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := jni_hello (java要呼叫的名稱)
LOCAL_SRC_FILES := main.c (對應的檔案)
include $(BUILD_SHARED_LIBRARY)
#新增Application.mk檔
在JNI目錄下創建一個Application.mk檔,內容如下:
APP_ABI:= all (可在哪些CPU上運行)
#修改build.gradle(Module:app)
打開build.gradle, 在defaultConfig裡面加入以下內容:
defaultConfig {
applicationId "chen.kuanlin.jnihello"
minSdkVersion 21
targetSdkVersion 25
versionCode 1
versionName "1.0"
ndk {
moduleName "jni_hello"
}
}
applicationId "chen.kuanlin.jnihello"
minSdkVersion 21
targetSdkVersion 25
versionCode 1
versionName "1.0"
ndk {
moduleName "jni_hello"
}
}
#新增main.c 在JNI目錄下創建main.c,依照JNI的語法寫入簡單的方法。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9FwBMLRMLgqO8B7sP5L68aEX-Em6lRTlsjZ5waOKSoNPBnomk80ycjyXPt_EnyImu3_KSeYQcnDwa5g6PG3PsUJSKWePV2dztWHNRLB1WzYQpJCqTt-3mdaxB8yHhrwWntjyIV6zu2yVC/s640/main_c.png)
#指定Library並宣告Native方法
在Java裡指定Library並宣告Native方法。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxDUnbVdODG0jLFBDRFVl4ArtCC3MY8dzNg59hFTBid0kcK1I4G1d-2lPPRF9VI6mQqwVDz05R9WMHzuGyFUwDge7gne6Sgc-XsoXTRPIB1xcZtVxgAyhT5I_-A5a5n534JoKykZhcPvkm/s640/Native_method.png)
接著只需在主程式裡呼叫StringFromJNI這個Native方法,即可得到C語言回傳的字串"Hello JNI!"
打鐵要趁熱,再多做一些簡單的練習吧!
#加入運算方法
在JNI目錄下創建math.c,一樣依照JNI的語法寫入簡單的方法。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAH7SJFjFR806irq4SWOVVfFSlJErKNIxDgbDkFgfAA9rVuDRer6LXdIZS3AfvfIbhZ3sOlY3WZRuiSVht639MqjWfaYO0mnZJM6yNFpB08oXkXPd1KHMHyxtOjC9EFprL8hXHQF3U4ssn/s640/math_c.png)
別忘了在Android.mk裡的LOCAL_SRC_FILES後面加上math.c
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgefLpcNcMY7Lc2hQfKiDV7pDruQ7nsJWF7R14YRu2kQfnf2augRivaLB9Heu23A8T0TC1xXPIwEV63B8ns9NFXgyoGbPFPJaxmywJKv0-9x9vYzTmhzyp9lZqOWHraJ1WAFAU7MP7QGLv6/s400/Android_mk.png)
並於主程式宣告新增的Native方法。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiugu9xB6kg0w3G_VqUMOqmlLLMWwyqA2OseIrvP5aLWjxLU29uq1Ew2UpT7gQhwQ_KefFPlSkFdOwHiE7nTEDkDGsK44IwiuKn-v6D66cR4-i-VZ4y2qVslxvknrOtroluYQte8wJdnYHq/s640/MainActivity_jni.png)
此時於程式裡呼叫並將參數帶入NativeAddition這個Native方法,就會得到透過C語言運算的結果。
#錯誤訊息
如果很不幸的在編譯時出現以下錯誤訊息:
Set "android.useDeprecatedNdk=true" in gradle.properties to continue using the current NDK integration.
請在gradle.properties檔案裡加入
android.useDeprecatedNdk=true
#Debug
有時後會需要加入Log至C語言的部份來做Debug,需要遵循以下步驟。
參考資料:
Android-JNI中的log打印
1.加入以下標頭檔
#include <android/log.h>
2.定義LOG標籤與類型
/*定義Log標籤*/
#define TAG "aes-jni-math"
/*定義LOGD類型*/
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__)
#define TAG "aes-jni-math"
/*定義LOGD類型*/
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtIOMjfYW6swMuhXL6GAQFwnLrYV07AIAwt4G6oTuodqBO87hJk2OTnatyu-Qg3vpY-9GW5LX_7u3BPnzS8n9wlBRnmcttOEDmGsZ64cSMyuHL9tm_rX6ElSnRg-wKVICKSA89XpEqHJXO/s640/jni_log.png)
3.修改Android.mk
加入以下內容:
LOCAL_LDLIBS := -llog
4.修改build.gradle(app)
ndk {
moduleName "jni_hello"
ldLibs "log"
}
moduleName "jni_hello"
ldLibs "log"
}
5.使用方式
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdIjBtetRQW44FRYEHK0TOaxnHU5s0A0fs81sKCbyooM9nkE3nz87dub0S58ZMm7Z3aWVIcJBGs9dZ6q8YROfdfjjyq_bnR_k3eODzJTqaitv-iRh4fB3XrWTk0kb0Rn3sYkeYW8sCGWvi/s640/jni_log_use.png)
以上就是簡單的實作方式與步驟,大家快去動手做作看吧!
留言
張貼留言