Android 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();
}

点击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

在工程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,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)   #这个不用修改

Application.mk

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

添加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");
}

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

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

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']
        }

接着就是编写我们的使用代码了,代码如下 ,需要注意的是,我们在加载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()
        }
    }

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

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android开发,我们经常需要使用C/C++编写一些高效的底层代码,为了将这些代码与Java代码结合起来使用,我们需要在Android Studio生成.so文件。 首先,我们需要在Android Studio创建一个新的本地模块。在项目的右上角或者从菜单栏选择"File" -> "New" -> "New Module",选择"Native Library"并点击"Next"。然后,我们可以选择使用C/C++进行编程或者使用CMake或ndk-build来构建.so文件。如果选择使用CMake,我们需要在CMakeLists.txt文件添加相关的源文件和。如果选择使用ndk-build,我们需要创建一个Android.mk文件,并在其指定源文件和。 接下来,我们需要在项目的根目录创建一个JNI文件夹,并将C/C++源文件放在该文件夹。在CMakeLists.txt添加具体的源文件路径,在Android.mk也需要指定源文件路径。 然后,我们需要配置项目的build.gradle文件以使用NDK工具链。在build.gradle文件,我们需要将ndk的路径添加到android.defaultConfig.ndk和externalNativeBuild.cmake的路径。如果我们选择使用ndk-build来构建.so文件,则需要在build.gradle文件添加ndkBuild路径。 最后,我们需要在Android Studio点击"Build" -> "Make Project"来生成.so文件。生成的.so文件将位于项目的\app\build\intermediates\cmake\debug\obj文件夹(如果使用的是CMake)或者\app\build\intermediates\ndk\debug\lib文件夹(如果使用的是ndk-build)生成.so文件后,我们可以在Java代码加载它并调用其函数。与生成的.so文件相关的Java类将在构建过程自动生成。 总而言之,通过以上步骤,我们可以在Android Studio生成.so文件,并将其与Java代码结合使用,从而实现更高效和灵活的Android开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值