万年不变的环境配置
NDK 下载 | Android NDK | Android Developers (google.cn)
需要提的是,直到本文撰写的时间,我在这个页面下的NDK是只有x86-64平台的。而我测试时确实只有x64编译成功。
在visual studio里新建一个安卓共享库工程:
刚开始的界面应该是这样的:
而后在: 工具->选项->跨平台 选上我们的ndk目录(这里和交叉编译工具链一样,把此前的ndk压缩包解压到你期望的目录):
再选择项目的重定解决方案:
重定好后可以再项目配置(项目->属性)里修改如下(这里clang最好改成5.0):
接下来配置include和lib目录。
快速定位这两个目录可以这样,在ndk目录搜索"log.h"(这个也是项目默认所需要引用的)
我们要用的是toolchains->llvm的。跳转过去找lib和include文件夹即可
接着将对应目录填进来(包含和引用),添加正确只后可以看到:
环境配置基本完成。
在VS-Android-So默认模板的基础上写JNI
工程一开始如下:
需要注意的是,我们的项目在默认情况下是编译不过的。因为定义LOGI、LOGW处的关键字"ANDROID_LOG_INFO"是NDK的头文件"log.h"里才被定义的内容,这里还没被引用。
开头引用:#include<android/log.h>
如果之前的配置步骤一致,编译正常是通过的。
而之后我们再添加JNI调用函数如下:
Java_com_example_myapplication_MainActivity_HelloWorld(JNIEnv * env, jclass jcls) {
LOGI("init", "012");
return env->NewStringUTF("Hello World!");
}
这里用我目前浅薄的认识稍微解释一下,JNI调用函数是很有讲究的。C层的函数接口,其命名需要和安卓工程的名匹配。(当然也有不一致的写法,但我还没学到)最后一截是函数名,前面那一串都是包名。
完整demo代码如下:
#include "SharedObject2.h"
#include <android/log.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "SharedObject2", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "SharedObject2", __VA_ARGS__))
extern "C" {
/*此简单函数返回平台 ABI,此动态本地库为此平台 ABI 进行编译。*/
const char * SharedObject2::getPlatformABI()
{
#if defined(__arm__)
#if defined(__ARM_ARCH_7A__)
#if defined(__ARM_NEON__)
#define ABI "armeabi-v7a/NEON"
#else
#define ABI "armeabi-v7a"
#endif
#else
#define ABI "armeabi"
#endif
#elif defined(__i386__)
#define ABI "x86"
#else
#define ABI "unknown"
#endif
LOGI("This dynamic shared library is compiled with ABI: %s", ABI);
return "This native library is compiled with ABI: %s" ABI ".";
}
extern "C" jstring Java_com_example_myapplication_MainActivity_HelloWorld(JNIEnv * env, jclass jcls) {
LOGI("init", "012");
return env->NewStringUTF("Hello World!");
}
void SharedObject2()
{
}
SharedObject2::SharedObject2()
{
}
SharedObject2::~SharedObject2()
{
}
}
生成完毕后AS新建工程、、、
而后开始配置build.gradle:
这里也是参考网上的一个配置脚本,把ndk和sourcesSet配置一下:
plugins {
id 'com.android.application'
}
android {
namespace 'com.example.myapplication'
compileSdk 32
defaultConfig {
applicationId "com.example.myapplication"
minSdk 26
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
ndk {
//针对自己项目的架构对应添加相应的so目录
//目前的手机架构基本上都是arm架构,x86的基本上没有,基本上是平板
abiFilters "armeabi-v7a",//arm架构的32位
"armeabi",//十年前的手机CPU架构,基本上已经不存在了
"arm64-v8a",//arm架构的64位
"x86",//x86架构的 32位
"x86_64"//x86架构的64位
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
} compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildFeatures {
viewBinding true
}
sourceSets {
main {
//这里的libs需要替换成你放置so库的目录,比如jniLibs
jniLibs.srcDirs = ['libs']
}
}}
dependencies {
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.navigation:navigation-fragment:2.4.1'
implementation 'androidx.navigation:navigation-ui:2.4.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
接着放上我们的lib:
static:
文章来源:https://www.toymoban.com/news/detail-413592.html
引用:
跑起来:
文章来源地址https://www.toymoban.com/news/detail-413592.html
到了这里,关于JNI小记1 -- VS生成so给AS调用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!