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

NDK  2022年5月27日 am8:08发布2年前 (2022)更新 91es.com站长
90 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、 本站申明: 个人流水账日记,内容并不保证有效

暂无评论

暂无评论...

随机推荐

蒋勋 : 孤独的乐趣

与孤独相处的时候,可以多一点思维的空间,生命的过程会不会更细腻一点?——蒋勋禅宗有一则有趣的故事,小徒弟整天跟老师父说:“我心不安,我心不安。”他觉得心好慌,上课没有心上课,做功课没有心做功课,问老师父到底该怎么办?师父拿出一把刀,说:“心拿出来,我帮你安一安。”心一直在自己身上,心会不安,是被...

UML类图中属性的可见性简介

UML类图中属性的可见性分为4级public 公用的 :用+ 前缀表示 ,该属性对所有类可见protected 受保护的:用 #  前缀表示,对该类的子孙可见private 私有的:用- 前缀表示,只对该类本身可见package 包的:用 ~ 前缀表示,只对同一包声明的其他类可见...

Android监听Home键和Back键的简介

前言Home键和BACK是Android中最实用的,因此本文就简单的介绍一下监听HOME和BACK键。好记性不如烂笔头正文由于Android的管控越来越严格,HOME键已经无法拦截,但可以监听,BACK键的监听和拦截都可以。监听HOME键目前监听HOME的按键,可以监听:public...

Android WindowManager弹窗容易出现的问题

WindowManager弹窗提示时需要注意下,比如系统应用和非系统应用权限的不同、Android不同版本的权限申请不同等,下面是我在应用中出现的问题,因此整理一下。问题一:没有设置android.permission.SYSTEM_ALERT_WINDOW出现异常提示Unable to a...

List排序简单记录

前言简单整理一下List的集合的排序,简单的记录一下,方便自己后续查阅。正文这里介绍一下使用Comparable和Comparator进行排序Comparable在实现的FileInfo实现Comparable,然后实现排序compareTo()即可。具体如下public class ...

罗伯特·弗罗斯特:未选择的路

黄色的树林里分出两条路,可惜我不能同时去涉足,我在那路口久久伫立,我向着一条路极目望去,直到它消失在丛林深处。 但我却选了另外一条路,它荒草萋萋,十分幽寂,啊,留下一条路等改日再见! 但我知道路径延绵无尽头,恐怕我难以再回返。 也许多少年后在某...