1.eclipse中的Jni開(kāi)發(fā)流程(一)
2.eclipse中的Jni開(kāi)發(fā)流程(二)
3.Android Studio配置CMake開(kāi)發(fā)NDK
1.在SDK Tools中勾選安裝CMake、LLDB、NDK

Paste_Image.png
2.配置一些快捷方式
參數(shù)講解
javah 用于生成頭文件
Program:$JDKPath$/bin/javah
Parameters:-d ../jni -jni $FileClass$
Working directory:$SourcepathEntry$\..\java
ndk-build 用于構(gòu)建so包
注意:MAC/Linux用ndk-build,沒(méi)有.cmd后綴
Program:D:\adt\sdk\ndk-bundle\ndk-build.cmd
Parameters:什么都不用填
Working directory:$ModuleFileDir$\src\main

Paste_Image.png

Paste_Image.png
3.在工程的local.properties文件中配置NDK的目錄
sdk.dir=C\:\\Users\\yuxue\\AppData\\Local\\Android\\sdk
ndk.dir=C\:\\Users\\yuxue\\AppData\\Local\\Android\\sdk\\ndk-bundle

Paste_Image.png
也可以使用圖形界面,單擊模塊選擇Open Moude Setting,選擇好NDK的路徑

Paste_Image.png
4.編譯時(shí)如果檢查NDK過(guò)時(shí)了可以在gradle.properties文件中增加“android.useDeprecatedNdk=true”使它可以使用過(guò)時(shí)的NDK
android.useDeprecatedNdk=true
5.創(chuàng)建CMakeLists.txt文件并放在模塊的的根目錄
# 設(shè)置構(gòu)建本地庫(kù)所需的最小版本的cbuild。
cmake_minimum_required(VERSION 3.4.1)
# 創(chuàng)建并命名一個(gè)庫(kù),將其設(shè)置為靜態(tài)
# 或者共享,并提供其源代碼的相對(duì)路徑。
# 您可以定義多個(gè)庫(kù),而cbuild為您構(gòu)建它們。
# Gradle自動(dòng)將共享庫(kù)與你的APK打包。
add_library( hello-lib #設(shè)置庫(kù)的名稱(chēng)。即SO文件的名稱(chēng),生產(chǎn)的so文件為“l(fā)ibhello-lib.so”,在加載的時(shí)候“System.loadLibrary("hello-lib");”
SHARED # 將庫(kù)設(shè)置為共享庫(kù)。
src/main/jni/hello.cpp # 提供一個(gè)源文件的相對(duì)路徑
src/main/jni/helloJni.cpp # 提供同一個(gè)SO文件中的另一個(gè)源文件的相對(duì)路徑
)
#搜索指定的預(yù)構(gòu)建庫(kù),并將該路徑存儲(chǔ)為一個(gè)變量。因?yàn)閏build默認(rèn)包含了搜索路徑中的系統(tǒng)庫(kù),所以您只需要指定您想要添加的公共NDK庫(kù)的名稱(chēng)。cbuild在完成構(gòu)建之前驗(yàn)證這個(gè)庫(kù)是否存在。
find_library(log-lib # 設(shè)置path變量的名稱(chēng)。
log # 指定NDK庫(kù)的名稱(chēng) 你想讓CMake來(lái)定位。
)
#指定庫(kù)的庫(kù)應(yīng)該鏈接到你的目標(biāo)庫(kù)。您可以鏈接多個(gè)庫(kù),比如在這個(gè)構(gòu)建腳本中定義的庫(kù)、預(yù)構(gòu)建的第三方庫(kù)或系統(tǒng)庫(kù)。
target_link_libraries( hello-lib #指定目標(biāo)庫(kù)中。與 add_library的庫(kù)名稱(chēng)一定要相同
${log-lib} # 將目標(biāo)庫(kù)鏈接到日志庫(kù)包含在NDK。
)
#如果需要生產(chǎn)多個(gè)SO文件的話,寫(xiě)法如下
add_library( natave-lib #設(shè)置庫(kù)的名稱(chēng)。另一個(gè)so文件的名稱(chēng)
SHARED # 將庫(kù)設(shè)置為共享庫(kù)。
src/main/jni/nataveJni.cpp # 提供一個(gè)源文件的相對(duì)路徑
)
target_link_libraries( natave-lib #指定目標(biāo)庫(kù)中。與 add_library的庫(kù)名稱(chēng)一定要相同
${log-lib} # 將目標(biāo)庫(kù)鏈接到日志庫(kù)包含在NDK。
)
6.在模塊的build.gradle文件中添加
android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
defaultConfig {
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}

Paste_Image.png
7.編寫(xiě)Java中的Native方法
public native String getStr();
public native String gethelloJniStr();
8.生成C的頭文件

Paste_Image.png
生成后

Paste_Image.png
9.編寫(xiě)C函數(shù)
#include "stdio.h"
#include "jni.h"
#include "string"
extern "C"
JNIEXPORT jstring JNICALL Java_com_ljp_learnandroidadvanced_MainActivity_getStr
(JNIEnv *env,
jobject jobject1){
return env->NewStringUTF("hello world from cpp");
}

Paste_Image.png
至此,這個(gè)項(xiàng)目就可以運(yùn)行了
更多的學(xué)習(xí)

Paste_Image.png
(1) .externalNativeBuild文件夾:用于存放cmake編譯好的文件,包括支持的各種硬件等信息,有點(diǎn)類(lèi)似于build.gradle文件明確Gradle如何編譯APP;
(2) cpp文件夾:存放C/C++代碼文件,native-lib.cpp文件默認(rèn)生成的;
(3) CMakeLists.txt:cmake腳本配置文件,cmake會(huì)根據(jù)該腳本文件中的指令去編譯相關(guān)的C/C++源文件,并將編譯后產(chǎn)物生成共享庫(kù)或靜態(tài)塊,然后Gradle將其打包到APK中。
CMakeLists.txt文件解析如下:
# 指定cmke版本
cmake_minimum_required(VERSION3.4.1)
# add_library()命令用于向CMake添加依賴(lài)源文件或庫(kù)
# 指令需傳入三個(gè)參數(shù)(函數(shù)庫(kù)名稱(chēng)、庫(kù)類(lèi)型、依賴(lài)源文件相對(duì)路徑)
add_library( # 生成函數(shù)庫(kù)的名稱(chēng),即libnative-lib.so或libnative-lib.a(lib和.so/.a默認(rèn)缺省)
native-lib
# 生成庫(kù)類(lèi)型:動(dòng)態(tài)庫(kù)為SHARED,靜態(tài)庫(kù)為STATIC
SHARED
# 依賴(lài)的c/cpp文件(相對(duì)路徑)
src/main/cpp/native-lib.cpp )
# find_library()命令用于定位NDK中的庫(kù)
# 需傳入兩個(gè)參數(shù)(path變量、ndk庫(kù)名稱(chēng))
find_library( # 設(shè)置path變量的名稱(chēng),這里為NDK中的日志庫(kù)
log-lib
#指定cmake查詢(xún)庫(kù)的名稱(chēng)
#即在ndk開(kāi)發(fā)包中查詢(xún)liblog.so函數(shù)庫(kù),將其路徑賦值給log-lib
log )
#target_link_libraries()命令用于指定要關(guān)聯(lián)到的原生庫(kù)的庫(kù)
target_link_libraries(# 指定目標(biāo)庫(kù),與上面指定的函數(shù)庫(kù)名一致
native-lib
# 鏈接的庫(kù),根據(jù)log-lib變量對(duì)應(yīng)liblog.so函數(shù)庫(kù)
${log-lib} )
通過(guò)查看native-lib.cpp方法,stringFromJNI目的是向Java層返回一個(gè)字符串。如果要在native-lib.cpp文件中添加新的方法,必須添加在extern"C" { } 中,或者在每個(gè)方法前加extern"C", 否則會(huì)報(bào)找不到方法。如果源文件為C,則須將extern“C”部分去掉,因?yàn)閑xtern "C"的作用就是告訴編譯器以C方式編譯。
JNI開(kāi)發(fā)打印日志
#include <android/log.h>
#define LOG_TAG "System.out.c"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
LOG的使用
LOGD("TAGD,a=%d,b=%d",a,b);
LOGI("TAGI,a=%d,b=%d",a,b);
LOGW("TAGW,a=%d,b=%d",a,b);
LOGE("TAGE,a=%d,b=%d",a,b);

Paste_Image.png
Android系統(tǒng)目前支持的CPU架構(gòu)
ARMv5,ARMv7 (從2010年起)
x86 (從2011年起)
MIPS (從2012年起)
ARMv8,MIPS64和x86_64 (從2014年起)
每一個(gè)CPU架構(gòu)對(duì)應(yīng)一個(gè)ABI
CPU架構(gòu) ABI
ARMv5 ---> armeabi
ARMv7 ---> armeabi-v7a
x86 ---> x86
MIPS ---> mips
ARMv8 ---> arm64-v8a
MIPS64 ---> mips64
x86_64 ---> x86_64
armeabi:默認(rèn)選項(xiàng),將創(chuàng)建以基于ARM* v5TE 的設(shè)備為目標(biāo)的庫(kù)。 具有這種目標(biāo)
的浮點(diǎn)運(yùn)算使用軟件浮點(diǎn)運(yùn)算。 使用此ABI(二進(jìn)制接口)創(chuàng)建的二進(jìn)制代碼將可以
在所有 ARM*設(shè)備上運(yùn)行。所以armeabi通用性很強(qiáng)。但是速度慢
armeabi-v7a:創(chuàng)建支持基于ARM* v7 的設(shè)備的庫(kù),并將使用硬件FPU指令。
armeabi-v7a是針對(duì)有浮點(diǎn)運(yùn)算或高級(jí)擴(kuò)展功能的arm v7 cpu。
mips:MIPS是世界上很流行的一種RISC處理器。MIPS的意思是“無(wú)內(nèi)部互鎖流水級(jí)
的微處理器”(Microprocessor without interlocked piped stages),其機(jī)
制是盡量利用軟件辦法避免流水線中的數(shù)據(jù)相關(guān)問(wèn)題。
x86:支持基于硬件的浮點(diǎn)運(yùn)算的IA-32 指令集。x86是可以兼容armeabi平臺(tái)運(yùn)行
的,無(wú)論是armeabi-v7a還是armeabi,同時(shí)帶來(lái)的也是性能上的損耗,另外需要
指出的是,打包出的x86的so,總會(huì)比armeabi平臺(tái)的體積更小。
總結(jié)
如果項(xiàng)目只包含了 armeabi,那么在所有Android設(shè)備都可以運(yùn)行;
如果項(xiàng)目只包含了 armeabi-v7a,除armeabi架構(gòu)的設(shè)備外都可以運(yùn)行;
如果項(xiàng)目只包含了 x86,那么armeabi架構(gòu)和armeabi-v7a的Android設(shè)備是無(wú)法
運(yùn)行的;
如果同時(shí)包含了 armeabi,armeabi-v7a和x86,所有設(shè)備都可以運(yùn)行,程序在運(yùn)
行的時(shí)候去加載不同平臺(tái)對(duì)應(yīng)的so,這是較為完美的一種解決方案,同時(shí)也會(huì)導(dǎo)致
包變大。
我的CSDN博客地址:http://blog.csdn.net/wo_ha/article/details/78131635