JNI小记1 -- VS生成so给AS调用

万年不变的环境配置

NDK 下载 | Android NDK | Android Developers (google.cn)
需要提的是,直到本文撰写的时间,我在这个页面下的NDK是只有x86-64平台的。而我测试时确实只有x64编译成功。
在visual studio里新建一个安卓共享库工程:
JNI小记1 -- VS生成so给AS调用_第1张图片

刚开始的界面应该是这样的:
JNI小记1 -- VS生成so给AS调用_第2张图片

而后在: 工具->选项->跨平台 选上我们的ndk目录(这里和交叉编译工具链一样,把此前的ndk压缩包解压到你期望的目录):
JNI小记1 -- VS生成so给AS调用_第3张图片

JNI小记1 -- VS生成so给AS调用_第4张图片

再选择项目的重定解决方案:
JNI小记1 -- VS生成so给AS调用_第5张图片

重定好后可以再项目配置(项目->属性)里修改如下(这里clang最好改成5.0):
JNI小记1 -- VS生成so给AS调用_第6张图片

接下来配置include和lib目录。
快速定位这两个目录可以这样,在ndk目录搜索"log.h"(这个也是项目默认所需要引用的)
JNI小记1 -- VS生成so给AS调用_第7张图片

我们要用的是toolchains->llvm的。跳转过去找lib和include文件夹即可
接着将对应目录填进来(包含和引用),添加正确只后可以看到:
JNI小记1 -- VS生成so给AS调用_第8张图片
JNI小记1 -- VS生成so给AS调用_第9张图片

JNI小记1 -- VS生成so给AS调用_第10张图片

环境配置基本完成。

在VS-Android-So默认模板的基础上写JNI

工程一开始如下:
JNI小记1 -- VS生成so给AS调用_第11张图片

需要注意的是,我们的项目在默认情况下是编译不过的。因为定义LOGI、LOGW处的关键字"ANDROID_LOG_INFO"是NDK的头文件"log.h"里才被定义的内容,这里还没被引用。
开头引用:#include
如果之前的配置步骤一致,编译正常是通过的。
而之后我们再添加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 
#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:
JNI小记1 -- VS生成so给AS调用_第12张图片

这里也是参考网上的一个配置脚本,把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:
JNI小记1 -- VS生成so给AS调用_第13张图片

static:
JNI小记1 -- VS生成so给AS调用_第14张图片

引用:
JNI小记1 -- VS生成so给AS调用_第15张图片
跑起来:
JNI小记1 -- VS生成so给AS调用_第16张图片

你可能感兴趣的:(android,java,JNI)