Android NDK基础

Android JNI(一) —— NDK与JNI基础 Android jni也是开发中的一个重要环节,也是实现java与C交互的平台,接下来就来学习JNI. 本篇文章大纲如下: 1、导读 2、什么是NDK 3、为什么使用NDK 4、NDK到SO 5、JNI 一、导读 在Android OS上开发应用程序,Google提供了两种开发包:SDK和NDK。你可以从Google官方查阅到有许多关于SDK的优秀书籍、文章作为参考,但是Google提供的NDK... 阅读详情

一、JNI 的概念

1、概念

JNI全称 Java Native Interface,Java 本地接口。可以通过JNI调用系统提供的API。

2、JNI 与 NDK 的区别
  • JNI:JNI是一套编程接口,用来实现Java代码与本地C/C++代码的交互。
  • NDK:NDK是Google开发的一套开发和编译工具集,可以生成动态链接库,主要用于Android的JNI开发。
3、JNI 的作用
  • 扩展: JNI扩展了JVM能力,驱动开发,例如开发一个wifi驱动,可以将手机设置为无限路由。
  • 高效: 本地代码效率高,游戏渲染,音频视频处理等方面使用JNI调用本地代码,C语言可以灵活操作内存。
  • 复用:在文件压缩算法 7zip开源代码库,机器视觉 OpenCV开放算法库等方面可以复用C平台上的代码,不必在开发一套完整的Java体系,避免重复发明轮子。
  • 特殊: 产品的核心技术一般也采用JNI开发,不易破解。

二、JNI 两种注册方式

(一)、静态注册

开发流程如下:

  1. 在 Java 中先声明 native 方法。

  2. 编译 Java 源文件得到 .class 文件。

  3. 使用 Javah -jni 命令生成对应的头文件。

    • 命令 javah -jni packagename.classname 生成由包名加类名命名的 jni 层头文件。
    • 命令 javah -o custom.h packagename.classname,其中 custom.h 为自定义的文件名。
  4. 实现 JNI 里面的函数(生成.c文件),再在Java中通过System.loadLibrary加载 so 库。

PS:javah 是 JDK 自带的一个命令,-jni 参数表示将 class 中用到 native 声明的函数生成 JNI 规则的函数

Demo:

  1. 创建项目

首先创建一个 Android 项目,包名:com.zf.ndkdemo

  1. 创建引用本地库的工具类

创建一个 Java 类 NDKTools

package com.zf.ndkdemo;

public class NDKTools {
    public static native String stringFromJNI();
}

  1. 在MainActivity中调用 NDKTools 的 stringFromJNI()方法
package com.zf.ndkdemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import java.io.File;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView tv = (TextView) findViewById(R.id.sample_text);
        tv.setText(NDKTools.stringFromJNI());
    }
}
  1. 获取classes文件

(1)点击 AndroidStudio 中的 Make Project 或者 Rebuild Project 进行编译获取class文件。(Build --> Make Project 或者 Build --> Rebuild Project)

(2)编译完成之后,按照如下目录寻找class文件。

app/build/intermediates/classes/debug/com/zf/ndkdemo

image

  1. 获取.h文件
    点击AndroidStudio下面Terminal,然后进入app/build/intermediates/classes/debug目录下,然后执行命令:javah -jni com.zf.ndkdemo.NDKTools 。如果一切顺利则会在app/build/intermediates/classes/debug下面生成com_zf_ndkdemo_NDKTools.h文件。如下图:
    image
    内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_zf_ndkdemo_NDKTools */

#ifndef _Included_com_zf_ndkdemo_NDKTools
#define _Included_com_zf_ndkdemo_NDKTools
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_zf_ndkdemo_NDKTools
 * Method:    stringFromJNI
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_zf_ndkdemo_NDKTools_stringFromJNI
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif
  1. 增加对应的.c文件
    在工程main目录下创建jni文件夹,然后将刚刚生成的.h剪切过来。然后再在jni目录下生成一个.c文件ndkdemo.c
//
// Created by zf on 2019/1/17.
//

#include "com_zf_ndkdemo_NDKTools.h"

JNIEXPORT jstring JNICALL
Java_com_zf_ndkdemo_NDKTools_stringFromJNI
        (JNIEnv *env, jobject obj) {
    return (*env)->NewStringUTF(env, "Hello world,我的第一行NDK代码");
}
  1. 添加并编写Android.mk文件
    在jni目录下生成一个Android.mk文件,内容如下:
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := ndkdemo-jni

LOCAL_SRC_FILES :=ndkdemo.c

include $(BUILD_SHARED_LIBRARY)
  1. 修改相关配置文件
  • local.properties 文件中添加 NDK 路径
ndk.dir=D\:\\Sdk\\ndk-bundle
sdk.dir=D\:\\Sdk
  • 修改 app module 目录下的 build.gradle 文件,内容如下:
apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.zf.ndkdemo"
        minSdkVersion 18
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        ndk{
            moduleName "ndkdemo-jni"
            abiFilters "armeabi", "armeabi-v7a", "x86"
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        externalNativeBuild {
            ndkBuild {
                path 'src/main/jni/Android.mk'
            }
        }
        sourceSets.main {
            jni.srcDirs = []
            jniLibs.srcDirs = ['src/main/jniLibs']
        }

    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
  • gradle.properties 文件中添加: Android.useDeprecatedNdk=true
  1. 修改引用类 NDKTools
public class NDKTools {
    static {
        System.loadLibrary("ndkdemotest-jni");
    }
    public static native String stringFromJNI();
}

over

(二)、动态注册

开发流程如下:

  1. 编写 Java 的 native 方法;
  2. 编写 JNI 函数的实现(函数名随意);
  3. 利用结构体 JNINativeMethod 保存 Java native 方法和 JNI 函数的对应关系;
  4. 利用 RegisterNatives(JNIEnv*, jclass, const JNINativeMethod*,jint) 注册类的所有本地方法;
  5. 第3、4步的代码在 JNI_OnLoad 方法中执行。
  6. 在编写 Java native 方法的类中通过 System.loadLibrary 加载 JNI 动态库,然后会自动调用 JNI_OnLoad 函数,完成动态注册。

三、JNI 数据类型映射

  • 基本数据类型:
Java类型本地类型(Native Type)描述
booleanjbooleanC/C++无符号8位整型 (unsigned char)
bytejbyteC/C++带符号8位整型 (char)
charjcharC/C+无符号16位整型 (unsigned short)
shortjshortC/C++带符号16位整型 (short)
intjintC/C++带符号32位整型 (int)
longjlongC/C++带符号64位整型 (long)
floatjfloatC/C++32位浮点型 (float)
doublejdoubleC/C++64位浮点型 (double)

基本数据类型的映射即在Java的基本数据类型前面添加 j 就是本地类型的基本数据类型

  • 引用数据类型:
Java类型本地类型(Native Type)描述
Objectjobject任何java对象
ClassjclassClass类对象
Stringjstring字符串对象
Object[]jobjectArray任何对象的数组
boolean[]jbooleanArray布尔型数组
byte[]jbyteArray比特型数组
char[]jcahrArray字符型数组
short[]jshortArray短整型数组
int[]jintArray整型数组
long[]jlongArray长整形数组
float[]jfloatArray浮点型数组
double[]jdoubleArray双浮点型数组
voidvoid

注意:

a、应用数据类型不能在Native层使用,需要根据 JNI 函数转化后才能使用;
b、多维数组都是引用类型。

 //获得一维数组的类引用,即jintArray类型  
jclass intArrayClass = env->FindClass("[I");   
//构造一个指向jintArray类一维数组的对象数组,该对象数组初始大小为length,类型为 jsize
jobjectArray obejctIntArray  =  env->NewObjectArray(length ,intArrayClass , NULL); 
  • 方法和变量的id

当Native要调用Java层方法的时候,需要通过JNI函数获取对应的id,根据id调用 JNI 函数获取该方法。变量同理。

id 结构如下:

struct _jfieldID;                       /* opaque structure */
typedef struct _jfieldID* jfieldID;     /* field IDs */

struct _jmethodID;                      /* opaque structure */
typedef struct _jmethodID* jmethodID;   /* method IDs */

时间问题,未完待续…

参考链接:
Android NDK开发:JNI基础篇
Android JNI

Android Studio NDK基础使用 NDK是什么?Android平台是基于java实现,运行于虚拟机Dalvik;故而使用Android SDK创建应用程序需要使用java语言来编写实现。不过并不仅限于使用java,google在发布android之初就宣称支持持JNI编程方式,也就是第三方应用完全可以通过JNI调用自己的C动态库,即在Android平台上,“Java+C”的编程方式是一直都可以实现的。 阅读详情

相关推荐

Android中集成FFmpeg及NDK基础知识

log-lib说一千道一万,不如自己去行动。要想在移动互联网的下半场是自己占有一席之地,那就得从现在开始,从今天开始,马上严格要求自己,既重视业务实现能力,也重视基础和原理。基础夯实好了,高楼才能够平地而起,稳如泰山。最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2020-2021面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。还有。

2401_84009529的博客 1004

Android NDK开发基础

仅作为个人学习记录,请小心求证。 https://developer.android.com/ndk/guides?hl=zh-cn 前言 NDK即Native Development Kit,是Android上用来开发c/c++的开发工具包。 安装步骤:https://developer.android.com/studio/projects/install-ndk 一、基础用法 在local.properties中配置ndk目录: ndk.dir=/Users/bc/android-ndk-r1.

BC工坊 5180

Android NDK与JNI基础

什么是NDK Android NDK 是一套工具集合,允许你使用C/C++语言来实现应用程序的部分功能。NDK本身其实就是一个交叉工作链,包含了Android上的一些库文件,然后,NDK为了方便使用,提供了一些脚本,使得更容易的编译C/C++代码。 什么是JNI JNI,全称为Java Native Interface,即Java本地接口,JNI是Java调用Native 语言的一种特性。通...

hwx865的专栏 614

Android NDK : 基本类型,字符串与数组

Android NDK : 基本类型,字符串与数组 Java与native的交互 :基本类型 示例1:获取native返回的整型数据 这个例子比较简单,只是返回一个整型数据,我们可以在android的java代码中接收这个值。 #include"com_cumt_ndktest1_GetInt.h" #include jint getint(){ return 100; } JNIE

cassiePython的专栏 1722

PCB布线避坑指南:为什么你的差分线等长总调不好?AD19蛇形等长技巧详解

本文详细解析了AD19环境下PCB差分线等长调整的核心技巧与常见问题。从差分信号等长的底层逻辑到AD19规则配置,再到蛇形等长高级技巧和信号完整性验证,帮助工程师解决差分线等长调整中的难题,提升高速PCB设计的信号质量。

weixin_28738397的博客 382

MTK Linux DRM分析(十一)- MTK KMS Panel显示屏驱动

面板扩展(Panel Extension)是指 MediaTek 在标准 DRM 面板驱动框架之上添加的定制化功能模块。

iTom1900 1684

Android NDK开发入门基础

一、NDK/JNI NDK NDK(Native Development Kit)-原生开发工具包,使得能够在Android上 去使用C/C++代码; JNI JNI即Java Native Interface,Java和Native接口,就是Java和C/C++之间通讯的桥梁; 为什么要有JNI,因为Java和C/C++之间是无法直接相互调用的,也就是无法直接通讯,就和Java和JS之间也不能直接相互调用,中间需要翻译者来处理,JNI就是为了实现Java和C/C++之间这两种不同语言之间的通讯的; JN

殇神马的博客 1404

自动驾驶仿真 (三)—— 基于PreScan与Simulink的AEB系统仿真

自动驾驶仿真三—— 基于PreScan&Simulink的AEB系统仿真1. AEB自动紧急制动系统1. 1 TTC碰撞时间模型1. 2 C-NCAP法规部分术语与定义1. 3 主动安全ADAS系统试验项目2. AEB仿真分析建模2.1 搭建场景2.2 传感器建模2.3 添加AEB控制系统3. 典型工况仿真3.1 CCRs仿真测试3.1 CCRm仿真测试4. 参考学习的书目教材 博主前面的博文已经介绍了Prescan&Simulink基本的场景建模及仿真分析流程,《自动驾驶仿真 (二)——

zhudj08的博客 1万+

Android NDK ~ 基础入门指南

本文介绍了 NDK 相关的概念如 ABI、JNI、NDK。如何使用 AndroidStudio 开发 NDK 程序。最后介绍了 JNI 的规范中的数据类型和描述符

Chiclaim 2927

【项目实战】主流车载操作系统,QNX实时操作系统入门介绍

QNX是一种实时操作系统,自1980年代初期由Quantum Software Systems成立以来,已被广泛应用于各种行业和领域。QNX具有实时响应、高可靠性和分布式等特点,为各种设备提供了强大的底层操作系统平台。随着科技的不断发展和进步,QNX系统的应用范围和潜力也在不断扩大。本文将全面介绍QNX系统,包括其引言、背景、系统特性、应用领域和生态系统等方面。QNX作为一种实时操作系统,具有高效的实时性能、高可靠性、分布式、可剪裁性和可扩展性等特点。它在各个领域都有广泛的应用,并拥有一个庞大的生态系统。

奶爸的编程之路,也就一周冷个三天 3068

RT-DETR改进策略【RT-DETR和Mamba】| CVPR 2025:EfficientViM 压缩隐藏状态空间进行通道混合、单头设计减少内存操作,提升目标检测效率与精度

本文记录的是利用模块优化的目标检测网络模型。EfficientViM Block(基于隐藏状态混合器的状态空间对偶性模块) 的设计旨在,提升特征提取效率,同时兼顾全局依赖捕捉与局部细节保留。本文将深入研究的原理,并将其应用到中,通过重构特征提取流程、减少内存绑定操作、融合多阶段特征,增强模型在资源受限环境下的检测性能与速度。Depth Information Assisted Collaborative Mutual Promotion Network for Single Image DehazingLE

Limiiiing的博客 916

Android NDK入门开发(一)

JNI(Java Native Interface):Java原生接口,是Java和其他原生代码语言(例如 C 和 C++)通信的桥梁。 NDK(Native Development Kit):原生开发工具集,是一套允许您使用原生代码语言(例如 C 和 C++)实现程序功能的工具集。 CMake:Android推荐使用的NDK构建工具,从AS 2.2版本之后开始支持(包含2.2版本)。 环境搭建:...

你的外祖父的博客 462

【AI大模型应用开发】1.0 Prompt Engineering(提示词工程)- 典型构成、原则与技巧,代码中加入Prompt

Prompt典型构成、原则与技巧,以及OpenAI API重要参数解释,助你轻松入门Prompt

同学小张的博客 2580

Android NDK基础编程入门

对于还不了解Android NDK作用和搭建的朋友,可以先参考下Android NDK作用与搭建,今天这篇文章是建立在已经搭建好Android NDK开发环境,来看看NDK编程 "Hello Jni"的实现。   首先Android NDK开发需要具备哪些基础知识? 1.熟悉Android应用开发 2.熟悉C语言(编写底层.so库需要用到) 3.了解Linux(要知道一些常用的命令)

花花大神的专栏 1443

最新Python爬虫实战(入门爬虫篇)——案例1:某瓣网站Top250图片数据采集(附上完整爬虫代码)

本次案例通过Python爬虫技术实现了某瓣Top250电影封面的批量下载。代码采用模块化设计,函数实现cookies的自动解析,简化了配置流程,涵盖请求、解析、存储的完整流程。学习重点包括:抓包工具定位数据源、正则表达式匹配图片链接、模拟请求头绕过反爬机制、以及自动化文件管理。需要注意控制请求频率并遵守网站使用规范,适用于入门爬虫实践。

努力让自己发光,对的人才能迎着光而来 16万+

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Android-NDK的基础使用

NDK基础 目录 环境信息 NDK是什么 JNI是什么 如何进行NDK开发 总结两点 创建工具 进行具体操作 第一步: 进行NDK开发的当然是下载NDK开发包 ,并在项目中配置好 第二步: 新建Java...

qq_36583893的博客 1149

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Android JNI(一)——NDK与JNI基础

本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Native相互调用 Android JNI学习(四)——JNI的常用方法的中文API Android JNI学习(五)——Demo演示 本片文章大纲如下: 1、导读 2、什么是NDK ...

木叶风的博客 280

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Android NDK基础和NDK独立编译SO环境搭建

目录 NDK编译SO环境搭建... 1 修订... 3 1. Android NDK基础... 4 1.1 简介... 4 1.2 结构... 4 1.3 目录详解... 6 1.4 工具详解... 7 1.4.1ndk-build.cmd. 7 1.4.2 Android.mk构建规则脚本... 8 1.4.3 Application.mk构建配置脚本... 18 1.5 Android NDK其他... 23 1.5.1 Android版本号... 23 1.5.2 精简内容.

Bonaventure的博客 838

Android NDK开发基础知识

概要Android NDK开发对于初学者来说,往往会有丈二和尚摸不着头脑之感,所以在此处理清一些基础知识,总体来说有以下几个方面: ABI概念的理解。 使用C++的两种方式(Android Studio)。 Gradle配置.so文件的格式。 使用.so的注意事项。 ABI概念的理解到目前为止,Android系统总共支持7种不同的CPU架构,分别是: ARMv5 ARMv7 x86 MIPS ARM

沐雨清风 619

Android JNI——NDK与JNI基础

Android JNI(一)——NDK与JNI基础本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Native相互调用 Android JNI学习(四)——JNI的常用方法的中文API Android JNI学习(五)——Demo演示 本片文章大纲...

蚂蝗征途 400

Android NDK --- JNI从入门到基础的全面掌握 (下)

【代码】Android NDK --- JNI从入门到基础的全面掌握 (下)

Mark Wu 的博客 277

[ 转载 ] Android JNI(一)——NDK与JNI基础

Android JNI(一)——NDK与JNI基础 隔壁老李头关注 4.42018.05.09 17:15*字数 5481阅读 11468评论 8喜欢 140 本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)...

weixin_30266885的博客 122
上一篇: Android 组件化
下一篇: (一)Android基础系列之:ActionBar
azhoufeng
博客等级 码龄10年 10粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值