android studio ndk-build 編譯C生成.so文件(ndk基礎篇)

 本文轉自:你我學習網: https://www.niwoxuexi.com/blog/android/article/246.html

一、概要

最近項目需要,要把代碼中加密的部分打包成so文件,剛開始接觸的時候真是痛苦呀,網上好多資料,都不是很詳細,步驟也不清晰,所以我整理了一下,希望大家喜歡。

現在android studio打包so文件有兩種方式,第一種是ndk-build編譯項目,還有一種用CMake腳本構建項目,今天主要介紹ndk-build的編譯過程

二、ndk-build 構建過程

1,下載NDK和構建工具

正所謂:“工慾善其事必先利其器”,我們今天的主要工具是Android Studio2.3版本,至於 Android Studio環境搭建,sdk,jdk什麼的,你們自己去弄,這裏主要是講解ndk編譯c語言的配置。

爲您的應用編譯和調試原生代碼,您需要以下組件:

  • Android 原生開發工具包 (NDK):這套工具集允許您爲 Android 使用 C 和 C++ 代碼,並提供衆多平臺庫,讓您可以管理原生 Activity 和訪問物理設備組件,例如傳感器和觸摸輸入。

  • CMake:一款外部構建工具,可與 Gradle 搭配使用來構建原生庫。如果您只計劃使用 ndk-build,則不需要此組件。

  • LLDB:一種調試程序,Android Studio 使用它來調試原生代碼。

您可以使用 SDK 管理器安裝這些組件:

  1. 在打開的項目中,從菜單欄選擇 Tools > Android > SDK Manager(或者在頂部工具欄中直接點擊SDK Manager, 下圖的標記就是從這裏點擊的)

  2. 點擊 SDK Tools 標籤。

  3. 選中 LLDBCMake 和 NDK 旁的複選框,如圖 1 所7ab0072474-ndkbuild01.png

  4. 點擊 Apply,然後在彈出式對話框中點擊 OK

  5. 安裝完成後,點擊 Finish,然後點擊 OK

SDK環境配置:

提前新建一個測試用的項目 NdkDemo

  1. 切換到Project工程目錄,打開Project Structure (方法一,直接在工具欄打開,如下圖所示,方法二, 右鍵工程目錄 -> Open Module Settings)

  2. 選擇左邊欄 SDK Location

  3. 在Android NDK Location 位置,選擇 ndk安裝包的路徑,一般放在sdk目錄下(下圖是我mac系統放置ndk的路徑,windows系統也類似,大家自己選擇)

  4. 點擊 OK0ae3d12f10-ndkbuild02.png

  5. 爲最外層工程目錄下的gradle.properties的文件末尾加上android.useDeprecatedNdk=true這段代碼(如果沒有這個目錄,自己新建一個),如下圖所示:7d55d7970c-ndkbuild03.png

Ok,上面我們把環境給配置好了,下面我們就可以寫Java和C代碼了

2,Java代碼和C代碼的編寫過程

1,首先新建一個java類JNIUtils.java,代碼如下

public class JNIUtils {
    // 加載native-jni
    static {
        System.loadLibrary("native-jni");
    }
    //java調C中的方法都需要用native聲明且方法名必須和c的方法名一樣
    public native String stringFromJNI();
}

2,重新Make Project一下工程如下圖2-1,完成後會在工程目錄 ... /NdkDemo/app/build/intermediates/classes/debug/com/niwoxuexi/ndkdemo 看到自己編譯後的classes文件JNIUtils.class如下圖2-2所示:

b41b59db7b-ndkbuild04.png

圖:2-1

ba02455df6-ndkbuild05.png

圖:2-2

3,用javah工具生成頭文件

1) 首先新建一個java類JNIUtils.java,

2) 代碼在studio打開Terminal命令行工具,打開步驟是View->Tool Windows->Terminal (或者在下邊的工具欄中直接打開或直接按Alt+F12)

在命令行中先進入到工程的main目錄下

3) 輸入命令:javah -d jni -classpath 自己編譯後的class文件的絕對路徑

例如:

javah -d jni -classpath /Users/zhuxiaocheng/android/workspace/NdkDemo/app/build/intermediates/classes/debug com.niwoxuexi.ndkkemo.JNIUtils

注意: 1, debug後的空格

2, windows 系統路徑中的文件的分割線是 '\' 而不是mac系統的 '/

7468a56fe0-ndkbuild06.png

4)按回車之後就會在main目錄下生成jni文件夾,同時生成.h文件 如下圖所示

bdbabdee80-ndkbuild07.png


5) 現在我們在jni目錄下新建一個 native-lib.c 的 c 文件,內容如下

//
// Created by 朱孝誠 on 2017/8/30.
//
#include "com_niwoxuexi_ndkdemo_JNIUtils.h"
/**
 * 上邊的引用標籤一定是.h的文件名家後綴,方法名一定要和.h文件中的方法名稱一樣
 */
JNIEXPORT jstring JNICALL Java_com_niwoxuexi_ndkdemo_JNIUtils_stringFromJNI
        (JNIEnv *env, jobject ojb){
    return (*env) -> NewStringUTF(env,"Hello, I'm from jni");
}

6)會後在app的build.gradle配置文件中添加如下代碼:

//ndk編譯生成.so文件
ndk {
    moduleName "native-lib"         //生成的so名字
    abiFilters "armeabi", "armeabi-v7a", "x86"  //輸出指定三種abi體系結構下的so庫。
}

如圖所示:

771675167e-ndkbuild08.png


7) 最後在我們來測試一下,只需要在MainActivity中調用一下C就可以了,代碼如下:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView textView = (TextView) findViewById(R.id.text);
        textView.setText(new JNIUtils().stringFromJNI());
    }
}

8) 直接運行項目,結果如下所示:

49fd5be0bc-ndkbuild09.png


ok,沒問題,可以調用,其實也沒有想象中的那麼難。

代碼地址:https://p_w_picpath.niwoxuexi.com/blog/download/NdkDemo.zip

三、調用編譯過的 .so 庫

上邊編譯完成了,有人會問:我要的是編譯後的.so庫,別人用的時候直接拿來用就可以了,那編譯後的.so庫在哪呢?不要着急,請看下圖:

40aaf041d0-ndkbuild10.png


根據這個路徑就可以找到指定輸出的三種體系結構下的.so庫文件,然後把.so文件複製出來,如下圖所示的放到相應libs的文件夾,

1, 把複製的so包,放到項目的libs目錄下

2, 在app module 下的buide.gradle 中添加下面代碼:

//放在libs目錄中
sourceSets {
    main {
        jniLibs.srcDirs = ['libs']
   }
}

如圖所示:

40412ce769-ndkbuild11.png


ok, 這樣就可以了

四、總結

也沒什麼好總結的,直接按照上面步驟一步一步來,就可以了,jni調用過程有什麼問題,歡迎留言!

最後是貼上代碼地址:https://p_w_picpath.niwoxuexi.com/blog/download/NdkDemo%202.zip


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