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 \

如有帮助,请多多点赞支持哦。

猜你喜欢

转载自blog.csdn.net/u012534831/article/details/106523533