一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

使用CMake來進(jìn)行Android NDK開發(fā)

 fishpan_oliver 2017-10-10



今日科技快訊


昨日,日本東芝公司日前宣布開發(fā)出新一代電動(dòng)車專用鋰電池,快充僅需6分鐘。傳統(tǒng)電動(dòng)車鋰電池快充30分鐘也只能充到約80%的電量,新一代鋰電池快充僅需6分鐘就能充到90%的電量。東芝公司測(cè)試用的電動(dòng)車充電6分鐘后最終跑了約320公里。目前,東芝公司計(jì)劃對(duì)其進(jìn)行完善,爭取在2019年推出正式產(chǎn)品。 


前言


Android NDK 開發(fā)可能在平時(shí)的項(xiàng)目開發(fā)中不常用到,但是這并不代表其不重要,  

相反NDK開發(fā)是Android開發(fā)人員的進(jìn)階過程中必須要掌握的技能。  

Android NDK 是一組允許將C或C++(原生代碼)嵌入到Android應(yīng)用中的工具。  

如果開發(fā)者在需要以下操作的時(shí)候,使用NDK開發(fā)特別有用:  

  • 在平臺(tái)之間移植其應(yīng)用

  • 從設(shè)備獲取卓越性能以用于計(jì)算密集型應(yīng)用,例如游戲或物理模擬。  

  • 重復(fù)使用現(xiàn)有庫或者提供自己庫供重復(fù)使用。  

除此之外,對(duì)于 ndk 的學(xué)習(xí),也有助于加深開發(fā)者在閱讀框架的源碼理解。  

ndk 開發(fā)有兩種編譯方式,一種是通過 ndk-build 來構(gòu)建;  

一種是通過 CMake 構(gòu)建原生庫。通過 CMake 構(gòu)建原生庫是 Google 新提出來的方式,比較方便、強(qiáng)大。


準(zhǔn)備


通過 cmake 進(jìn)行ndk開發(fā)首先有個(gè)要求,需要 Android Studio 的版本是2.2以上版本(包含2.2) ,Gradle 的版本需要升到2.2.0及以上。  

滿足上面的條件下,我們需要下載 ndk 和構(gòu)建工具。如下圖:

紅線標(biāo)記的三個(gè)工具下載好就行。CMake 和 NDK 就不說了,都好理解,  LLDB 呢是一種調(diào)試程序,用來調(diào)試原生代碼的。  


向項(xiàng)目添加原生代碼


上面的準(zhǔn)備工作做完之后就可以向項(xiàng)目中添加原生代碼,構(gòu)建原生庫進(jìn)行ndk開發(fā)了。  

這邊有個(gè)討論,向項(xiàng)目中添加原生代碼有兩種情況:  

  • 一種是新建一個(gè)新的項(xiàng)目支持 C/C++;  

  • 一種是在已有項(xiàng)目中添加原生代碼。  

所以這邊相應(yīng)的也有兩種方式。先說第一種方式。

創(chuàng)建支持C/C++的新項(xiàng)目

創(chuàng)建支持原生代碼的新項(xiàng)目跟平常開發(fā)中創(chuàng)建一個(gè)新項(xiàng)目沒有太大的區(qū)別,說一下不同的地方。

  • 前者在向?qū)У腃onfig your new project界面需要選中Include C++ Support 復(fù)選框。如圖1:

  • 前者在向?qū)У腃ustomize C++ Support 界面會(huì)有C++ Standard 的選擇  意思是你希望使用哪種 C++ 標(biāo)準(zhǔn)。  選擇 ToolchainDefault 會(huì)使用默認(rèn)的 CMake 設(shè)置。  這里我們選擇默認(rèn)的。  

Exceptions Support:如果你希望啟用對(duì) C++ 異常處理的支持,請(qǐng)選中此復(fù)選框。  

如果啟用此復(fù)選框,Android Studio 會(huì)將 -fexceptions 標(biāo)志添加到模塊級(jí) build.gradle 文件的 cppFlags 中,Gradle 會(huì)將其傳遞到 CMake。

Runtime Type Information Support:如果你希望支持 RTTI,請(qǐng)選中此復(fù)選框。如果啟用此復(fù)選框,Android Studio 會(huì)將 -frtti 標(biāo)志添加到模塊級(jí) build.gradle 文件的   cppFlags 中,Gradle 會(huì)將其傳遞到 CMake。  這里自己看需求選擇勾不勾選,這邊演示的demo選擇勾選。如圖2:

創(chuàng)建項(xiàng)目完成之后,在 as 的左側(cè)項(xiàng)目結(jié)構(gòu)目錄中的 app 應(yīng)用模塊中可以看到 cpp 文件夾,cpp 文件件里面存放有屬于項(xiàng)目的所有原生源文件、標(biāo)頭和預(yù)構(gòu)建庫。對(duì)于新項(xiàng)目,Android Studio 會(huì)創(chuàng)建一個(gè)示例 C++ 源文件 native-lib.cpp 除了 cpp 文件夾之外,我們還看一個(gè) CMakeLists.txt 的這樣一個(gè)文件。這個(gè)文件是CMake的構(gòu)建腳本,下面會(huì)詳細(xì)說,這里就暫且不說。之前有說過新建支持 C/C++ 的項(xiàng)目會(huì)提供了一個(gè)示例的 c++ 源文件native-lib.cpp,存放在 cpp 文件夾中  ,我們點(diǎn)開看看內(nèi)容

#include #include extern 'C' JNIEXPORT jstring JNICALL Java_com_example_ndkdemo_MainActivity_stringFromJNI(        JNIEnv *env,        jobject /* this */) {    std::string hello = 'Hello from C++';    return env->NewStringUTF(hello.c_str()); }

恩,是使用 C++ 寫的一個(gè)方法,返回一個(gè)'Hello from C++',我們跟蹤進(jìn)去這個(gè)方法,看看哪里調(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),這個(gè)原生方法是在MainActivity中調(diào)用的,返回的字符串設(shè)置給了TextView。  

通過這兩部分代碼我們發(fā)現(xiàn),原生方法通過native關(guān)鍵字來表示、在使用原生庫之前,需要通過 System.loadLibrary(“庫名稱”)加載、原生方法的方法名命名等常見要點(diǎn)。這邊就一筆略過。因?yàn)楸疚闹攸c(diǎn)是CMake構(gòu)建原生庫。 所以ndk的一些基礎(chǔ)知識(shí),以及JNI等,就不細(xì)說。本文假設(shè)讀者知道這些。這樣的一個(gè)新的支持原生代碼的項(xiàng)目創(chuàng)建之后,并且還自帶demo,開發(fā)者就可以很方便在上面進(jìn)行開發(fā)。 假設(shè)現(xiàn)在要?jiǎng)?chuàng)建一個(gè)原生庫進(jìn)行ndk開發(fā),我們?cè)赾pp文件夾下new一個(gè)C/C++ Source file ,在你new出來的文件編寫你的C/C++代碼邏輯,然后在CMakeLists.txt配置文件上稍作配置,即可。下面會(huì)詳述CMakeLists.txt 的配置。 

向現(xiàn)有項(xiàng)目添加原生代碼

向現(xiàn)有項(xiàng)目添加原生代碼,進(jìn)行ndk開發(fā),這里選擇一個(gè)我的項(xiàng)目,空閑時(shí)間寫的一個(gè)APP,  一款仿今日頭條的資訊類軟件(求star)-

PalmRead

https://github.com/MRYangY/PalmRead

主要有三個(gè)大步驟。第一步:創(chuàng)建新的原生源文件;第二步:創(chuàng)建CMake構(gòu)建腳本;第三步:將Gradle關(guān)聯(lián)到原生庫。現(xiàn)在我們來看第一步,創(chuàng)建新的原生源文件,首先我們要先在應(yīng)用模塊src/main 目錄下創(chuàng)建一個(gè)cpp文件夾用來存放原生源文件等。然后在cpp文件夾下面創(chuàng)建C/C++源文件New > C/C++ Source File。如圖:

創(chuàng)建了一個(gè)名為 palmread-lib 文件。第二步,我們創(chuàng)建CMake構(gòu)建腳本,也就是CMakeLists.txt 文件,在應(yīng)用模塊下new一個(gè)file文件,命名為 CMakeLists.txt 即可,注意哦,這個(gè)文件的名稱不能搞錯(cuò)哦。CMakeLists.txt 創(chuàng)建好打開后,發(fā)現(xiàn)沒有任何內(nèi)容,這就對(duì)了。。需要我們自己配置的。不像是通過第一種新創(chuàng)建支持原生代碼的項(xià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} )

通過圖片我們看到,其實(shí)內(nèi)容也沒什么。就cmake_minimum_required()add_library()、find_library、target_link_libraries()。這幾個(gè)CMake命令,每個(gè)CMake命令都有英文介紹很好理解。比如add_library創(chuàng)建和命名一個(gè)庫,這邊名稱我們就填palmread-lib,種類分為static和shared,具體區(qū)別嘛移步:

static和shared的區(qū)別

https:///questions/2649334/difference-between-static-and-shared-libraries

這里我們選擇 SHARED,然后就是提供一個(gè) library 的相對(duì)路徑。只有在 CMakeLists.txt 文件中配置了該命令 ,才能找到編譯這個(gè)庫。其他的一些 CMake 命令大家自行搜索了解,都不是很難,很好理解,這里篇幅有限就不細(xì)說了。那現(xiàn)在我們可以按照系統(tǒng)提供的模板,基于自己的項(xià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 庫,這里我這邊寫了一個(gè) 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的快捷鍵來實(shí)現(xiàn)的,右鍵點(diǎn)擊你想要關(guān)聯(lián)到原生庫的模塊(例如 app 模塊), 并從菜單中選擇 Link C++ Project with Gradle。 BuildSystem選擇CMake,projectpath 就是CMakeLists.txt文件的路徑。點(diǎn)擊ok完成。 

你會(huì)在應(yīng)用模塊的build.gradle文件中發(fā)現(xiàn),android閉包里出現(xiàn)了

externalNativeBuild {        cmake {            path 'CMakeLists.txt'        }    }

這個(gè)語句就跟我們之前說的第二種方式有關(guān)系,這里先不說了,后面博文再說。

同步項(xiàng)目后,突然想到之前新建的palmread-lib.c文件好像還沒有寫C代碼呢,呀,這腦子,沒事,我們現(xiàn)在寫。  寫些什么呢?這樣吧我們用C來實(shí)現(xiàn)這樣一個(gè)功能,接受一個(gè)字符串參數(shù),然后對(duì)字符串進(jìn)行拼接修改操作  ,使得返回一個(gè)新的字符串。  

代碼如下:

#include 'jni.h' #include #include JNIEXPORT jstring JNICALL Java_com_example_yangyu_palmread_Logic_NdkHelper_GetStringFromC(JNIEnv *env, jclass type,                                                                jstring str_) {    const char *a = (*env)->GetStringUTFChars(env, str_, 0);    // TODO    char * b = ' from c' ;    char *result = malloc(strlen(a)+strlen(b)+1);    strcpy(result, a);    strcat(result, b);    (*env)->ReleaseStringUTFChars(env, str_, a);    return (*env)->NewStringUTF(env, result); }

代碼寫好之后,就是去調(diào)用了,為了方便測(cè)試,我們選在在應(yīng)用的首頁activity去調(diào)用這個(gè)原生方法。  通過toast顯示方法返回的值。  

如圖:

通過代碼,我們可以看出,我們調(diào)用了,NdkHelper.GetStringFromC()這個(gè)原生方法,傳入一個(gè)“歡迎來到PalmRead”字符串作為參數(shù)。按照之前的 C 邏輯,應(yīng)該會(huì)返回一個(gè)新的字符串為  “歡迎來到PalmRead from c”。  那我們運(yùn)行程序試試效果吧。  

O(∩_∩)O哈!,我們發(fā)現(xiàn)toast顯示的值確實(shí)是我們?cè)O(shè)想的返回值。這樣就架起了Java與原生代碼之間的橋梁。 現(xiàn)在我們可以應(yīng)用模塊的build/outputs/apk目錄下,打開我們的apk,我們會(huì)發(fā)現(xiàn),我們創(chuàng)建的原生文件,編譯成了原生庫'libpalmread-lib.so'也打包進(jìn)了apk文件。如圖:  


結(jié)語


好了,關(guān)于CMake來進(jìn)行 Android NDK 開發(fā),大致的流程就是這樣。CMakeLists 的一些命令 還有Gradle關(guān)聯(lián)原生庫的第二種通過編輯build.gradle文件的方式 , 通過 CMake 來進(jìn)行ndk開發(fā)之補(bǔ)充篇

http://blog.csdn.net/qq_34902522/article/details/78144127

 有詳細(xì)說明。

最后給大家做個(gè)推薦,隔壁鴻洋新開發(fā)了一個(gè)Android開發(fā)者必看的網(wǎng)站,域名是 http:// ,里面有不少干貨文章,大家有興趣的話可以登錄這個(gè)網(wǎng)站瞧一瞧。


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    99精品人妻少妇一区二区人人妻| 91久久精品国产成人| 国产精品推荐在线一区| 91老熟妇嗷嗷叫太91| 国产午夜福利在线免费观看| 清纯少妇被捅到高潮免费观看| 欧洲一级片一区二区三区| 国产成人av在线免播放观看av | 激情图日韩精品中文字幕| 国产偷拍盗摄一区二区| 亚洲精品国产福利在线| 日韩毛片视频免费观看| 国产成人综合亚洲欧美日韩| 精品日韩欧美一区久久| 日本高清不卡一二三区| 日本少妇aa特黄大片| 免费在线播放不卡视频| 好吊妞在线免费观看视频| 国产对白老熟女正在播放| 久久精品国产99国产免费| 日韩美成人免费在线视频| 欧美日韩免费黄片观看| 国产成人亚洲精品青草天美| 伊人欧美一区二区三区| 九九热在线免费在线观看| 搡老熟女老女人一区二区| 国产午夜精品久久福利| 丁香七月啪啪激情综合| 成人精品一区二区三区在线| 欧美自拍系列精品在线| 国产不卡的视频在线观看| 日韩欧美一区二区黄色| 五月婷婷六月丁香狠狠| 邻居人妻人公侵犯人妻视频| 国产精品一区日韩欧美| 激情内射亚洲一区二区三区| 日本精品最新字幕视频播放 | 欧美丰满人妻少妇精品| 出差被公高潮久久中文字幕| 在线观看视频成人午夜| 日木乱偷人妻中文字幕在线|