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.jar 和 jna-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.jar 和 QtAndroidBearer.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 {
Jna INSTANCE = Native.loadLibrary("jnatest", Jna.class);
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 \
如有帮助,请多多点赞支持哦。