Android JNI入门

先啰嗦一段,从学习Android以来一直会看到这个JNI,偶尔也看到要写c/c++的代码,其实从心里就是有些排斥的,毕竟我学的是Java,我学习一个JNI我还得学会c++,c其实是学了一遍了,但是长期不用基本也就忘了,虽然基本的都是看得懂的,但是编码并不是看得懂就行的,要自己能写,所以其实打心底是排斥JNI的.但是学习Android的时间越长,我发现JNI是支撑Android运行的一大模块,比如我们常见的那些播放音频的功能其实底层就是使用了JNI,这样子就让Java代码可以调用底层的c代码,从而可以操纵硬件的目的,所以其实JNI我们可以理解为Java和(c/c++)之间的桥梁,举例一段源码:

MediaPlayer m = new MediaPlayer();
		m.start();
/**
* Starts or resumes playback. If playback had previously been paused,
* playback will continue from where it was paused. If playback had
* been stopped, or never started before, playback will start at the
* beginning.
*
* @throws IllegalStateException if it is called in an invalid state
*/
public  void start() throws IllegalStateException {
    stayAwake(true);
    _start();
}

private native void _start() throws IllegalStateException;

这是播放音频控件的开始播放方法的有关源码,我们可以看到,在start()方法中,调用了一个_start()的方法,这个方法是用native关键字标识的,这就是我们以前经常听到的本地方法,意思就是说这个方法的具体实现是通过c/c++代码实现的,这就是JNI的简单案例

ndk环境的搭建,这里亲们就去谷歌官网去下载就行了,下载完毕解压,然后在eclipse里面关联一下即可

下面让我带大家入门

我带大家做一个简单的加法来学习JNI,首先我们得声明一个方法

private native int add(int i,int j);

方法类似于上面的_start()方法是没有方法体的,类似于接口中的方法声明对不对,没有方法体,然后我们在activity的oncreate()方法中调用这个方法来实现

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	int result = add(3,5);
	System.out.println("result == " + result);
}

调用的时候就和普通方法一样调用就可以了,这样子就可以了?

很明显这样子不够,因为方法的实现我们还没做呢!我们说实现是需要c/c++来实现的,这里设计到书写c/c++代码了.

步骤:

1.在项目根目录建立一个文件夹jni,里面用来书写c/c++代码

2.在jni文件夹下新建一个c/c++源码文件

3.里面自然需要实现我们之前定义个那个方法add了

int add(int i, int j){
	return i + j;
}

c中写一个add方法就是上面这样子书写的,但是使用JNI的时候需要加上JNI的一些规范

首先就是方法名字,规范如下:

Java_包名_类名_方法名

所以代码就需要改成这样子

int Java_com_example_day01_MainActivity_add(int i, int j){
	return i + j;
}

都是用下划线隔开的,请注意,然后就是参数列表,这里有两个参数是固定的,必须要写,如下:

int Java_com_example_day01_MainActivity_add(JNIEnv* e, jobject thiz, int i,
		int j) {
	return i + j;
}

可以看到这里多了两个参数,一个是JNIEnv*和jobject

JNIEnv*:这里做一下解释,我们的java代码是运行在虚拟机里面的,所以利用JNI在实现功能的同时,需要用到虚拟机环境的指针,也就是需要环境的支持,并且这是一个指针,指向运行环境

jobject是调用方法的时候的对象,这里也就是我们的MainActivity对象

做完了这一切我们就实现了add方法,当然了别忘了添加一些必要的头文件,完整的c代码是

#include <stdio.h>
#include <stdlib.h>
#include <jni.h>

jint Java_com_example_day01_MainActivity_add(JNIEnv* e, jobject thiz, int i,
		int j) {
	return i + j;
}

这里有一个jni.h头文件是使用jni功能所必需的,还有这里的返回值jint,其实就是谷歌为了让代码更有可读性预定义的一些名字,这里我点进去

可以看到就是一个int,这里也做一个解释,为啥要这样子,直接适应int不是挺好的.

其实这里你用int和jint都是没有什么区别的,但是我们想一下,在c中是没有对象的概念的,加入你java里面传入的是一个数组,或者传入一个对象,在c中都是一个指针而已,指向了你传入的对象,在c中都是void*表示,这时候你写的代码过几天去看,你还知道当初的void*这里的参数,到底是数组呢还是对象,还是字符串呢?你不知道了,你只能去调用的地方去瞧瞧,很明显这里降低了代码的可阅读性,所以谷歌工程师为我们预定义了很多的关键字来表示不同的对象

typedef void*           jobject;
typedef jobject         jclass;
typedef jobject         jstring;
typedef jobject         jarray;
typedef jarray          jobjectArray;
typedef jarray          jbooleanArray;
typedef jarray          jbyteArray;
typedef jarray          jcharArray;
typedef jarray          jshortArray;
typedef jarray          jintArray;
typedef jarray          jlongArray;
typedef jarray          jfloatArray;
typedef jarray          jdoubleArray;
typedef jobject         jthrowable;
typedef jobject         jweak;

可以看到这些的本质的是void*,但是我们可以用jobject和jarray这些来说明参数的含义,这样子就可阅读性很强

最后我们写的c/c++代码最后都会被打包成.so文件,所以我们使用的时候需要在Avtivity里面先加载类库

public class MainActivity extends Activity {

	static {
		System.loadLibrary("hello");
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		int result = add(3,5);
		System.out.println("result == " + result);
	}

	private native int add(int i,int j);
}

我们的.so文件要打包成功还需要有一个android.mk,直接从ndk自带的例子里面复制过来就行了

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello
LOCAL_SRC_FILES := hello.c

include $(BUILD_SHARED_LIBRARY)

里面就是这几句话,只要修改hello所在的地方就可以了,你可以把上面的两个hello改成其他的任意名字

利用ndk里面的ndk-build.cmd进行打包我们的c代码

当然了用eclipse关联了ndk之后,直接运行项目就可以了,打包的工作交给eclipse

时间: 2024-10-10 09:15:13

Android JNI入门的相关文章

Android JNI入门教程

Android JNI入门教程 最近公司里有项目要用到jni,就研究并整理了下,现在分享给大家. 下载最新的ndk,新建环境变量NDK_ROOT,值是ndk的根目录,并把它加到PATH.这样做是因为我们要用到ndk的ndk-build.cmd,而且像eclipse要根据NDK_ROOT识别ndk. 现在新建一个最简单的安卓工程NewJNI,修改类MainActivity: public class MainActivity extends Activity { public native voi

android JNI入门-学习笔记

JNI入门-学习笔记 可执行文件 Windows - *.exe | linux - *.elf c函数库文件 Windows - *.dll | linux - *.so 批处理文件 Windows - *.bat | linux - *.sh 工具 NDK -- native developer kits Cygwin -- Linux系统模拟器 安装过程要点: --安装时可以联网安装也可以通过本地文件安装(如果有本地文件) --Select Packages:没必要全部安装,安装Devel

Android JNI 入门

Android JNI (Java Native Interface)就是为了实现java 与其他语言相互调用的语言.当然在Android就是为了跟C,C++的调用.在Linux ,Mac中Java最后调用的就是.so的文件,在Window中就是.dll文件. 那么Java到C怎么对应起来?调用Java的哪个方法就是C中的哪个方法呢?通过在Java类中声明native的方法就开始了. 新建一个Android工程HelloNDK.新建一个类GetString public class GetStr

Android JNI入门第二篇——Java参数类型与本地参数类型对照

前面一篇通过简单的例子介绍了android中JNI的使用.这一篇从基础上了解一些Java参数类型与本地参数类型区别. 1)        java中的返回值void和JNI中的void是完全对应的哦!(仅仅一个而已). 2)        java中的基本数据类型(byte ,short ,int,long,float,double ,boolean,char-8种)在JNI中对应的数据类型只要在前面加上j就对应了(jbyte ,jshort ,jint,jlong,jfloat,jdouble

Android JNI入门第一篇——HelloJni

android支持使用NDK开发C程序,关于配置NDK环境问题应该不用再赘述了,这个网上有很多,这里通过一篇实例来讲述简单的JNI开发,大家可以参考这篇文章(Get Your Eclipse-Integrated NDK On!)搭建Eclipse编译C语言为so文件的开发环境. native方法实现步骤如下: 1.在Java中声明native()方法,然后编译(javac): 2.用javah产生一个.h文件: 3.编写包含.h文件的c文件 4.编译c文件 5.使用编译成功的so文件. 第一步

Android jni 编程入门

本文将介绍如何使用eclipse和ndk-build来编写一个基于Android4.4版本的包含有.so动态库的安卓程序. 前提是已经安装和配置好了诸如SDK,NDK等编译环境.下面开始编程! 1 程序逻辑 我们要编写的程序包含两部分:java部分--负责界面和调用JNI native函数:JNI native 部分--负责native函数的具体实现(本文使用C语言). native 函数伪代码如下: ? 1 2 3 4 5 6 7 8 /* funtion: 传入两个整形变量,计算他们之和 r

Android JNI配置及入门

JNI是一种可以在Java中调用C/C++代码的技术,也就是说可以在Android上使用C/C++来开发.但是并不能用纯C/C++来开发Android应用,因为这些C/C++代码要通过Java定义的接口来调用. 我试验Android上的JNI时使用的是NDK-R10,不需要Cygin,使用版本较低的NDK时请另寻教程. NDK的安装与ADT中如何配置NDK 可以到Android Developer官网上去下载最新的NDK工具包,下载下来之后解压到随便一个好找的目录,比如我们解压到了C:\,这样N

Android jni本地编程入门

在某些情况下,java编程已经不能满足我们的需要,比如一个复杂的算法处理,这时候就需要用到jni技术: jni : java native interface jni 其实就是java和c/cpp之间进行通信的一个接口规范,java可以调用c/cpp里面的函数,同样,c/cpp也可以调用java类的方法: jni开发工具ndk的安装:在最新的ndk版本中,安装ndk很简单,只需要装ndk的路径配置到系统环境变量中即可:在编译的时候,进入工程根目录:执行命令  ndk-build  即可完成编译:

Android jni开发有哪些常见的错误

我们在Android jni开发中,特别是对于刚入门学习Android jni开发的同学来说,往往会遇到很多错误,这里总结了我们经常遇见的错误.这些错误,你是否经常遇到. 错误1:java.lang.UnsatisfiedLinkError: Native method not found: 本地方法没有找到 1.本地函数名写错 2.忘记加载.so文件 没有调用System.loadlibrary 错误2:findLibrary returned null 1.System.loadLibrar