[NDK开发]Android JNI 开发之静态注册

NDK  2022年5月27日 am8:08发布2年前 (2022)更新 91es.com站长
80 0 0

前言

简单记录一下,方便自己查阅。

PS: Android jni开发主要依赖Android开发平台,sdk和ndk三个部分

Android SDK : Version 31
JAVA Sdk    : java1.8
NDK         : android-ndk-r21d

上面只是举个例子,具体环境需要自己搭建。

静态注册

静态注册:先由Java得到本地方法的声明,然后再通过JNI实现该声明方法。

  1. 优点: 理解和使用方式简单, 属于傻瓜式操作, 使用相关工具按流程操作就行, 出错率低
  2. 缺点: 当需要更改类名,包名或者方法时, 需要按照之前方法重新生成头文件, 灵活性不高
动态注册

动态注册:动态注册JAVA的Native方法,使得c/c++里面方法名 可以和 java 的Native方法名可以不同, 动态注册是将将二者方法名关联起来,以后在修改Native方法名时,只需修改动态注册关联的方法名称即可

  1. 优点: 灵活性高, 更改类名,包名或方法时, 只需对更改模块进行少量修改, 效率高
  2. 缺点: 对新手来说稍微有点难理解, 同时会由于搞错签名, 方法, 导致注册失败

正文

直入正题。本文介绍的是JNI静态注册。

第一步

新建一个Android 工程,这里命令为MyDeviceABI

然后新增一个DeviceABI.java

package com.biumall.mydeviceabi;

public class DeviceABI {
    static {
        //so库名也定义为DeviceABI
        System.loadLibrary("DeviceABI");
    }

    // 定义一个接口
    public static native String getDeviceABI();
}

第二步

使用Android Studio的Terminal

进入DeviceABI.java所在的目录,然后:

javac DeviceABI.java

然后退到MyDeviceABI\src\main\java目录下,执行

javah com.biumall.mydeviceabi.DeviceABI

生成

com_biumall_mydeviceabi_DeviceABI.h

我这里会改名字,具体看自己

DeviceABI.h

第三步

在MyDeviceABI工程根目录中创建jni目录

MyDeviceABI\jni

把DeviceABI.h(这里是生成的,没有改变)放入jni。

然后在jni目录中创建DeviceABI.c文件(从DeviceABI.h复制再改动的)

DeviceABI.c,完整版如下:

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

#ifndef _Included_com_biumall_mydeviceabi_DeviceABI
#define _Included_com_biumall_mydeviceabi_DeviceABI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_biumall_mydeviceabi_DeviceABI
 * Method:    getDeviceABI
 * Signature: ()Ljava/lang/String;
 */

 // 此处开始有改动,其他的都是拷贝DeviceABI.h

JNIEXPORT jstring JNICALL Java_com_biumall_mydeviceabi_DeviceABI_getDeviceABI
  (JNIEnv * env){

    #if defined(__arm__)
      #if defined(__ARM_ARCH_7A__)
        #if defined(__ARM_NEON__)
          #if defined(__ARM_PCS_VFP)
            #define ABI "armeabi-v7a/NEON (hard-float)"
          #else
            #define ABI "armeabi-v7a/NEON"
          #endif
        #else
          #if defined(__ARM_PCS_VFP)
            #define ABI "armeabi-v7a (hard-float)"
          #else
            #define ABI "armeabi-v7a"
          #endif
        #endif
      #else
       #define ABI "armeabi"
      #endif
    #elif defined(__i386__)
       #define ABI "x86"
    #elif defined(__x86_64__)
       #define ABI "x86_64"
    #elif defined(__mips64)  /* mips64el-* toolchain defines __mips__ too */
       #define ABI "mips64"
    #elif defined(__mips__)
       #define ABI "mips"
    #elif defined(__aarch64__)
       #define ABI "arm64-v8a"
    #else
       #define ABI "unknown"
    #endif

    return (*env)->NewStringUTF(env, "Compiled with ABI " ABI ".");
  }
// 改动结束
#ifdef __cplusplus
}
#endif
#endif

PS: 如果你要复制,请记得改变函数名,这里函数涉及到包名。

第四部

这部分主要是新增Android.mk和Application.mk文件。

Android.mk
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := DeviceABI
LOCAL_SRC_FILES := DeviceABI.c

include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_ABI := all

具体配置就不细说,后续会总结、

第五步

进入 MyDeviceABI\jni> 然后执行 ndk-build

如果程序或者配置没问题,就编译正常。

E:\MyDeviceABI\jni>ndk-build

[arm64-v8a] Compile        : DeviceABI <= DeviceABI.c
[arm64-v8a] SharedLibrary  : libDeviceABI.so
[arm64-v8a] Install        : libDeviceABI.so => libs/arm64-v8a/libDeviceABI.so
[x86_64] Compile        : DeviceABI <= DeviceABI.c
[x86_64] SharedLibrary  : libDeviceABI.so
[x86_64] Install        : libDeviceABI.so => libs/x86_64/libDeviceABI.so
[mips64] Compile        : DeviceABI <= DeviceABI.c
[mips64] SharedLibrary  : libDeviceABI.so
[mips64] Install        : libDeviceABI.so => libs/mips64/libDeviceABI.so
[armeabi-v7a] Compile thumb  : DeviceABI <= DeviceABI.c
[armeabi-v7a] SharedLibrary  : libDeviceABI.so
[armeabi-v7a] Install        : libDeviceABI.so => libs/armeabi-v7a/libDeviceABI.so
[armeabi] Compile thumb  : DeviceABI <= DeviceABI.c
[armeabi] SharedLibrary  : libDeviceABI.so
[armeabi] Install        : libDeviceABI.so => libs/armeabi/libDeviceABI.so
[x86] Compile        : DeviceABI <= DeviceABI.c
[x86] SharedLibrary  : libDeviceABI.so
[x86] Install        : libDeviceABI.so => libs/x86/libDeviceABI.so
[mips] Compile        : DeviceABI <= DeviceABI.c
[mips] SharedLibrary  : libDeviceABI.so
[mips] Install        : libDeviceABI.so => libs/mips/libDeviceABI.so

我的编译成功后,libs中出现对应的so库等。

├─arm64-v8a
├─armeabi
├─armeabi-v7a
├─mips
├─mips64
├─x86
└─x86_64

因为我的存在libs,最后一步配置就是直接引用。

第六步

配置 so库,网上很多种,看自己习惯。

在工程中的build.gradle,新增如下内容:

android {
    compileSdkVersion 31

    // 

    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
}

可能存在问题

下面是我偷懒,复制时,出现的问题

java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String com.biumall.mylog.DeviceABI.getDeviceABI() (tried Java_com_biumall_mylog_DeviceABI_getDeviceABI and Java_com_biumall_mylog_DeviceABI_getDeviceABI__)
    at com.biumall.mylog.DeviceABI.getDeviceABI(Native Method)
    at com.biumall.mylog.MainActivity$1.onClick(MainActivity.java:21)

这里是由于包名路径不对,导致找不到,所以不建议直接复制。

参考文章

  1. android JNI 开发之第一个 JNI 实例
  2. Android jni 开发详细流程

 历史上的今天

  1. 2023: Android批量拷贝文件(0条评论)
  2. 2021: [代码片段]通过pinyin4j实现汉字转拼音(0条评论)
  3. 2018: Java多线程编程核心技术的笔记之1(0条评论)
  4. 2018: Callable的简单使用(0条评论)
  5. 2018: Eclipse历史版本下载(0条评论)
版权声明 1、 本站名称: 91易搜
2、 本站网址: 91es.com3xcn.com
3、 本站内容: 部分来源于网络,仅供学习和参考,若侵权请留言
3、 本站申明: 个人流水账日记,内容并不保证有效

暂无评论

暂无评论...

随机推荐

Launcher2源码之壁纸设置

上回我们简单介绍了Launcher中的布局,这次我们看看如何设置壁纸。在Launcher界面,长按空白处,就会弹出如上图的壁纸设置对话框。直接上代码Launcher.java1. onCreate() 加载布局和初始化控件 @Override protected v...

ListView item布局简单记录

前言简单记录一下ListView中ItemLayout正文下面布局按下后文字和图片都按按下效果颜色变化。隐藏内容!付费阅读后才能查看!¥2 ¥3多个隐藏块只需支付一次付费阅读参考文章

SurfaceView和TextureView介绍

前言TextureView和SurfaceView常用于视频播放画面显示,项目中根据各种需求需要在二者中选中。这次记录一下他们之间的区别和特点。正文 个人随笔,只是简单总结,谢谢隐藏内容!评论可看后才能查看!评论可看参考文章《SurfaceView 与 TextureView ...

adb logcat的基本使用

adb logcat基本用法1. adb logcat //打印默认所有日志2. adb logcat -s tag //打印带有tag标签的所有日志3. adb logcat -v time //打印所有日志并带上时间4. adb logcat -s tag -v time //...

Android ListView 滚动条的简单记录

前言用了多次还是容易忘记,因此这里记录一下,方便自己查阅。好记性不如烂笔头主要是摘抄的。正文android:scrollbars是否显示滚动条,它的取值可以是vertical,horizontal或none。android:scrollbarThumbVertical控制垂直滚动条...

JNI学习手册

前言之前初略的学习了一下JNI的使用,也做了对应的笔记。为了方便自己复现,这里就把所有文章整理在一起,方便自己查询。正文JNI之数据类型Java中调到Native方法传递的参数是Java类型,这些参数需要通过Dalvik虚拟机转换为JNI类型。具体请看《JNI之类型介绍》基本数据类型...