NDK 之生成so庫

Android Studio 配置 NDK(一)

什麼是ndk, 簡單的講就是ndk可以讓你調用到c/c++方法來實現一些比較安全的功能,例如你完全可以將Android程序的數據 通過c/c++原來編寫存儲, 然後通過jni方式調用方法,而且在實現的時候, 也可以各種加密,讓後程序的數據更加安全。

最近想給項目應用增量更新,所以就折騰了一下ndk。

和以往的ndk開發方式不太一樣。

1.現在查到的資料大部分套路都是需要先通過javah文件方式生成.h文件, 然後寫對應的實現文件.c /. cpp,最終配置文件android.mk, Application.mk,放在jni目錄下, 執行ndk-build命令,最終生成可用的.so庫

2.使用官方提供的gradle-experimental插件(gradle的版本和插件版本要對應),照着官方文檔在gradle中一頓配置後, 編寫native 方法,alter+enter鍵,最終還是未出來。

最終發現, 其實現在的android studio都是很智能,配置好模塊,make project的時候自動幫你編譯生成.so庫文件, 基本上不用配置什麼,最終還是能很容易的就編出hello world。這裏只是簡單的講一下ndk建立項目的一些初步問題, 高手請繞道。

1.新建立一個項目:
2.配置gradle

 android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.caldremch.myapplication"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"

        ndk{
            moduleName = "cade"

            //abiFilters "x86","armeabi-v7a" //這裏填寫兩個abi cpu架構,如果什麼都不寫,則默認支持所有平臺
        }

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

3.建立一個類 ,包含native方法,此時會有看到方法是紅色的, 這很正常的

public class JNITest {

    static {
        System.loadLibrary("cade"); //這裏的cade跟gradle配置的modulename一致
    }

    public native String getAA(); //native方法

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

4.切刀Java目錄 ,輸入命令.javah -d ../jni 包名.類名(例如com.cade.utils.JNITest)
,生成.h文件, 編寫對應的.c文件

這裏寫圖片描述


hello.c文件爲:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <string.h>
#include "hello.h" //這裏注意, 如果剛纔沒有改文件名,那麼這裏就不是hello.h了

jstring Java_com_caldremch_myapplication_JNITest_getAA
  (JNIEnv * env, jobject clazz)
  {

    return (*env)->NewStringUTF(env, "測試成功沒有");

  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

準備工作已經差不多了, 接下里還要在gradle.properties文件中加上一句:


android.useDeprecatedNdk=true //不加有可能導致編譯不成功
  • 1
  • 2
  • 1
  • 2

執行編譯:菜單欄 build—》make project(��圖標)

在MainActivity中引測試

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView textView = (TextView) findViewById(R.id.text);
        textView.setText(new JNITest().getAA());
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

接下來我們看看到底.so庫在哪裏生成了?

這裏寫圖片描述

看到結果了吧。

這裏說幾點:
1.配置不讓gradle自動編譯,自己編譯,那麼在build.gradleandroid節點下設置

//    sourceSets.main{
//            jni.srcDirs = []//設置禁止gradle生成Android.mk
//            jniLibs.srcDirs = ['src/main/jniLibs']//設置目標的so存放路徑
//    }
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

2.如果一個項目中,有多個引用的.so庫, 請注意一點, 一定讓它們支持的cpu abi數量和類型 一樣。不然會報錯 java.lang.UnsatisfiedLinkError
例如在一同一個項目中有ndk模塊

   ndk {
            moduleName = 'module1'

            abiFilters "x86","armeabi-v7a"
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

在另一個依賴項目:

   ndk {
            moduleName = 'module2'

            abiFilters "x86","armeabi-v7a"
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

如果它們 abiFilters不一樣,數量或者類型有別, 那麼將導致錯誤。

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