Android中JNI的使用方法

Android studio 简单方便的使用JNI调用c语言中的方法 今天尝试了在Android studio中调用JNI,历尽千辛万苦终于成功了。不说废话,只谈步骤: 第一步:在gradle.properties文件中添加  Android.useDeprecatedNdk = true 第二步:将鼠标光标移到你的项目上按f4,选中SDK Location,这一步的是添加NDK,一般来说在最下面的NDK location是没有的,点击旁边的下载 阅读详情

Android中JNI的使用方法

首先看一下Android平台的框架图:(网上盗用)

    


  可以看到Android上层的Application和ApplicationFramework都是使用Java编写,

底层包括系统和使用众多的LIiraries都是C/C++编写的。

  所以上层Java要调用底层的C/C++函数库必须通过Java的JNI来实现。

下面将学习Android是如何通过Jni来实现Java对C/C++函数的调用。以HelloWorld程序为例:

第一步:

使用Java编写HelloWorld 的Android应用程序:

复制代码
package com.lucyfyr;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class HelloWorld extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  Log.v("dufresne", printJNI("I am HelloWorld Activity"));
}
  static
  {
    //加载库文件
    System.loadLibrary("HelloWorldJni");
  }
   //声明原生函数 参数为String类型 返回类型为String
  private native String printJNI(String inputStr);
}
复制代码

 

  这一步我们可以使用eclipse来生成一个App;

因为eclipse会自动为我们编译此Java文件,后面要是用到。


第二步:

  生成共享库的头文件:

  进入到eclipse生成的Android Project中 :/HelloWorld/bin/classes/com/lucyfyr/ 下:

  可以看到里面后很多后缀为.class的文件,就是eclipse为我们自动编译好了的java文件,其中就有:

    HelloWorld.class文件。

  退回到classes一级目录:/HelloWorld/bin/classes/

执行如下命令:

  javah com.lucyfyr.HelloWorld

  生成文件:com_lucyfyr_HelloWorld.h

 

复制代码
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_lucyfyr_HelloWorld */
#ifndef _Included_com_lucyfyr_HelloWorld
#define _Included_com_lucyfyr_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_lucyfyr_HelloWorld
* Method: printJNI
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_lucyfyr_HelloWorld_printJNI
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
复制代码

 

  可以看到自动生成对应的函数:Java_com_lucyfyr_HelloWorld_printJNI

    Java_ + 包名(com.lucyfyr) + 类名(HelloWorld) + 接口名(printJNI):必须要按此JNI规范来操作;

  java虚拟机就可以在com.simon.HelloWorld类调用printJNI接口的时候自动找到这个C实现的Native函数调用。

  当然函数名太长,可以在.c文件中通过函数名映射表来实现简化。


第三步:

实现JNI原生函数源文件:

新建com_lucyfyr_HelloWorld.c文件:

 

复制代码
#include <jni.h>
#define LOG_TAG "HelloWorld"
#include <utils/Log.h>
/* Native interface, it will be call in java code */
JNIEXPORT jstring JNICALL Java_com_lucyfyr_HelloWorld_printJNI(JNIEnv *env, jobject obj,jstring inputStr)
{
  LOGI("dufresne Hello World From libhelloworld.so!");
  // 从 instring 字符串取得指向字符串 UTF 编码的指针
  const char *str =
  (const char *)(*env)->GetStringUTFChars( env,inputStr, JNI_FALSE );
  LOGI("dufresne--->%s",(const char *)str);
  // 通知虚拟机本地代码不再需要通过 str 访问 Java 字符串。
  (*env)->ReleaseStringUTFChars(env, inputStr, (const char *)str );
  return (*env)->NewStringUTF(env, "Hello World! I am Native interface");
}
/* This function will be call when the library first be load. * You can do some init in the libray. return which version jni it support. */ jint JNI_OnLoad(JavaVM* vm, void* reserved) {   void *venv;   LOGI("dufresne----->JNI_OnLoad!");   if ((*vm)->GetEnv(vm, (void**)&venv, JNI_VERSION_1_4) != JNI_OK) {     LOGE("dufresne--->ERROR: GetEnv failed");     return -1;   }
  return JNI_VERSION_1_4; }
复制代码

 

  OnLoadJava_com_lucyfyr_HelloWorld_printJNI

函数里面做一些log输出 注意JNI中的log输出的不同。

  JNI_OnLoad函数JNI规范定义的,当共享库第一次被加载的时候会被回调,

这个函数里面可以进行一些初始化工作,比如注册函数映射表,缓存一些变量等,

最后返回当前环境所支持的JNI环境。本例只是简单的返回当前JNI环境。

 

第四步:

编译生成so库

  编译com_lucyfyr_HelloWorld.c成so库可以和app一起编译,也可以都单独编译。

在当前目录下建立jni文件夹:HelloWorld/jni/

  下建立Android.mk ,并将com_lucyfyr_HelloWorld.c和 com_lucyfyr_HelloWorld.h 拷贝到进去

编写编译生成so库的Android.mk文件:

 

复制代码
LOCAL_PATH:= $(call my-dir)
# 一个完整模块编译
include $(CLEAR_VARS)
LOCAL_SRC_FILES:=com_lucyfyr_HelloWorld.c
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_MODULE := libHelloWorldJni
LOCAL_SHARED_LIBRARIES := libutils
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_TAGS :=optional
include $(BUILD_SHARED_LIBRARY)
复制代码

 

系统变量解析:

  LOCAL_PATH - 编译时的目录
  
$(call 
目录,目录….) 目录引入操作符
    
如该目录下有个文件夹名称 src,则可以这样写 $(call src),那么就会得到 src 目录的完整路径

  include $(CLEAR_VARS) -清除之前的一些系统变量
  LOCAL_MODULE 
- 编译生成的目标对象
  LOCAL_SRC_FILES 
- 编译的源文件
  LOCAL_C_INCLUDES 
- 需要包含的头文件目录
  LOCAL_SHARED_LIBRARIES 
- 链接时需要的外部库
  LOCAL_PRELINK_MODULE 
- 是否需要prelink处理 
  include$
(BUILD_SHARED_LIBRARY) - 指明要编译成动态库

  android.mk编译模块添加具体方法参考:http://blog.youkuaiyun.com/yili_xie/article/details/4906865


编译此模块:输入编译命令

  ./makeMtk mm packages/apps/HelloWorld/jni/

  上面是我的工程根目录编译命令。具体编译方式根据自己系统要求执行。

编译输出: libHelloWorldJni.so (system/lib中视具体而定)

  此时库文件编译好了可以使用,如果在eclipse中模拟器上使用,需要将 libHelloWorldJni.so导入到system/lib 下,

  或者对应app的data/data/com.lucyfyr/lib/下;

但是在导入system/lib 下的时候,却始终提示out of memory。于是网上说使用emulator去搞,

  但是此命令使用起来却有问题,始终没有解决。但是可以导入到data/data/com.lucyfyr/lib/下使用。但是我这里直接在真机上弄的。

看一下HelloWorld中Android.mk文件的配置

  其中存在:

    include $(LOCAL_PATH)/jni/Android.mk 表示编译库文件

    LOCAL_JNI_SHARED_LIBRARIES := libHelloWorldJni 表示app依赖库,打包的时候会一起打包。


第五步:

验证执行

  将编译好的apk安装到手机上

  使用adb push到手机上去需要自己去导入库文件libHelloWorldJni.so到data/data/com.lucyfyr/lib/

  使用adb install方式安装则会自动导入。

启动HelloWorld :输入命令 adb logcat |grep dufresne

输出log如下:

  I/HelloWorld(28500): dufresne Hello World From libhelloworld.so!

  I/HelloWorld(28500): dufresne--->I am HelloWorld Activity

  V/dufresne(28500): Hello World! I am Native interface

符合调用打印顺序正确。

 

以上通过一个简单的例子学习了Android如何编写编译C库文件,以及如何使用库文件。

对于JNI的使用其中还涉及到其他方面的一些知识:C++接口如何调用,函数名注册表怎么回事,

参数类型如何匹配,JNI如何调用Java中的方法java<--->JNI等。

Android JNI C/C++调用Java方法 JNI环境的支持 Android JNI编程从Java方法来调用native方法是比较容易的, 因为Java本身就提供了native关键字作为索引,只要正确的对应Java方法和native方法的包名,做到这一步并不难. 而从C/C++方法调用Java方法则稍复杂一点,因为C/C++没有提供跨语言调用的直接支持,所以需要由Java的JNI运行环境来提供帮助. 每一个JNI native方法的 阅读详情

相关推荐

Android JNI动态注册Native 方法(实现IDA中改名)

1、Android应用层代码: import android.app.Activity; import android.os.Bundle; import android.widget.TextView; import android.util.Log; public class NdkLoad extends Activity { public static final Stri

Beautiful Attack and Defence 2389

Android JNI精细化讲解,让你彻底了解JNI(中)

Android开发中,随着对移动程序的安全性、性能等方面的重视,JNI技术也越发重要。如今,多数企业在招聘中、高级程序员时,基本上都要求熟悉JNI开发,所以,掌握JNI技术,也是我们迈进心仪企业的必备条件。本套课程共分为三部分,当前为第二部分,主要包括内容:1、JNI函数解析2、JNI类型解析3、JNI描述符(签名)解析4、JNI静态注册与动态注册原理解析5、JNI调用流程原理解析适合人群:1、有一定Android基础,零JNI基础的学员;2、接触过JNI,但却不甚了解的学员;3、使用过JNI,希望解其原理的学员;

在Android系统中添加JNI方法

我们创建了一个JNI头文件来声明要添加的JNI方法,然后实现了这些方法的源代码。最后,我们在Java代码中调用了这些JNI方法,并验证了它们的功能。然后,你可以在适当的位置调用"callNativeMethod"方法,以触发JNI方法的调用。请注意,这里声明了一个名为"nativeMethod"的JNI方法,它将在Java类"com.example.MyClass"中调用。这里我们声明了一个名为"nativeMethod"的本地方法,并在"callNativeMethod"方法中调用它。

CodeJolt的博客 462

Android-JNI的简单使用

一、什么是JNI 1、jni的含义 JNI即为java native interface Java本地接口;JNI是用来调用本地方法的技术,用来使Java和C/C++进行通信。 简单来说,Java运行一个程序需要和不同的系统进行交互,在windows里就要和windows底层平台交互,mac里就要和mac的底层平台交互, JVM就是通过大量的JNI技术能够使Java运行在不同的系统平台当中,与不同的系统平台底层进行交互。 2、Java与JNI类型对照表 基本类型对照 引用类型对照 3、什么是动态库 静态

HZF 6568

UDS服务应该支持哪些否定响应码

UDS服务应该支持哪些否定响应码所有服务都需支持的否定响应码具体的服务需要支持的否定响应码否定响应码定义及其取值 USD诊断服务的否定响应中包含有导致否定响应原因的编码,称为否定响应码(NRC, Negative Response Code)。否定响应码的取值范围为0x00 - 0xFF,被分为三组: 0x00:服务器内部实现否定响应码判断逻辑时使用,表示要给出肯定响应。 0x01 – 0x7F:诊断通信相关的否定响应码。 0x80 – 0xFF:服务器收到诊断服务请求时,由于某些条件不满足要求而给出的否定

闲聊汽车软件开发 4万+

模拟CMOS 第2章 MOS器件物理基础

模拟CMOS 第2章 MOS器件物理基础 文章目录模拟CMOS 第2章 MOS器件物理基础2.1 基本概念2.1.1 MOSEFT开关2.1.2 MOSEFT结构2.1.3 MOS符号2.2 MOS的I/V特性2.2.1 阈值电压2.2.2 I/V特性的推导2.3 二级效应2.4 MOS器件模型2.4.1 MOS器件版图2.4.2 MOS器件电容2.4.3 MOS小信号模型2.4.4 MOS SPICE模型2.4.5 NMOS与PMOS器件的比较2.4.6 长沟道器件与短沟道器件的比较附录A 用作电容器MO

椰子奶糖的博客 5199

Android ——JNI基本了解与使用

JNI (Java Native Interface,Java本地接口)是一种编程框架,使得Java虚拟机中的Java程序可以调用本地应用/或库,也可以被其他程序调用。本地程序一般是用其它语言(C、C++或汇编语言等)编写的,并且被编译为基于本机硬件和操作系统的程序。Android NDK开发之JNI基础Android JNI详解JNI入门到精通: 用Java和C/C++打造高性能应用ANDROID STUDIO 创建一个JNI工程创建JNI基础工程并运行JNI基本知识(一)JNI编程原理。

qq_35231506的博客 2352

傻瓜教程:使用GeoServer发布离线地图服务

一、离线地图下载 离线地图分为两种:一种叫“金字塔瓦片”数据,一种叫“矢量地图数据”。我们看的在线地图比如,百度,谷歌,高德等等网页上的地图,都是金字塔瓦片;另外一种是手机上用来导航的,比如高德地图APP,也可以下载离线地图数据,这个就是矢量的。 卫星影像地图都是金字塔瓦片,无矢量数据。 因此,我们所说的离线地图下载通常都是指离线地图金字塔瓦片数据下载。 离线地图金字塔瓦片搭建的离线地图服务分很多种:一般有WEB方式,TMS、WMTS/WMS等等,不同的应用有不同...

米兰的小码农的博客 1万+

JNI原理及常用方法概述

JNIEnv概念 :JNIEnv是一个线程相关的结构体, 该结构体代表了 Java 在本线程的运行环境。通过JNIEnv可以调用到一系列JNI系统函数。JNIEnv线程相关性:每个线程中都有一个 JNIEnv 指针。JNIEnv只在其所在线程有效, 它不能在线程之间进行传递。注意:在C++创建的子线程中获取JNIEnv,要通过调用JavaVM的AttachCurrentThread函数获得。

Easyhood的博客 3327

creo二次开发使用映射

在creo进行二次开发时,一些无法直接通过访问底层代码来对特征进行操作,比如“镜像装配”,这个时候就可以使用映射(Mapkey)来完成一键镜像。 注:这是镜像装配的代码 ProError status; ProMacro macro; wstring Macro; strMacro = L"mapkey(continued) ~ Command ProCmdMirrorAssem ; mapkey(continued) ~ Activate mirror_component_dialog Sy

qq_49328512的博客 1607

手把手教你学simulink(16.2)--基于Simulink的高通滤波器(High-Pass Filter)项目

基于Simulink的高通滤波器(High-Pass Filter)项目的详细实例介绍。这个项目将重点放在高通滤波器的设计、实现和仿真上,帮助你理解和应用高通滤波器在信号处理中的作用。

MHD0815的博客 926

android jni 调用 java_安卓应用开发通过java调用c++ jni的图文使用方法

首先建议一个工程 HelloJni如下图:按照默认的配置下一步,直到完成 。如下图操作,点击windows菜单-》Prefrence菜单:弹出如下图:选择Andriod ->NDK:配置完成以后,点击工程属性菜单:做这一步的目的是,增加对c++代码的支持,他会自动生成一些东西,你会看到多一个jni的文件夹。这个名字可以默认,就用工程的名字,实际上就是产生的c++代码生成.so文件的名称(wi...

weixin_31965935的博客 205

s8654

The official Snapdragon Ride SX 4.0 development board provides standardized hardware support for the secondary development and functional verification of the s8654 platform.

qq_39257814的博客 6828

android编写JNI方法

在 这篇文章中将会简单介绍如何编制一些简单的JNI 方法。我们都知道JNI方法可以帮助我们调用用C/c++编写的函数,这样如果一项工作已经用C /c++语言实现的话,我们就可以不用花很大的力气再用JAVA语言对这一工作进行再实现,只要编制相应的JNI函数,就可以轻松实现JAVA语言对C /c++函数的调用,从而大大减轻程序开发人员的工作量。  在这个项目中,我们编制了很多小实例,通过阅读,运

记忆沉思 1154

RK3568 低功耗设计全解析:DVFS 策略与 PMIC 电源管理

本文深入解析RK3568处理器的低功耗优化方案。从硬件架构分析入手,阐述四核Cortex-A55的功耗特性及分层电源域设计。重点介绍DVFS动态调压调频技术,包括Linux内核配置方法及场景化策略设计。详细讲解RK809 PMIC的电源管理优化,提供外设电源域控制与休眠唤醒配置的实战案例。通过智能终端应用实例,展示待机功耗从280mA降至65mA的优化效果,并推荐功率测试工具。文章强调需要平衡性能与功耗,结合场景定制策略,并指出AI负载预测等未来优化方向,为RK3568开发者提供系统性的低功耗解决方案。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 2073

毕设帮扶:从0到1搭建基于YOLOv5的打架斗殴检测系统——助你搞定深度学习毕设

做完这个毕设,你已经掌握了从数据准备到模型部署、界面开发的全流程。把模型部署到边缘设备(如安防摄像头的嵌入式系统)上,实现本地化实时检测与报警;加入行为严重程度分析(如轻微推搡 vs 严重斗殴)、涉事人员数量统计,让系统从“检测”升级为“智能安防决策”;尝试融合声音、红外等多模态数据,打造全方位的暴力事件监测系统。按照这个教程一步步做,你的毕设肯定能做得很扎实。要是过程中遇到啥问题,别担心,慢慢梳理或者咱们一起聊聊,一定能把这个毕设做成你满意的作品。

LXY_LOVE36的博客 119

安卓 tv java_Android为TV端助力 关于JNI的使用方法

1首先在java里面定义你需要的native方法2打开cmd,进入doc窗口,如果是android项目就进入到你当前项目的bin目录下,在doc里面输入cd E:\workspace\Test1 也就是进入你项目的所在地,3.然后在当前项目的根目录创建一个名为jni的目录,用于存储头文件,so库等等4.在doc里面输入javah -classpath bin\classes -d jni com...

weixin_28889765的博客 185

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

android jni 回调 java_安卓开发—JNI开发-在C中回调java中的方法

在C代码 中的实现#include #include #include //回调空参数的方法JNIEXPORT void JNICALL Java_com_example_jnitest2_NativeProviefder_showStringNative(JNIEnv * env , jobject obj){// (*FindClass)(JNIEnv*, const char*);jclas...

weixin_39923110的博客 195

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

android jni 方法映射,Android JNI学习

JNI是Android中比较重要的一块知识,Java层与C/C++层进行调用的桥梁。所以今天就来学习一下JNI相关的知识。JNI(Java Native Interface)JNI(Java Native Interface):java本地开发接口,JNI是一个协议,这个协议用来沟通java代码和外部的本地代码(c/c++),外部的c/c++代码也可以调用java代码。为什么使用JNI?效率上 C...

weixin_33743292的博客 326

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

安卓 jni 开发之 native 方法的动态注册

安卓 jni 开发之 native 方法的动态注册

心现识变妙莲华 1075

Android下如何通过JNI方法向上提供接口总结

参考文献: http://blog.youkuaiyun.com/luoshengyang/article/details/6575988 http://www.androidmi.com/Androidkaifa/rumen/201005/633.html 1 什么是JNI JNI是Java Native Interface的缩写,即Java本地接口.从Java1.1开始,JNI标准成为Ja

放飞梦想,成就未来 1万+

android jni 方法定义,Android JNI与NDK编程

导语Java JNI本意为Java Native Interface(java本地接口), 是为方便java调用C或者C++等本地代码所封装的一层接口. 由于Java的跨平台性导致本地交互能力的不好, 一些和操作系统相关的特性Java无法完成, 于是Java提供了JNI专门用于和本地代码交互。主要内容JNI的开发流程NDK的开发流程JNI的数据类型和类型签名JNI调用Java方法的流程具体内容ND...

weixin_35106801的博客 405

android JNI的一些方法见解

距离上一次写博客过去了 很久,中间想写个MVP+RXjava+Dagger+Retrofit,然后一直耽搁了我会很快补上的,最近项目要用到串口,学习了一会JNI,现在把简介写出来,如果有写的不对的地方,下方评论联系我。 什么是JNI,全称是Java Native Interface(Java 本地接口) 作用是java调用本地语言,那么什么是本地语言呢,通俗来说C语言,C++这些就是本地语言。...

知我饭否 562

Android调用JNI的实现方法

介绍Android如何调用JNI

保温杯拖把风扇的博客 2680

Android jni代码注册本地方法

Android 开发中有时需要调用本地方法,这就需要注册本地方法,而注册的方法有两种: RegisterNatives注册使用javah生成规范的头文件,然后编写对应的源文件。 先看一下java文件 Hello.java,这里面有一个native方法、一个平常方法。 package cn.vn.jniregisternative; public class Hello { sta

奋斗的菜鸟ing 1万+
上一篇: Mac os x下配置 Android ndk 开发环境
下一篇: Android使用JNI实现Java与C之间传递数据
stonenotes123
博客等级 码龄15年 30粉丝 176原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值