Android studio jni
首先我们要明确几个概念,jni,ndk,共享库(.so)。
jni是java native interface的缩写,java 本地接口。它提供了若干的API实现了Java和其他语言的通信(主要是C/C++)。从Java1.1开始,jni标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。
ndk:Android NDK 是在SDK前面又加上了“原生”二字,即Native Development Kit,因此又被Google称为“NDK”。
.so:共享函数库,在可执行程序启动的时候加载,所有程序重新运行时都可自动加载共享函数库中的函数。
为何要使用ndk?
通俗来说,jni提供一套标准,包括定义了一些数据类型,引用类型,对应于Java中的数据类型,引用类型。还有一些转换函数,这些都定义在jni.h中。
例如,java传入的String参数,在c文件中被jni转换为jstring的数据类型,在c文件中声明char* test,然后test = (char*)(*env)->GetStringUTFChars(env, jstring, NULL);注意:test使用完后,需要释放指针变量:(*env)->ReleaseStringUTFChars(env, jstring, test);将char* test转换为jstring 用 (*env)->NewStringUTF(env,const char* );(const 指啥意思?)
Android 函数库是用c/c++写的,框架层不能直接调用它,而是通过jni调用的。我们也可以自己用jni调用native层。
实战。
1,配置NDK环境,需要下载NDK开发包并配置。

2,在app build.gradle里面配置ndk属性。

3,静态加载动态库,编写naive方法,和普通java方法基本没区别。
static {
System.loadLibrary("JniTest");
}
public native String getStringFromNative();
4,生成头文件。在android studio 的命令行界面中,进入/app/src/main/java目录下,执行命令:
javah -d ../jni com.example.shengchanglu.test.MainActivity
这样就在src/main/目录中新增了jni目录,以及jni/com_example_shengchanglu_test_MainActivity.h头文件。

com_example_shengchanglu_test_MainActivity.h头文件内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_shengchanglu_test_MainActivity */ #ifndef _Included_com_example_shengchanglu_test_MainActivity
#define _Included_com_example_shengchanglu_test_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_shengchanglu_test_MainActivity
* Method: getStringFromNative
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_shengchanglu_test_MainActivity_getStringFromNative
(JNIEnv *, jobject); #ifdef __cplusplus
}
#endif
#endif
看返回值jstring对应于java中得String。
5,在jni目录中新增main.c文件,去实现com_example_shengchanglu_test_MainActivity.h头文件中定义的方法。
//
// Created by shengchang lu on 15/9/2.
// /* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <android/log.h> #ifndef LOG_TAG
#define LOG_TAG "ANDROID_LAB"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#endif #ifndef _Included_com_example_shengchanglu_test_MainActivity
#define _Included_com_example_shengchanglu_test_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_shengchanglu_test_MainActivity
* Method: getStringFromNative
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_shengchanglu_test_MainActivity_getStringFromNative(JNIEnv * env , jobject j)
{
LOGE("log string from ndk.");
return (*env)->NewStringUTF(env,"Hello From JNI!");
} #ifdef __cplusplus
}
#endif
#endif
6,Android中调用native方法。

7,编译,运行。在app/build/intermediates/下出现ndk目录,生成了动态库so文件和mk文件。
上面讲的只是ndk开发最基本的。Java不仅可以调用jni方法,jni也可以调用Java中属性(静态和非静态),方法(静态和非静态)。
void AppAction::setUndoRedoState(bool undo, bool redo) {
JNIEnv* jniEnv = EnvManager::shareInstance()->getEnv();
if (jniEnv == NULL) {
return;
}
jclass jclz = NULL;
jclz = jniEnv->FindClass(
"com/fotoable/fotoproedit/activity/ProEditLightPenActivity");
if (jniEnv->ExceptionCheck() == JNI_TRUE) {
jniEnv->ExceptionClear();
jniEnv->DeleteLocalRef(jclz);
return;
}
jmethodID checkUndoRedoState = jniEnv->GetStaticMethodID(jclz,
"checkUndoRedoState", "(ZZ)V");
if (checkUndoRedoState == NULL) {
jniEnv->DeleteLocalRef(jclz);
return;
}
jniEnv->CallStaticVoidMethod(jclz, checkUndoRedoState,
undo,redo);
if (jniEnv->ExceptionCheck() == JNI_TRUE) {
jniEnv->ExceptionClear();
}
jniEnv->DeleteLocalRef(jclz);
}
根据上面的jni代码,我们可以反推出在当前项目中有且只有一个类中有这个方法。
类名:com.fotoable.fotoproedit.activity.ProEditLightPenActivity
方法:public void static checkUndoRedoState(boolean b1,boolean b1);
调用方法完毕后,指针变量应该释放,要不然会引起内存泄露,程序崩溃。难点是异常捕获,ExceptionCheck只能捕获上一行代码引发的异常,且不能向Android层抛出,所以必须多加小心。
关于保存jni环境: EnvManager::shareInstance():
/*
* UtilManager.h
*
* Created on: 2013-12-31
* Author: Administrator
*/ #ifndef UTILMANAGER_H_
#define UTILMANAGER_H_
#include <jni.h>
class EnvManager {
public:
EnvManager();
virtual ~EnvManager(); static EnvManager* shareInstance();
static void destroy(); JNIEnv* getEnv(); void setEnv(JNIEnv* jniEnv); private:
JNIEnv* env;
}; #endif /* UTILMANAGER_H_ */
/*
* UtilManager.cpp
*
* Created on: 2013-12-31
* Author: Administrator
*/
#include <stdio.h>
#include <stdlib.h>
#include "EnvManager.h" static EnvManager * sEnvManager = NULL; EnvManager * EnvManager::shareInstance()
{
if (!sEnvManager) {
sEnvManager = new EnvManager();
}
return sEnvManager;
} void EnvManager::destroy()
{
delete sEnvManager;
sEnvManager = NULL;
} JNIEnv* EnvManager::getEnv(){
return env;
} void EnvManager::setEnv(JNIEnv* jniEnv){
env = jniEnv;
} EnvManager::EnvManager() {
env = NULL;
} EnvManager::~EnvManager() {
delete env;
}
后续:跨平台开发方面。譬如在图片处理方面,Android 和 iOS底层可以使用cocos2dx ,Android 通过 jni 与上层界面交互,iOS可以调用Cocos2dx,这样底层的代码是一样的,iOS和Android只用各写自己的界面就行。开发速度就比较快。
如果底层有内存泄露引起崩溃,整个引用也会崩溃,不会抛出异常。所以应该尽量少做底层和Android层的来回频繁切换,避免崩溃。
Android studio jni的更多相关文章
- Android Studio JNI开发入门教程
Android Studio JNI开发入门教程 2016-08-29 14:38 3269人阅读 评论(0) 收藏 举报 分类: JNI(3) 目录(?)[+] 概述 在Andorid ...
- Android Studio JNI 开发简单案例
转载:http://www.androidchina.net/5744.html 进程保活,热修复,硬件接入等等都需要底层的支持,而底层代码是 C .C++ 写的,那么在 Android 中怎么调用底 ...
- Android Studio Jni 环境搭建
第一步:NDK环境搭建,点击下图红色框区域查看NDK下载和环境配置 安照正常情况是很慢的或者无法下载成功的,这个时候可以去下载NDK压缩包进行解压.下面给出两个下载地址 (1)官网:http://we ...
- Android Studio JNI/NDK 编程(二) Windows 下环境搭建 demo 开发
环境 windows 8 (注:其实 Linux 开发可能更方便) Android Studio 2.1; 一 . 下载 安装android-ndk开发包 地址:链接:http://pan.baid ...
- 实现Android Studio JNI开发C/C++使用__android_log_print输出Log
相信很多人在刚开始学习Android JNI编程的时候,需要输出Log,在百度Google搜索的时候都是说需要在Android.mk中加入LOCAL_LDLIBS+= -L$(SYSROOT)/usr ...
- android studio JNI使用
Step: 1. 添加native接口注意写好native接口和System.loadLibrary()即可了,并无特别之处. Step: 2.执行Build->Make Project 生成了 ...
- android studio jni调用入门
一.开发环境配置: 1.Android Studio 2.3.3 2.android-ndk-r14b-windows-x86_64 二.创建项目 1.新建android项目 2.新建文件 3.编译生 ...
- 【OpenCV for Android】Android Studio JNI和NDK配置及采坑记录
在配置好Android studio的OpenCV环境后,我们就可以通过Java代码调用OpenCV的API了,但是在通常情况下,用Java代码编写图像处理算法的运行效率是没有C++代码高的,在应用层 ...
- Android Studio JNI体验
近期项目中须要调用c/c++的实现,Android是支持JNI的.所以体验了一下JNI的全过程 1. 前期环境准备 (1) 下载NDK,网址是https://developer.android.com ...
随机推荐
- mysql 触发器 trigger用法 four
实验4 触发器 (1)实验目的 掌握数据库触发器的设计和使用方法 (2)实验内容和要求 定义BEFORE触发器和AFTER触发器.能够理解不同类型触发器的作用和执行原理,验证触发器的有效性. (3)实 ...
- SNMP学习笔记之SNMP介绍,OID及MIB库
1.1. SNMP概览 SNMP的基本知识介绍简单网络管理协议(SNMP-Simple Network Management Protocol)是一个与网络设备交互的简单方法.该规范是由IETF ...
- P3538 [POI2012]OKR-A Horrible Poem
P3538 [POI2012]OKR-A Horrible Poem hash+线性筛 题解 <----这篇写的不错(其实是我懒得码字了qwq) UVA10298 Power Strings 的 ...
- 05: python中的函数
1.1 python 函数 1.函数作用 定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 特性: 减少重复代码 使程序变的可扩展 使程序变得 ...
- Python3.5 MySQL 数据库连接
Python3.5 MySQL 数据库连接 在本文中介绍 Python3 使用PyMySQL连接数据库,并实现简单的增删改查 为什么使用PyMySQL? PyMySQL是在Pyhton3.x版本中用 ...
- cogs 362. [CEOI2004]锯木厂选址
★★★ 输入文件:two.in 输出文件:two.out 简单对比 时间限制:0.1 s 内存限制:32 MB 从山顶上到山底下沿着一条直线种植了n棵老树.当地的政府决定把他们砍下来. ...
- JavaScript:正则表达式 分组
在现在的我看来,带小挂号的就是分组,嗯. 代码: var reg=/(abc)/; var str="abcdabcdeabcdef"; console.dir(reg.exec( ...
- Visio 画图去掉页边距(图形四周的空白区域)的解决办法
步骤如下: 1.打开Visio对象后在[文件]菜单[选项]菜单项上单击,然后单击[自定义功能区]. 2.在[自定义功能区]的主选项卡中找到[开发工具]复选框,打上勾,单击确定. 3.在Visio对象的 ...
- C++课程上 有关“指针” 的小结
上完了C++的第二节课以后,觉得应该对这个内容进行一个小结,巩固知识点,并对我的心情进行了一个侧面烘托... 开始上课的老师: 正在上课的我: 上去敲代码的我: 过程是这样的: 下来的我: 非常的尴尬 ...
- NOI 8785 装箱问题(0-1背包)
http://noi.openjudge.cn/ch0206/8785/ 描述 有一个箱子容量为V(正整数,0<=v<=20000),同时有n个物品(0< n<n<=30 ...