NDK:Android NDK 是在SDK前面又加上了“原生”二字,即Native Development Kit,因此又被Google稱為“NDK”。

成都創(chuàng)新互聯(lián)"三網(wǎng)合一"的企業(yè)建站思路。企業(yè)可建設(shè)擁有電腦版、微信版、手機(jī)版的企業(yè)網(wǎng)站。實(shí)現(xiàn)跨屏營銷,產(chǎn)品發(fā)布一步更新,電腦網(wǎng)絡(luò)+移動(dòng)網(wǎng)絡(luò)一網(wǎng)打盡,滿足企業(yè)的營銷需求!成都創(chuàng)新互聯(lián)具備承接各種類型的網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作項(xiàng)目的能力。經(jīng)過10年的努力的開拓,為不同行業(yè)的企事業(yè)單位提供了優(yōu)質(zhì)的服務(wù),并獲得了客戶的一致好評(píng)。
NDK全稱:Native Development Kit。
NDK是一系列工具的集合。
* NDK提供了一系列的工具,幫助開發(fā)者快速開發(fā)C(或C++)的動(dòng)態(tài)庫,并能自動(dòng)將so和java應(yīng)用一起打包成apk。這些工具對(duì)開發(fā)者的幫助是巨大的。
* NDK集成了交叉編譯器,并提供了相應(yīng)的mk文件隔離CPU、平臺(tái)、ABI等差異,開發(fā)人員只需要簡單修改mk文件(指出“哪些文件需要編譯”、“編譯特性要求”等),就可以創(chuàng)建出so。
* NDK可以自動(dòng)地將so和Java應(yīng)用一起打包,極大地減輕了開發(fā)人員的打包工作。
其實(shí):
NDK就是能夠方便快捷開發(fā).so文件的工具。JNI的過程比較復(fù)雜,生成.so需要大量操作,而NDK就是簡化了這個(gè)過程。
Android SDK:
SDK (software development kit)軟件開發(fā)工具包。被軟件開發(fā)工程師用于為特定的軟件包、軟件框架、硬件平臺(tái)、操作系統(tǒng)等建立應(yīng)用軟件的開發(fā)工具的集合。因此!Android SDk 指的既是Android專屬的軟件開發(fā)工具包
JNI:
Java Native Interface (JNI)標(biāo)準(zhǔn)是java平臺(tái)的一部分,它允許Java代碼和其他語言寫的代碼進(jìn)行交互。JNI 是本地編程接口,它使得在 Java 虛擬機(jī) (VM) 內(nèi)部運(yùn)行的 Java 代碼能夠與用其它編程語言(如 C、C++ 和匯編語言)編寫的應(yīng)用程序和庫進(jìn)行交互操作
當(dāng)然一般需要進(jìn)行如下操作流程:
1) 編寫java程序:這里以HelloWorld為例。為了實(shí)現(xiàn)在 java代碼中調(diào)用c函數(shù)printf。
代碼1:
class HelloWorld {
public native void testHelloWorld();
static {
System.loadLibrary("hello");
}
public static void main(String[] args) {
new HelloWorld().testHelloWorld();
}
}
聲明native方法:如果你想將一個(gè)方法做為一個(gè)本地方法的話,那么你就必須聲明改方法為native的,并且不能實(shí)現(xiàn)。
Load動(dòng)態(tài)庫:System.loadLibrary("hello");
這里一般是以static塊進(jìn)行加載的。同時(shí)需要注意的是System.loadLibrary()的參數(shù)“hello”是動(dòng)態(tài)庫的名字。
2) 編譯
javac HelloWorld.java
3) 生成擴(kuò)展名為h的頭文件 javah ?
JNIEXPORT void JNICALL Java_HelloWorld_testHelloWorld (JNIEnv *, jobject);
這個(gè)h文件相當(dāng)于我們?cè)趈ava里面的接口,這里聲明了一個(gè) Java_HelloWorld_testHelloWorld (JNIEnv *, jobject)方法,然后在我們 的本地方法里面實(shí)現(xiàn)這個(gè)方法,也就是說我們?cè)诰帉慍/C++程序的時(shí)候所使用的方法名必須和這里的一致)。
4) 編寫本地方法實(shí)現(xiàn)和由javah命令生成的頭文件里面聲明的方法名相同的方法
代碼2:
#include "jni.h"
#include "HelloWorld.h"
#include other headers
JNIEXPORT void JNICALL Java_HelloWorld_testHelloWorld(JNIEnv *env, jobject obj)
{
printf("Hello world!/n");
return;
}
注意代碼2中的第1行,需要將jni.h(該文件可以在%JAVA_HOME%/include文件夾下面找到)文件引入,因?yàn)樵诔绦蛑械腏NIEnv、 jobject等類型都是在該頭文件中定義的;另外在第2行需要將HelloWorld.h頭文件引入。然后保存為 HelloWorldImpl.c就ok了。
5) 生成動(dòng)態(tài)庫
這里以在Windows中為例,需要生成dll文件。在保存HelloWorldImpl.c文件夾下面,使用VC的編譯器cl成。 cl -I%java_home%/include -I%java_home%/include/win32 -LD HelloWorldImp.c -Fehello.dll 注意:生成的dll文件名在選項(xiàng)-Fe后面配置,這里是hello,因?yàn)樵贖elloWorld.java文件中我們loadLibary的時(shí)候使用的名字是hello。
另外需要將-I%java_home%/include -I%java_home%/include/win32參數(shù)加上,因?yàn)樵诘谒牟嚼锩婢帉懕镜胤椒ǖ臅r(shí)候引入了jni.h文件。
很多朋友在開發(fā) Android JNI的的時(shí)候,會(huì)遇到findlibrary returned null的錯(cuò)誤,因?yàn)槟撤N原因,so沒有打包到apk中。下面淺析下引起該錯(cuò)誤的原因以及平臺(tái)兼容性問題。
一、沒有將so打包到apk中的原因。
當(dāng)你發(fā)現(xiàn)到findlibrary returned null的錯(cuò)誤時(shí),其實(shí)最直接的解決辦法就是解壓apk,看看apk中的x86、armeabi、armeabi-v7a文件夾中是否有對(duì)應(yīng)的so,此時(shí)你可能在對(duì)應(yīng)的文件夾下發(fā)現(xiàn)少了so,然后再去查原因即可。
一般有兩方面的原因:
1.apk中有對(duì)應(yīng)平臺(tái)的文件夾,但是文件夾里卻沒有對(duì)應(yīng)的so。
舉個(gè)例子,apk中l(wèi)ib下面一旦出現(xiàn)x86文件夾,程序運(yùn)行的時(shí)候就會(huì)去加載x86對(duì)應(yīng)的庫,但是如果此時(shí)x86文件夾沒有將so放進(jìn)來,則會(huì)遇到報(bào)錯(cuò)。
2.第三方對(duì)平臺(tái)的兼容策略與自己不一致。
可能第三方選擇了只支持armeabi(假設(shè)某支付sdk),但是我們的游戲在Application.mk中配置了APP_ABI := all,如此,我們的游戲打包出 了所有平臺(tái)的so,但是第三方卻只有armeabi文件夾對(duì)應(yīng)的so,造成程序運(yùn)行異常,這種情況在開發(fā)期間最常見,一些小公司由于測試人員不足或者測試設(shè)備不足,上線后才發(fā)現(xiàn)這個(gè)問題也不奇怪。
二、對(duì)于平臺(tái)的支持,我們應(yīng)該如何選擇。
armeabi-v7a確實(shí)是可以兼容armeabi的,而v7a的CPU支持硬件浮點(diǎn)運(yùn)算,目前絕大對(duì)數(shù)設(shè)備已經(jīng)是v7a了,所以為了性能上的更優(yōu),就不要為了兼容放到armeabi。 x86是可以兼容armeabi平臺(tái)運(yùn)行的,無論是armeabi-v7a還是armeabi,同時(shí)帶來的也是性能上的損耗,另外需要指出的是,打包出的x86的so,總會(huì)比armeabi平臺(tái)的體積更小,對(duì)于性能有潔癖的童鞋們,還是建議在打包so的時(shí)候支持x86。具體會(huì)有怎樣的性能損耗,作者還不能說的非常清楚,可以訪問下intel官方在csdn的博客。 總結(jié)一下在項(xiàng)目中的表現(xiàn)就是:
1、NDK是一系列工具的集合。
2、NDK提供了一份穩(wěn)定、功能有限的API頭文件聲明。
3、NDK的發(fā)布,使“Java+C”的開發(fā)方式終于轉(zhuǎn)正,成為官方支持的開發(fā)方式。
4、NDK將使Android平臺(tái)支持C開發(fā)的開端。
NDK使得在android中,java可以調(diào)用C函數(shù)庫。我們都知道,java是半解釋型語言,很容易被反匯編后拿到源代碼文件,在開發(fā)一些重要協(xié)議時(shí),我們?yōu)榱税踩鹨姡褂肅語言來編寫這些重要的部分,來增大系統(tǒng)的安全性。還有,在一些接近硬件環(huán)境下,相信大家都清楚C與java的優(yōu)劣。順帶提一下:NDK并不能顯著提升應(yīng)用效率。why?我們都覺得C語言比起java來說效率要高出很多,一方面,隨著jdk的不斷更新,java的效率也隨之提高;另一方面,即便使用C語言編碼提高了應(yīng)用效率,但是在java與C相互調(diào)用時(shí)平白又增大了開銷。
1、NDK是一系列工具的集合。
NDK提供了一系列的工具,幫助開發(fā)者快速開發(fā)C(或C++)的動(dòng)態(tài)庫,并能自動(dòng)將so和java應(yīng)用一起打包成apk。這些工具對(duì)開發(fā)者的幫助是巨大的。
NDK集成了交叉編譯器,并提供了相應(yīng)的mk文件隔離CPU、平臺(tái)、ABI等差異,開發(fā)人員只需要簡單修改mk文件(指出“哪些文件需要編譯”、“編譯特性要求”等),就可以創(chuàng)建出so。
NDK可以自動(dòng)地將so和Java應(yīng)用一起打包,極大地減輕了開發(fā)人員的打包工作。
2、NDK提供了一份穩(wěn)定、功能有限的API頭文件聲明。
Google明確聲明該API是穩(wěn)定的,在后續(xù)所有版本中都穩(wěn)定支持當(dāng)前發(fā)布的API。從該版本的NDK中看出,這些API支持的功能非常有限,包含有:C標(biāo)準(zhǔn)庫(libc)、標(biāo)準(zhǔn)數(shù)學(xué)庫(libm)、壓縮庫(libz)、Log庫(liblog)。
3、NDK的發(fā)布,使“Java+C”的開發(fā)方式終于轉(zhuǎn)正,成為官方支持的開發(fā)方式。
使用NDK,我們可以將要求高性能的應(yīng)用邏輯使用C開發(fā),從而提高應(yīng)用程序的執(zhí)行效率。
使用NDK,我們可以將需要保密的應(yīng)用邏輯使用C開發(fā)。畢竟,Java包都是可以反編譯的。
NDK促使專業(yè)so組件商的出現(xiàn)。(樂觀猜想,要視乎Android用戶的數(shù)量)
4、NDK將使Android平臺(tái)支持C開發(fā)的開端。
NDK提供了的開發(fā)工具集合,使開發(fā)人員可以便捷地開發(fā)、發(fā)布C組件。同時(shí),Google承諾在NDK后續(xù)版本中提高“可調(diào)式”能力,即提供遠(yuǎn)程的gdb工具,使我們可以便捷地調(diào)試C源碼。在支持Android平臺(tái)C開發(fā),我們能感覺到Google花費(fèi)了很大精力,我們有理由憧憬“C組件支持”只是Google Android平臺(tái)上C開發(fā)的開端。畢竟,C程序員仍然是碼農(nóng)陣營中的絕對(duì)主力,將這部分人排除在Android應(yīng)用開發(fā)之外,顯然是不利于Android平臺(tái)繁榮昌盛的。
只要你細(xì)心的查看,再配合Google 提供的工具,完全可以快速地準(zhǔn)確定位出錯(cuò)的代碼位置,這個(gè)工作我們稱之為“符號(hào)化”。需要注意的是,如果要對(duì)NDK錯(cuò)誤進(jìn)行符號(hào)化的工作,需要保留編譯過程中產(chǎn)生的包含符號(hào)表的so文件,這些文件一般保存在$PROJECT_PATH/obj/local/目錄下。
第一種方法:ndk-stack
這個(gè)命令行工具包含在NDK工具的安裝目錄,和ndk-build及其他常用的一些NDK命令放在一起,比如在我的電腦上,其位置是/android-ndk-r9d/ndk-stack。根據(jù)Google官方文檔,NDK從r6版本開始提供ndk-stack命令,如果你用的之前的版本,建議還是盡快升級(jí)至最新的版本。使用ndk –stack命令也有兩種方式
實(shí)時(shí)分析日志
在運(yùn)行程序的同時(shí),使用adb獲取logcat日志,并通過管道符輸出給ndk-stack,同時(shí)需要指定包含符號(hào)表的so文件位置;如果你的程序包含了多種CPU架構(gòu),在這里需求根據(jù)錯(cuò)誤發(fā)生時(shí)的手機(jī)CPU類型,選擇不同的CPU架構(gòu)目錄,如:
當(dāng)崩潰發(fā)生時(shí),會(huì)得到如下的信息:
第二種方法:使用addr2line和objdump命令
這個(gè)方法適用于那些不滿足于上述ndk-stack的簡單用法,而喜歡刨根問底的程序員們,這兩個(gè)方法可以揭示ndk-stack命令的工作原理是什么,盡管用起來稍微麻煩一點(diǎn),但可以稍稍滿足一下程序員的好奇心。
先簡單說一下這兩個(gè)命令,在絕大部分的Linux發(fā)行版本中都能找到他們,如果你的操作系統(tǒng)是Linux,而你測試手機(jī)使用的是Intel x86系列,那么你使用系統(tǒng)中自帶的命令就可以了。然而,如果僅僅是這樣,那么絕大多數(shù)人要絕望了,因?yàn)榍∏〈蟛糠珠_發(fā)者使用的是Windows,而手機(jī)很有可能是armeabi系列。
在NDK中自帶了適用于各個(gè)操作系統(tǒng)和CPU架構(gòu)的工具鏈,其中就包含了這兩個(gè)命令,只不過名字稍有變化,你可以在NDK目錄的toolchains目錄下找到他們。以我的Mac電腦為例,如果我要找的是適用于armeabi架構(gòu)的工具,那么他們分別為arm-linux-androideabi-addr2line和arm-linux-androideabi-objdump;位置在下面目錄中,后續(xù)介紹中將省略此位置:
假設(shè)你的電腦是Windows系統(tǒng),CPU架構(gòu)為mips,那么你要的工具可能包含在一下目錄中:
接下來就讓我們來看看如何使用這兩個(gè)工具,下面具體介紹。
找到日志中的關(guān)鍵函數(shù)指針
其實(shí)很簡單,就是找到backtrace信息中,屬于我們自己的so文件報(bào)錯(cuò)的行。
首先要找到backtrace信息,有的手機(jī)會(huì)明確打印一行backtrace(比如我們這次使用的手機(jī)),那么這一行下面的一系列以“#兩位數(shù)字 pc”開頭的行就是backtrace信息了。有時(shí)可能有的手機(jī)并不會(huì)打印一行backtrace,那么只要找到一段以“#兩位數(shù)字 pc ”開頭的行,就可以了。
其次要找到屬于自己的so文件報(bào)錯(cuò)的行,這就比較簡單了。找到這些行之后,記下這些行中的函數(shù)地址。
首先我們需要了解一下socket的通信原理,大家百度就可以找到這張圖片
然后客戶端
__fd:上面第一步創(chuàng)建得到的返回值
__addr:指向要綁定給__fd的協(xié)議地址
__addr_lenght:對(duì)應(yīng)的是地址的長度
__addr:代表返回客戶端的協(xié)議地址
__addr_length參數(shù):為協(xié)議地址的長度
__fd:accept返回成功后的返回值socket描述詞
使用service的oncreate方法
即上一篇寫完 NDK開發(fā)之路1-共享內(nèi)存 之后,我們?cè)囍謩?dòng)實(shí)現(xiàn)parcel共享內(nèi)存的方式。
調(diào)用
結(jié)果
當(dāng)前標(biāo)題:ndk開發(fā)鴻蒙,鴻蒙基于安卓開發(fā)
當(dāng)前URL:http://chinadenli.net/article1/dsgchod.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、服務(wù)器托管、靜態(tài)網(wǎng)站、標(biāo)簽優(yōu)化、網(wǎng)站建設(shè)、網(wǎng)站營銷
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)