Android JNI/NDK 開發指南

JNI 概述

JNI 是 Java 語言提供的 Java 和 C/C++ 相互溝通的機制,Java 可以通過 JNI 調用本地的 C/C++ 代碼,本地的 C/C++ 的代碼也可以調用 Java 代碼。JNI 是本地編程接口,Java 和 C/C++ 互相通過的接口。Java 通過 C/C++ 使用本地的代碼的一個關鍵性原因在於 C/C++ 代碼的高效性。 代碼和其他語言寫的代碼進行交互。

相信很多做過 Java 或 Android 開發的朋友經常會接觸到 JNI 方面的技術,由其做過 Android 的朋友,爲了應用的安全性,會將一些複雜的邏輯和算法通過本地代碼(C或C++)來實現,然後打包成.so動態庫文件,並提供 Java 接口供應用層調用,這麼做的目的主要就是爲了提供應用的安全性,防止被反編譯後被不法分子分析應用的邏輯。當然打包成.so也不能說完全安全了,只是相對反編譯 Java 的 class 字節碼文件來說,反彙編.so動態庫來分析程序的邏輯要複雜得多,沒那麼容易被破解。比如百度開放平臺提供的定位服務、搜索服務、LBS 服務、推送服務的Android SDK,除了Java接口的jar包之外,還有一個.so文件,這個.so就是實現了Java層定義的native接口的動態庫。

以前公司有一個 JavaWeb 的項目,其中有一個用戶註冊的模塊,需要驗證用戶的手機號(流程大家都懂的),由於這個項目的用戶量不大,沒用採用運營商的短信網關接口,直接採購了一臺 16 口的短信貓設備和 SIM 卡來解決這個事情。由於短信貓設備只提供了 C 的接口,而 Java 是不能直接與 C 語言進行交互的,所以 JNI 就派上用場了,先在 Java 層定義好發送短信、接收短信、短信發送隊列等相關 native 方法,然後用 javah 命令將定義 Java native 接口的 class 字節碼文件生成.h頭文件(這個後面會講到),最後用設備場商提供的 C 接口來實現 java 的 native 方法,完了之後編譯成.dll或.so動態庫,提供給 Java 程序使用即可。

JNI 在 Cocos2d-x 遊戲引擎中也經常用到,該引擎是用純 C++ 開發的,而且是跨平臺的,依託 C++ 的跨平臺特性,只需用 C++ 編寫一次邏輯,就可以將遊戲打包發佈到不同的平臺(IOS、Android、WinPhone、黑莓、Linux、Windows),打包發佈的細節就不在這裏討論了。如果遊戲要發佈到 Android 平臺,開發過程當中,少不了 C++ 層和 Java 層進行交互,比如遊戲當中要打開一個網頁、播放一段視頻或打開一個新的窗口等,這些在 C++ 層實現是非常麻煩的,如果用 Android 應用層提供的 API 就變得相當容易。所以這時就不得不寫 JNI 來完成這些功能的需求。當然這些常用的 JNI 操作,Cocos2d-x 引擎進行了封裝,相關的接口定義在 JniHelper.cpp這個類中,可以拿來直接使用。(後面會有例子詳細介紹)

雖然現在的物聯網和智能家居行業還處於萌芽狀態,但隨着這個時代在技術的創新與不斷改進的發展下,想象 5 年後,物聯網和智能家居行業真正成熟起來,由於 Android 系統的開源,自然會被各大硬件場商所採用,相當於這幾年 Android 智能手機的市場一樣,仍然可能會處於移動智能終端的霸主地位。你可能會問,但這和 JNI 和有什麼關係呢?當各種設備接入互聯網的同時,自然少不了人機交互的應用程序,當應用程序需要調用硬件特定的功能時,此時只能通過 C 或 C++ 封裝對應功能的 JNI 接口來供上層應用使用。比如要用手機中的 app 控制家裏的電燈、窗簾、冰箱、空調等一切智能的電子設備時,自然少不了應用要和底層硬件進行通訊,至於各種智能設備的運行控制,自然是由廠商來實現,他們只需提供操作設備相關功能的接口即可。雖然廠商會封裝好 JNI 接口,但我們也要了解下 JNI 與 Java 通訊的原理,以便我們在開發過程當中遇到問題時,能夠快速定位到問題。

NDK 概述

NDK 是一系列工具的集合。它提供了一系列的工具,幫助開發者快速開發 C(或C++)的動態庫,並能自動將 so 和 Java 應用一起打包成 apk。這些工具對開發者的幫助是巨大的。它集成了交叉編譯器,並提供了相應的 mk 文件隔離 CPU、平臺、ABI 等差異,開發人員只需要簡單修改 mk 文件(指出“哪些文件需要編譯”、“編譯特性要求”等),就可以創建出 so。它可以自動地將 so 和 Java 應用一起打包,極大地減輕了開發人員的打包工作。
NDK 產生的背景
Android 平臺從誕生起,就已經支持 C、C++ 開發。衆所周知,Android 的 SDK 基於 Java 實現,這意味着基於Android SDK 進行開發的第三方應用都必須使用 Java 語言。但這並不等同於“第三方應用只能使用 Java”。在Android SDK 首次發佈時,Google 就宣稱其虛擬機 Dalvik 支持 JNI 編程方式,也就是第三方應用完全可以通過 JNI 調用自己的 C 動態庫,即在 Android 平臺上,“Java+C”的編程方式是一直都可以實現的。
不過,Google 也表示,使用原生 SDK 編程相比 Dalvik 虛擬機也有一些劣勢,Android SDK 文檔裏,找不到任何 JNI 方面的幫助。即使第三方應用開發者使用 JNI 完成了自己的 C 動態鏈接庫(so)開發,但是 so 如何和應用程序一起打包成 apk 併發布?這裏面也存在技術障礙。比如程序更加複雜,兼容性難以保障,無法訪問Framework API,Debug 難度更大等。開發者需要自行斟酌使用。
於是 NDK 就應運而生了。NDK 全稱是 Native Development Kit。
NDK 的發佈,使“Java+C”的開發方式終於轉正,成爲官方支持的開發方式。NDK 將是 Android 平臺支持 C 開發的開端。

NDK 優點:
代碼的保護。由於 apk 的 java 層代碼很容易被反編譯,而 C/C++ 庫反匯難度較大。
可以方便地使用現存的開源庫。大部分現存的開源庫都是用 C/C++ 代碼編寫的。
提高程序的執行效率。將要求高性能的應用邏輯使用 C 開發,從而提高應用程序的執行效率。
便於移植。用 C/C++ 寫得庫可以方便在其他的嵌入式平臺上再次使用。
NDK 提供了一份穩定、功能有限的 API 頭文件聲明

Google 明確聲明該 API 是穩定的,在後續所有版本中都穩定支持當前發佈的 API。從該版本的 NDK 中看出,這些 API 支持的功能非常有限,包含有:C 標準庫(libc)、標準數學庫(libm)、壓縮庫(libz)、Log 庫(liblog)。


JNI 的詳細使用:JNI/NDK 開發指南

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章