Android studio NDK成長記錄(一)CMake

Android studio NDK開發支持CMake和ndk-build兩種編譯方式:

第一種:CMake編譯方式的開發步驟

  1. 下載安裝studio     下載地址:“http://www.android-studio.org/
  2. 新建項目
  3. 下載安裝ndk插件:File右鍵->setting->Android SDK->SDK Tool勾選CMake,LLDB,NDK,將這三個插件全都安裝上。
  4. 查看是否關聯上NDK,也可以手動添加(local.properties末尾加上如下代碼)
    //這是自己的ndk地址,注意轉義,下面的地址本來是"E:\Android\SDK\ndk-bundle"
    ndk.dir=E\:\\Android\\sdk\\ndk-bundle
  5. gradle.properties文件末尾添加代碼"android.useDeprecatedNdk=true"(爲了適配低版本)
  6. 在module(如app:)目錄下創建一個CMake的配置文件(CMakeLists.txt,必須是這個名字,這個文件是用於關聯上gradle和CMake的),必須配置以下幾個基本屬性,如有需要並熟悉CMake語法,可自行酌情增加,可參考下面CMakeLists.txt的配置。(也可以在創建項目的時候勾選上support c++,studio就會自動創建該文件,並配置好gradle,並且會在MainActivity中生成一個native方法,創建一個cpp文件,和一個native-lib.cpp文件。這時候只需要去修改CMakeLists.txt中的參數,並且刪除cpp中自動生成的cpp文件,改成自己想要的就行。
    #CMakeLists.txt配置內容如下
    #版本
    cmake_minimum_required(VERSION 3.4.1)
    
    add_library( 
                # 決定編譯出來的so庫的名稱(這個配置文件得到的是libhello.so).
                 hello
                 # 動態 這樣studio會將so庫打包到你的apk中
                 SHARED  
                 #c文件的地址,若有多個文件,直接一一列出,以空格或者換行隔開       
                 src/main/cpp/hello.c src/main/cpp/test.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.
                           hello
    
                           # Links the target library to the log library
                           # included in the NDK.
                           ${log-lib} )
  7. 關聯CMake和gradle,配置這個的主要原因是爲了讓studio在編譯的時候能找到你的資源文。
    有兩種方式:有的同學不一定Link C++ Project with Gradle選項,就用第二種
    (1)自動關聯,將工程改爲Android視圖,右鍵選中module(如app),選擇Link C++ Project with Gradle,下拉選項中選擇CMake,瀏覽找到你的項目中的CMakeLists.txt文件。(2.)手動關聯,在module(如app)下的build.gradle中做如下配置externalNativeBuild屬性
    android {
        compileSdkVersion 25
        buildToolsVersion "25.0.0"
        defaultConfig {
            applicationId "com.picovr.ndksupporttest"
            minSdkVersion 15
            targetSdkVersion 25
            versionCode 1
            versionName "1.0"
            externalNativeBuild {
                cmake {
                    cppFlags "-frtti -fexceptions"  }
            }
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
        externalNativeBuild {
            cmake {
                path "CMakeLists.txt"  }
        }
    }
  8. 創建一個java類,在裏面申明一個native方法
    package com.picovr.ndksupporttest.mynative;
    
    /**
     * Created by PICO-USER Dragon on 2017/1/17.
     */
    
    public class JNI {
        public static native String getString();
    }
  9. 創建.c或者cpp源文件,和頭文件。(下面以c語言爲例)
    第一種方式:
    在mian目錄下新建cpp文件夾。
    選中Android Studio的左下角Terminal面板,輸入命令“cd app/src/main/java”進入java目錄,執行命令“javah 包名+類名“,這個命令是調用jdk中的javah.exe程序對native方法所在的Java類生成一個對應的.h頭文件。這種方式生成的.h頭文件中,自動將native方法在C語言中所對應的方法名全部生成出來了。然後將生成的.h文件剪切到cpp文件夾,並將.h文件中放方法名稱copy到c文件中,將參數補全即可。
    生成.h文件的命令如:“javah com.picovr.ndksupporttest.mynative.JNI”
    第二種方式:
    在main目錄新建文件夾cpp,右鍵新建C/C++ Source File 勾選上Create an asscoiated hearder,這樣就會生成一個.c文件和.h的頭文件,這個.h文件不會像第一種方式那樣自動生成native方法在C語言中所對應的方法名,需要自己手動去寫。在學習階段建議手動去做,更好地瞭解並熟悉jni的一些規則。
    java中的native方法對應C語言中的方法的規則在下面的代碼中已經詳細解釋:
    copy下面的代碼的時候,導包hello.h和jni.h分別copy,因爲每個人的頭文件名字不一樣。ndk安裝路徑也不一樣,所以jni.h所在目錄不一樣。
    /* Created by PICO-USER Dragon on 2017/1/17.
      導包的時候要注意
      1.你自己創建的.h文件必須要
      2.jni.h必須要,這個導包的時候,studio應該會提示,其實就是你安裝ndk所在目錄下的platforms目錄中的任意
      一個版本中,可以在電腦中按照下面jni.h的那個路徑中找來看看
     */
    #include "hello.h" #include "../../../../../../Android/SDK/ndk-bundle/platforms/android-21/arch-x86_64/usr/include/jni.h"
    #include <stdio.h>
    #include <stdlib.h>
    /**
     * 命名規則:返回值類型 + 方法名
     * 方法名:Java+包名+類名+方法名,並且把'.'改爲'_'
     *
     * JNIEXPORT和JNICALL 可要可不要string Java_com_picovr_ndksupporttest_mynative_JNI_getString(JN *IEnv *env, jobject jobj)也行
     *
     * jstring 是返回值對應java中的String類
     * JNIEnv *env 必須參數,在C中必須要用到這個參數去調用方法
     * jobject jobj 必須參數 不一定用到
     */
    JNIEXPORT jstring JNICALL
    Java_com_picovr_ndksupporttest_mynative_JNI_getString(JNIEnv *env, jobject jobj) {
    
        //jstring     (*NewStringUTF)(JNIEnv*, const char*);其實是在調用ndk-build中的jni.h中的方法
        return (*env)->NewStringUTF(env, "The first jinDemo for Dragon !");
    
    }
  10. 加載動態鏈接庫
    在native方法所在類中增加靜態代碼塊,加載動態鏈接庫
    package com.picovr.ndksupporttest.mynative;
    
    /**
     * Created by PICO-USER on 2017/1/17.
     */
    
    public class JNI {
    
        // Used to load the 'native-lib' library on application startup.
        static {
            //"hello"是so庫的名字,也就是CMakeLists.txt文件中add_library()屬性中的第一個參數
            System.loadLibrary("hello");
        }
    
        public static native String getString();
    
    }
  11. 調用native方法getstring()。看看是否能成功調用。



發佈了34 篇原創文章 · 獲贊 23 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章