昨日,,日本東芝公司日前宣布開發(fā)出新一代電動車專用鋰電池,快充僅需6分鐘,。傳統(tǒng)電動車鋰電池快充30分鐘也只能充到約80%的電量,,新一代鋰電池快充僅需6分鐘就能充到90%的電量。東芝公司測試用的電動車充電6分鐘后最終跑了約320公里,。目前,,東芝公司計劃對其進行完善,爭取在2019年推出正式產(chǎn)品,。 Android NDK 開發(fā)可能在平時的項目開發(fā)中不常用到,,但是這并不代表其不重要, 相反NDK開發(fā)是Android開發(fā)人員的進階過程中必須要掌握的技能,。 Android NDK 是一組允許將C或C++(原生代碼)嵌入到Android應(yīng)用中的工具,。 如果開發(fā)者在需要以下操作的時候,使用NDK開發(fā)特別有用:
除此之外,對于 ndk 的學(xué)習(xí),,也有助于加深開發(fā)者在閱讀框架的源碼理解,。 ndk 開發(fā)有兩種編譯方式,一種是通過 ndk-build 來構(gòu)建,; 一種是通過 CMake 構(gòu)建原生庫,。通過 CMake 構(gòu)建原生庫是 Google 新提出來的方式,比較方便,、強大,。 通過 cmake 進行ndk開發(fā)首先有個要求,需要 Android Studio 的版本是2.2以上版本(包含2.2) ,,Gradle 的版本需要升到2.2.0及以上,。 滿足上面的條件下,我們需要下載 ndk 和構(gòu)建工具,。如下圖: 紅線標(biāo)記的三個工具下載好就行,。CMake 和 NDK 就不說了,都好理解,, LLDB 呢是一種調(diào)試程序,,用來調(diào)試原生代碼的。 上面的準(zhǔn)備工作做完之后就可以向項目中添加原生代碼,,構(gòu)建原生庫進行ndk開發(fā)了,。 這邊有個討論,向項目中添加原生代碼有兩種情況:
所以這邊相應(yīng)的也有兩種方式。先說第一種方式,。 創(chuàng)建支持C/C++的新項目 創(chuàng)建支持原生代碼的新項目跟平常開發(fā)中創(chuàng)建一個新項目沒有太大的區(qū)別,,說一下不同的地方。
Exceptions Support:如果你希望啟用對 C++ 異常處理的支持,,請選中此復(fù)選框。 如果啟用此復(fù)選框,,Android Studio 會將 -fexceptions 標(biāo)志添加到模塊級 build.gradle 文件的 cppFlags 中,,Gradle 會將其傳遞到 CMake,。 Runtime Type Information Support:如果你希望支持 RTTI,請選中此復(fù)選框,。如果啟用此復(fù)選框,,Android Studio 會將 -frtti 標(biāo)志添加到模塊級 build.gradle 文件的 cppFlags 中,Gradle 會將其傳遞到 CMake,。 這里自己看需求選擇勾不勾選,,這邊演示的demo選擇勾選。如圖2: 創(chuàng)建項目完成之后,,在 as 的左側(cè)項目結(jié)構(gòu)目錄中的 app 應(yīng)用模塊中可以看到 cpp 文件夾,,cpp 文件件里面存放有屬于項目的所有原生源文件、標(biāo)頭和預(yù)構(gòu)建庫,。對于新項目,Android Studio 會創(chuàng)建一個示例 C++ 源文件 native-lib.cpp 除了 cpp 文件夾之外,,我們還看一個 CMakeLists.txt 的這樣一個文件,。這個文件是CMake的構(gòu)建腳本,下面會詳細說,,這里就暫且不說,。之前有說過新建支持 C/C++ 的項目會提供了一個示例的 c++ 源文件native-lib.cpp,存放在 cpp 文件夾中 ,,我們點開看看內(nèi)容 #include 恩,,是使用 C++ 寫的一個方法,返回一個'Hello from C++',,我們跟蹤進去這個方法,,看看哪里調(diào)用。 public class MainActivity extends AppCompatActivity { // Used to load the 'native-lib' library on application startup. static { System.loadLibrary('native-lib'); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Example of a call to a native method TextView tv = (TextView) findViewById(R.id.sample_text); tv.setText(stringFromJNI()); } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ public native String stringFromJNI(); } 我們發(fā)現(xiàn),,這個原生方法是在MainActivity中調(diào)用的,,返回的字符串設(shè)置給了TextView。 通過這兩部分代碼我們發(fā)現(xiàn),,原生方法通過native關(guān)鍵字來表示,、在使用原生庫之前,需要通過 System.loadLibrary(“庫名稱”)加載,、原生方法的方法名命名等常見要點,。這邊就一筆略過。因為本文重點是CMake構(gòu)建原生庫,。 所以ndk的一些基礎(chǔ)知識,,以及JNI等,就不細說,。本文假設(shè)讀者知道這些,。這樣的一個新的支持原生代碼的項目創(chuàng)建之后,并且還自帶demo,開發(fā)者就可以很方便在上面進行開發(fā),。 假設(shè)現(xiàn)在要創(chuàng)建一個原生庫進行ndk開發(fā),,我們在cpp文件夾下new一個C/C++ Source file ,在你new出來的文件編寫你的C/C++代碼邏輯,,然后在CMakeLists.txt配置文件上稍作配置,,即可。下面會詳述CMakeLists.txt 的配置,。 向現(xiàn)有項目添加原生代碼 向現(xiàn)有項目添加原生代碼,,進行ndk開發(fā),這里選擇一個我的項目,,空閑時間寫的一個APP,, 一款仿今日頭條的資訊類軟件(求star)- PalmRead
主要有三個大步驟。第一步:創(chuàng)建新的原生源文件,;第二步:創(chuàng)建CMake構(gòu)建腳本,;第三步:將Gradle關(guān)聯(lián)到原生庫。現(xiàn)在我們來看第一步,,創(chuàng)建新的原生源文件,,首先我們要先在應(yīng)用模塊src/main 目錄下創(chuàng)建一個cpp文件夾用來存放原生源文件等。然后在cpp文件夾下面創(chuàng)建C/C++源文件New > C/C++ Source File,。如圖: 創(chuàng)建了一個名為 palmread-lib 文件,。第二步,我們創(chuàng)建CMake構(gòu)建腳本,,也就是CMakeLists.txt 文件,,在應(yīng)用模塊下new一個file文件,命名為 CMakeLists.txt 即可,,注意哦,,這個文件的名稱不能搞錯哦。CMakeLists.txt 創(chuàng)建好打開后,,發(fā)現(xiàn)沒有任何內(nèi)容,,這就對了。,。需要我們自己配置的,。不像是通過第一種新創(chuàng)建支持原生代碼的項目那種,還給你寫好,,不過我們可以參考第一種方式下,,系統(tǒng)給我們默認(rèn)生成的內(nèi)容。咱們看一下第一種方式下,,系統(tǒng)默認(rèn)生成的 CMakeLists.txt 文件的內(nèi)容是什么樣子吧,。如下: # Sets the minimum version of CMake required to build the native library. cmake_minimum_required(VERSION 3.4.1) # Creates and names a library, sets it as either STATIC # or SHARED, and provides the relative paths to its source code. # You can define multiple libraries, and CMake builds them for you. # Gradle automatically packages shared libraries with your APK. add_library( # Sets the name of the library. native-lib # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). src/main/cpp/native-lib.cpp ) # Searches for a specified prebuilt library and stores the path as a # variable. Because CMake includes system libraries in the search path by # default, you only need to specify the name of the public NDK library # you want to add. CMake verifies that the library exists before # completing its build. find_library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that # you want CMake to locate. log ) # Specifies libraries CMake should link to your target library. You # can link multiple libraries, such as libraries you define in this # build script, prebuilt third-party libraries, or system libraries. target_link_libraries( # Specifies the target library. native-lib # Links the target library to the log library # included in the NDK. ${log-lib} ) 通過圖片我們看到,,其實內(nèi)容也沒什么。就cmake_minimum_required()add_library(),、find_library,、target_link_libraries()。這幾個CMake命令,,每個CMake命令都有英文介紹很好理解,。比如add_library創(chuàng)建和命名一個庫,這邊名稱我們就填palmread-lib,,種類分為static和shared,,具體區(qū)別嘛移步: static和shared的區(qū)別
這里我們選擇 SHARED,然后就是提供一個 library 的相對路徑,。只有在 CMakeLists.txt 文件中配置了該命令 ,,才能找到編譯這個庫。其他的一些 CMake 命令大家自行搜索了解,,都不是很難,,很好理解,這里篇幅有限就不細說了,。那現(xiàn)在我們可以按照系統(tǒng)提供的模板,基于自己的項目寫了一份 CMakeLists.txt 文件,,代碼如下: cmake_minimum_required(VERSION 3.4.1) add_library( palmread-lib SHARED src/main/cpp/palmread-lib.c ) find_library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that # you want CMake to locate. log ) target_link_libraries( # Specifies the target library. palmread-lib # Links the target library to the log library # included in the NDK. ${log-lib} ) 隨后在 Java 類中加載 palmread-lib 庫,,這里我這邊寫了一個 NdkHelper 類,專門用來定義 native 方法的: public class NdkHelper { static { System.loadLibrary('palmread-lib'); } public static native String GetStringFromC(String str); } 這一步做完后,,第二步也算告一段落了,,現(xiàn)在我們來看第三步:將 Gradle 關(guān)聯(lián)到你的原生庫。 將 gradle 關(guān)聯(lián)到原生庫有兩種方式,,這里就先說第一種比較簡單的方式,,第二種下篇博文再說。 第一種方式是通過as的快捷鍵來實現(xiàn)的,,右鍵點擊你想要關(guān)聯(lián)到原生庫的模塊(例如 app 模塊),, 并從菜單中選擇 Link C++ Project with Gradle。 BuildSystem選擇CMake,,projectpath 就是CMakeLists.txt文件的路徑,。點擊ok完成。 你會在應(yīng)用模塊的build.gradle文件中發(fā)現(xiàn),,android閉包里出現(xiàn)了 externalNativeBuild { cmake { path 'CMakeLists.txt' } } 這個語句就跟我們之前說的第二種方式有關(guān)系,,這里先不說了,后面博文再說,。 同步項目后,,突然想到之前新建的palmread-lib.c文件好像還沒有寫C代碼呢,,呀,這腦子,,沒事,,我們現(xiàn)在寫。 寫些什么呢,?這樣吧我們用C來實現(xiàn)這樣一個功能,,接受一個字符串參數(shù),然后對字符串進行拼接修改操作 ,,使得返回一個新的字符串,。 代碼如下: #include 'jni.h' #include 代碼寫好之后,就是去調(diào)用了,,為了方便測試,,我們選在在應(yīng)用的首頁activity去調(diào)用這個原生方法。 通過toast顯示方法返回的值,。 如圖: 通過代碼,,我們可以看出,我們調(diào)用了,,NdkHelper.GetStringFromC()這個原生方法,,傳入一個“歡迎來到PalmRead”字符串作為參數(shù)。按照之前的 C 邏輯,,應(yīng)該會返回一個新的字符串為 “歡迎來到PalmRead from c”,。 那我們運行程序試試效果吧。 O(∩_∩)O哈,!,,我們發(fā)現(xiàn)toast顯示的值確實是我們設(shè)想的返回值。這樣就架起了Java與原生代碼之間的橋梁,。 現(xiàn)在我們可以應(yīng)用模塊的build/outputs/apk目錄下,,打開我們的apk,我們會發(fā)現(xiàn),,我們創(chuàng)建的原生文件,,編譯成了原生庫'libpalmread-lib.so'也打包進了apk文件。如圖: 好了,,關(guān)于CMake來進行 Android NDK 開發(fā),,大致的流程就是這樣。CMakeLists 的一些命令 還有Gradle關(guān)聯(lián)原生庫的第二種通過編輯build.gradle文件的方式 ,, 通過 CMake 來進行ndk開發(fā)之補充篇
有詳細說明,。 最后給大家做個推薦,隔壁鴻洋新開發(fā)了一個Android開發(fā)者必看的網(wǎng)站,,域名是 http:// ,,里面有不少干貨文章,,大家有興趣的話可以登錄這個網(wǎng)站瞧一瞧。
|
|