NDK撩妹三部曲(二)—論“Android 實戰如何使用 C++ so 庫這個神祕武器?”之帶妹實戰篇

NDK撩妹三部曲(一)—站住同學,我這有個C++的so庫,底層運算效率飛起,想不想要?

從何說起?

  上禮拜在妹子面前秀了一波後,妹子事後頻頻要請我喝奶茶,還說我明明可以靠臉喫飯,卻偏偏要靠才華(我淦,內外兼修纔是我追求的終極奧義)。堅持了3天,終於抵擋不住妹子的熱情,當然,妥協是因爲飢渴,不對,是因爲奶茶,還不對,不是因爲奶茶,而是本着助人爲樂,共同學習,分享快樂的宗旨,獻上我寶貴的“NDK”寶典。拂去1cm厚的灰塵,翻到,328頁,對,就是這兒,“論 Android 實戰如何使用 C++ so 庫這個神祕武器?”。

寶典摘要

  不管你是葵花寶典還是九陰真經,都少不了“摘要”、“目錄”這幾章吧,可千萬不要小看了這一點點內容,它可是真正武功祕籍的濃縮所在,也就是說全是精華,可謂一字值千金,百字通氣海。

  如果你是一個初學者,當拿到一個 so 庫時,可能不知道怎麼辦了,因爲“聽說 Native 有點難呀”,老有人嚇你。然後當你鼓足勇氣挑戰一下,我靠,JNI 真…踏馬的麻煩。
  而又當你是一個老司機時,你一定會霹靂拍啦一陣操作,生成 JNI 頭文件,再實現,再編譯 so,看起來很簡單,但是擡頭一看,幾個小時過去了,這還不包含可能出現的錯誤。當然了,有點誇張,只是舉例說明一下 JNI 方式的繁瑣。
  今天我們帶妹子嘗試另一種姿勢,不對,另一種方式,使用 SUN 公司的 JNA 代替 JNI 的繁瑣過程,一會兒你就知道這讓我們調用 Native 方法有多舒服。

和妹子一起操作

一、新建 Android 項目,jnatest:

在這裏插入圖片描述在這裏插入圖片描述
進入 libs 文件夾,然後根據你需要的 Android ABI 建立相應的文件夾,如 arm64-v8a 、armeabi-v7a。

二、從官網下載 JNA 包:

https://github.com/java-native-access/jna/releases

解壓後,進入下圖的目錄:
在這裏插入圖片描述
上圖中分別標識了不同的 Android ABI 對應的 JNA 庫,把自己需要的 jar 包複製出來並解壓,我們選擇 android-aarch64.jar ,會得到一個 libjnidispatch.so 文件,將其複製到上面我們新建的 arm64-v8a 或者 armeabi-v7a 文件夾中。

再次回到 dist 目錄,複製裏面的 jna-min.jarjna-platform.jar 粘貼到上面的 libs 目錄。
在這裏插入圖片描述

三、依賴庫拷貝

3.1 如果你是個純 C++ 的 so 庫,到 ndk 目錄下拷貝 libc++_shared.so 文件到上面的 rm64-v8a 目錄。

科普:
libc++_shared 和 libgnustl_shared 均爲 C++ 標準庫,因爲不同的 NDK 版本要求了不同的 C++ 標準。
   1、libc++,從 Lollipop 開始的官方安卓系統和現代 Mac 操作系統都將其作爲C++標準庫使用。從 NDK17 開始,它將成爲 NDK 中唯一可用的 C+ + 標準實現。

   2、gnustl,libstdc++ 的別名,這兩者在 GNU/linux 是同一個庫。這個庫的已被棄用,它在NDK 18 中被刪除;

   3、STLport,由 STLport 項目編寫的 C++ 標準庫的第三方實現,自2008年以來一直處於不活躍狀態。與gnustl一樣,STLport在NDK 18 中被刪除;

3.2 如果你是個 QT 的 so 庫,往下看:
  首先在任意地方新建一個文件夾,然後複製下面的內容命名爲: android-libjnatest.so-deployment-settings.json

{
   "description": "This file is generated by qmake to be read by androiddeployqt and should not be modified by hand.",
   "qt": "D:/WorkSoftware/QT5.12.0_for_Android/5.12.0/android_arm64_v8a",
   "sdk": "C:/Users/HiWin10/AppData/Local/Android/Sdk",
   "sdkBuildToolsRevision": "26.1.1",
   "ndk": "D:\\Java\\android-ndk-r16-windows-x86_64\\android-ndk-r16",
   "toolchain-prefix": "aarch64-linux-android",
   "tool-prefix": "aarch64-linux-android",
   "toolchain-version": "4.9",
   "ndk-host": "windows-x86_64",
   "target-architecture": "arm64",
   "stdcpp-path": "D:/Java/android-ndk-r16-windows-x86_64/android-ndk-r16/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so",
   "application-binary": "E:/VPlayer_git/release/arm64-v8a/libjnatest.so"
}

其次將你編譯出的 so 庫也放到此目錄在此目錄,
最後打開 cmd 窗口,並輸入以下內容。或者將下面的內容放到 test.bat 中,雙擊此 bat 文件執行:

"D:/WorkSoftware/Qt5.12.0_for_android/5.12.0/android_arm64_v8a/bin/androiddeployqt.exe" --input E:/VPlayer_git/release/arm64-v8a/android-libjnatest.so-deployment-settings.json --output E:/VPlayer_git/release/arm64-v8a/android-build

完成後可以看到在當前目錄下創建了 android-build 目錄,依次進入 libs 目錄,再進入 arm64 目錄,可以看到這裏面即爲當前你編譯的 libjnatest.so 庫要在 android 環境下運行所要依賴的庫(此處我使用的是我們項目真正的庫文件,只是修改了名字,這樣更能貼近真實的情況。假如我用一個簡單的 so 庫測試,可能會出現和大家不一樣的情況,比如依賴庫不全等等問題)。
在這裏插入圖片描述
將上面這些庫拷貝到第二步中的 rm64-v8a 文件夾中。然後別急,再將剛纔 libs 目錄下的 QtAndroid.jarQtAndroidBearer.jar 文件拷貝到第二步中的 rm64-v8a 的外層
在這裏插入圖片描述
即下圖的目錄。(是否有這兩個 jar 包取決於我們編譯的庫是否有相關依賴,如果沒有不用複製
在這裏插入圖片描述

四、萬事俱備,只欠東風——修改 gradle 文件和添加 JNA 代碼

4.1 在 MainActivity 同級新建 Jna.java 文件,如下:

package com.qht.jnatest;
import com.sun.jna.Library;
import com.sun.jna.Native;

public interface Jna extends Library {
    /*
     * Step1:
     * JNA加載.so庫,通過Native.loadLibrary()方法來加載,不帶前綴“lib”
     */
    Jna INSTANCE = Native.loadLibrary("jnatest", Jna.class);
    /*
     * Step2:
     * 重寫與C/C++源文件名稱相同的方法,不需要用到的方法可以不用寫
     */
    int test(int a,int b);
}

4.2 MainActivity 添加一句話即可:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView tv = (TextView) findViewById(R.id.tv);
        int result = Jna.INSTANCE.test(20,500);
        tv.setText("引用so,計算結果:" + result);
    }
}

4.3 編輯 app 下的 build.gradle 文件:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.qht.jnatest"
        minSdkVersion 16
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    packagingOptions {
        exclude 'META-INF/XXXX'
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs'] //相當於將libs文件夾當做jnilibs文件夾
        }
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation files('libs/jna-min.jar') //將這4個jar包含到項目
    implementation files('libs/jna-platform.jar')
    implementation files('libs/QtAndroid.jar')
    implementation files('libs/QtAndroidBearer.jar')
}

完成之後 右鍵點擊 jna-min.jar 包,選擇add as library,最後點小錘子 make 一下:
在這裏插入圖片描述
如果不報錯,再將項目切到 Android 視圖,可以看到是不是多了一個 jniLibs 目錄:
在這裏插入圖片描述
最後點擊小三角,run:
在這裏插入圖片描述

我靠,剛過完 520,又來個 601,妹子這是給我什麼暗號???


csdn地址:http://blog.csdn.net/u012534831
github地址:https://github.com/qht1003077897 \

如有幫助,請多多點贊支持哦。

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