当前位置:   article > 正文

Android JNI编程并生成so库_安卓jni中使用静态so库

安卓jni中使用静态so库

Android JNI编程并生成so库

Android Studio配置

下载配置NDK

下载NDK: 点击如下按钮,或者在 File->settings->Android SDK->SDK Tools中检查NDK是否下载,如果没有就需要下载并配置一下,除了需要NDK之外,还需要下载LLDB、CMake这两个编译工具。
在这里插入图片描述
在这里插入图片描述

配置NDK路径

local.properties文件或者 file -> project Structure ->Sdk Location 配置好androidNDK;

在这里插入图片描述

编写native方法和c文件

编写Native接口方法: 编写一个java类,并在Java文件中声明native方法。

public class NdkTools {
    public static native String getStrFromNative();
}
  • 1
  • 2
  • 3

点击build中的make project编译一下项目,获取对应的class文件:app->build->intermediates目录下,
在这里插入图片描述
在AS的Terminal面板下,进入到路径/app/build/intermediates/javac/debug/classes下,执行javac -h -jni com.example.test2.NdkTools ,正常情况也可以用 javah -jni com.example.test2.NdkTools (com.example.test2是自己的包名)生成.h文件,生成完毕之后如下:

在这里插入图片描述

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_test2_NdkTools */

#ifndef _Included_com_example_test2_NdkTools
#define _Included_com_example_test2_NdkTools
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_test2_NdkTools
 * Method:    getStrFromNative
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_test2_NdkTools_getStrFromNative
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

在工程main目录下创建目录命名为jni,将刚才生成的.h文件剪切过来,在jni目录下新建一个c文件,命名为ndktest.c,如下图:
在这里插入图片描述
写ndkdemotest.c文件如下:

#include "com_example_test2_NdkTools.h"

JNIEXPORT jstring JNICALL Java_com_example_test2_NdkTools_getStrFromNative
(JNIEnv *env,jclass NDKTools){
    return (*env)->NewStringUTF(env,"Hello World,this is Ndk");
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

新电脑,所以中间遇到个问题说一下:1,jdk环境变量配置好;2,javah 命令在java高版本上已经被javac -h替换,有些同学可能会遇到javah命令找不到的错误;

编写配置文件生成so库

在jni目录下新建Android.mk和Application.mk文件,这两个文件是编译so时用到的脚本文件。Android.mk和Application.mk的语法和说明可以参考详解。配置选项不多,根据我们的需求进行配置,这里的配置尽量选择少一点,根据我下面的注释修改的脚本文件。
android.mk

LOCAL_PATH := $(call my-dir)      #my-dir 表示当前文件夹,一般不用修改
include $(CLEAR_VARS)             #这个配置需要,但是不用做修改
LOCAL_MODULE := ndktest-jni       #ndktest-jni就是命名so的名称,如果不是以lib开头,编译后的so文件名会以lib+文件名作为so名称
LOCAL_SRC_FILES := ndktest.c      #指定需要编译的c++/c文件
include $(BUILD_SHARED_LIBRARY)   #这个不用修改
  • 1
  • 2
  • 3
  • 4
  • 5

Application.mk

APP_PLATFORM := android-23  #必选,定义使用的ndk库函数版本号。
APP_MODULES := ndktest-jni #指定需要编译模块名子
APP_ABI := armeabi-v7a #编译so的平台,根据你的需求选择这些'armeabi','x86', 'armeabi-v7a', 'x86_64'
  • 1
  • 2
  • 3

添加ndktest.c文件

#include "com_example_test2_NdkTools.h"

JNIEXPORT jstring JNICALL Java_com_example_test2_NdkTools_getStrFromNative
(JNIEnv *env,jclass NDKTools){
    return (*env)->NewStringUTF(env,"Hello World,this is Ndk");
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

编译c++:到terminal中切换到jni目录,执行ndk-build;

D:\workspace\Test2\app\src\main\jni> ndk-build
  • 1

ndk-buil命令结束之后,会在libs目录中出生成对应平台的so文件,这里我只配置了armeabi-v7a这一种格式。
在这里插入图片描述
现在编译so的过程就完成了,接下来就是使用so了。
Android.mk和Application.mk的语法和说明可以参考详解

使用so库

首先需要在gradle里面配置so文件的目录,如果不指定jniLigs.srcDirs, 会报找不到so的错误。
在//在Android{}里面配置如下。

        sourceSets.main{
            jni.srcDirs = []
            jniLibs.srcDirs = ['src/main/jniLibs']
        }
  • 1
  • 2
  • 3
  • 4

接着就是编写我们的使用代码了,代码如下 ,需要注意的是,我们在加载so文件的时候,前缀“lib”不需,直接使用我们命名的文件名就可以了

class MainActivity : AppCompatActivity() {

    private lateinit var appBarConfiguration: AppBarConfiguration
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        setSupportActionBar(binding.toolbar)

        val navController = findNavController(R.id.nav_host_fragment_content_main)
        appBarConfiguration = AppBarConfiguration(navController.graph)
        setupActionBarWithNavController(navController, appBarConfiguration)

        binding.fab.setOnClickListener { view ->
        //使用native方法的地方
            Snackbar.make(view, NdkTools.getStrFromNative(), Snackbar.LENGTH_LONG)
                .setAction("Action", null).show()
//            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
//                    .setAction("Action", null).show()
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

运行之后如图:
在这里插入图片描述

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号