首先我们要明确几个概念,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?

    1. 代码的保护,由于apk的java层代码很容易被反编译,而C/C++库反汇难度较大。
    2. 在NDK中调用第三方C/C++库,因为大部分的开源库都是用C/C++代码编写的。
    3. 便于移植,用C/C++写的库可以方便在其他的嵌入式平台上再次使用。
 

  通俗来说,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方法基本没区别。

  1. static {
  2. System.loadLibrary("JniTest");
  3. }
  4.  
  5. public native String getStringFromNative();

  4,生成头文件。在android studio 的命令行界面中,进入/app/src/main/java目录下,执行命令:

  1. javah -d ../jni com.example.shengchanglu.test.MainActivity

  这样就在src/main/目录中新增了jni目录,以及jni/com_example_shengchanglu_test_MainActivity.h头文件。

  com_example_shengchanglu_test_MainActivity.h头文件内容如下:

  1. /* DO NOT EDIT THIS FILE - it is machine generated */
  2. #include <jni.h>
  3. /* Header for class com_example_shengchanglu_test_MainActivity */
  4.  
  5. #ifndef _Included_com_example_shengchanglu_test_MainActivity
  6. #define _Included_com_example_shengchanglu_test_MainActivity
  7. #ifdef __cplusplus
  8. extern "C" {
  9. #endif
  10. /*
  11. * Class: com_example_shengchanglu_test_MainActivity
  12. * Method: getStringFromNative
  13. * Signature: ()Ljava/lang/String;
  14. */
  15. JNIEXPORT jstring JNICALL Java_com_example_shengchanglu_test_MainActivity_getStringFromNative
  16. (JNIEnv *, jobject);
  17.  
  18. #ifdef __cplusplus
  19. }
  20. #endif
  21. #endif

  看返回值jstring对应于java中得String。

  5,在jni目录中新增main.c文件,去实现com_example_shengchanglu_test_MainActivity.h头文件中定义的方法。

  1. //
  2. // Created by shengchang lu on 15/9/2.
  3. //
  4.  
  5. /* DO NOT EDIT THIS FILE - it is machine generated */
  6. #include <jni.h>
  7. #include <android/log.h>
  8.  
  9. #ifndef LOG_TAG
  10. #define LOG_TAG "ANDROID_LAB"
  11. #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
  12. #endif
  13.  
  14. #ifndef _Included_com_example_shengchanglu_test_MainActivity
  15. #define _Included_com_example_shengchanglu_test_MainActivity
  16. #ifdef __cplusplus
  17. extern "C" {
  18. #endif
  19. /*
  20. * Class: com_example_shengchanglu_test_MainActivity
  21. * Method: getStringFromNative
  22. * Signature: ()Ljava/lang/String;
  23. */
  24. JNIEXPORT jstring JNICALL Java_com_example_shengchanglu_test_MainActivity_getStringFromNative(JNIEnv * env , jobject j)
  25. {
  26. LOGE("log string from ndk.");
  27. return (*env)->NewStringUTF(env,"Hello From JNI!");
  28. }
  29.  
  30. #ifdef __cplusplus
  31. }
  32. #endif
  33. #endif

  6,Android中调用native方法。

  7,编译,运行。在app/build/intermediates/下出现ndk目录,生成了动态库so文件和mk文件。

  上面讲的只是ndk开发最基本的。Java不仅可以调用jni方法,jni也可以调用Java中属性(静态和非静态),方法(静态和非静态)。

  1. void AppAction::setUndoRedoState(bool undo, bool redo) {
  2. JNIEnv* jniEnv = EnvManager::shareInstance()->getEnv();
  3. if (jniEnv == NULL) {
  4. return;
  5. }
  6. jclass jclz = NULL;
  7. jclz = jniEnv->FindClass(
  8. "com/fotoable/fotoproedit/activity/ProEditLightPenActivity");
  9. if (jniEnv->ExceptionCheck() == JNI_TRUE) {
  10. jniEnv->ExceptionClear();
  11. jniEnv->DeleteLocalRef(jclz);
  12. return;
  13. }
  14. jmethodID checkUndoRedoState = jniEnv->GetStaticMethodID(jclz,
  15. "checkUndoRedoState", "(ZZ)V");
  16. if (checkUndoRedoState == NULL) {
  17. jniEnv->DeleteLocalRef(jclz);
  18. return;
  19. }
  20. jniEnv->CallStaticVoidMethod(jclz, checkUndoRedoState,
  21. undo,redo);
  22. if (jniEnv->ExceptionCheck() == JNI_TRUE) {
  23. jniEnv->ExceptionClear();
  24. }
  25.  
  26. jniEnv->DeleteLocalRef(jclz);
  27. }

  根据上面的jni代码,我们可以反推出在当前项目中有且只有一个类中有这个方法。

   类名:com.fotoable.fotoproedit.activity.ProEditLightPenActivity

   方法:public void static checkUndoRedoState(boolean b1,boolean b1);

  调用方法完毕后,指针变量应该释放,要不然会引起内存泄露,程序崩溃。难点是异常捕获,ExceptionCheck只能捕获上一行代码引发的异常,且不能向Android层抛出,所以必须多加小心。

  关于保存jni环境: EnvManager::shareInstance():

  1. /*
  2. * UtilManager.h
  3. *
  4. * Created on: 2013-12-31
  5. * Author: Administrator
  6. */
  7.  
  8. #ifndef UTILMANAGER_H_
  9. #define UTILMANAGER_H_
  10. #include <jni.h>
  11. class EnvManager {
  12. public:
  13. EnvManager();
  14. virtual ~EnvManager();
  15.  
  16. static EnvManager* shareInstance();
  17. static void destroy();
  18.  
  19. JNIEnv* getEnv();
  20.  
  21. void setEnv(JNIEnv* jniEnv);
  22.  
  23. private:
  24. JNIEnv* env;
  25. };
  26.  
  27. #endif /* UTILMANAGER_H_ */
  1. /*
  2. * UtilManager.cpp
  3. *
  4. * Created on: 2013-12-31
  5. * Author: Administrator
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include "EnvManager.h"
  10.  
  11. static EnvManager * sEnvManager = NULL;
  12.  
  13. EnvManager * EnvManager::shareInstance()
  14. {
  15. if (!sEnvManager) {
  16. sEnvManager = new EnvManager();
  17. }
  18. return sEnvManager;
  19. }
  20.  
  21. void EnvManager::destroy()
  22. {
  23. delete sEnvManager;
  24. sEnvManager = NULL;
  25. }
  26.  
  27. JNIEnv* EnvManager::getEnv(){
  28. return env;
  29. }
  30.  
  31. void EnvManager::setEnv(JNIEnv* jniEnv){
  32. env = jniEnv;
  33. }
  34.  
  35. EnvManager::EnvManager() {
  36. env = NULL;
  37. }
  38.  
  39. EnvManager::~EnvManager() {
  40. delete env;
  41. }

后续:跨平台开发方面。譬如在图片处理方面,Android 和 iOS底层可以使用cocos2dx ,Android 通过 jni 与上层界面交互,iOS可以调用Cocos2dx,这样底层的代码是一样的,iOS和Android只用各写自己的界面就行。开发速度就比较快。

      如果底层有内存泄露引起崩溃,整个引用也会崩溃,不会抛出异常。所以应该尽量少做底层和Android层的来回频繁切换,避免崩溃。

Android studio jni的更多相关文章

  1. Android Studio JNI开发入门教程

    Android Studio JNI开发入门教程 2016-08-29 14:38 3269人阅读 评论(0) 收藏 举报  分类: JNI(3)    目录(?)[+]   概述 在Andorid ...

  2. Android Studio JNI 开发简单案例

    转载:http://www.androidchina.net/5744.html 进程保活,热修复,硬件接入等等都需要底层的支持,而底层代码是 C .C++ 写的,那么在 Android 中怎么调用底 ...

  3. Android Studio Jni 环境搭建

    第一步:NDK环境搭建,点击下图红色框区域查看NDK下载和环境配置 安照正常情况是很慢的或者无法下载成功的,这个时候可以去下载NDK压缩包进行解压.下面给出两个下载地址 (1)官网:http://we ...

  4. Android Studio JNI/NDK 编程(二) Windows 下环境搭建 demo 开发

    环境 windows 8  (注:其实 Linux 开发可能更方便) Android Studio 2.1; 一 . 下载 安装android-ndk开发包 地址:链接:http://pan.baid ...

  5. 实现Android Studio JNI开发C/C++使用__android_log_print输出Log

    相信很多人在刚开始学习Android JNI编程的时候,需要输出Log,在百度Google搜索的时候都是说需要在Android.mk中加入LOCAL_LDLIBS+= -L$(SYSROOT)/usr ...

  6. android studio JNI使用

    Step: 1. 添加native接口注意写好native接口和System.loadLibrary()即可了,并无特别之处. Step: 2.执行Build->Make Project 生成了 ...

  7. android studio jni调用入门

    一.开发环境配置: 1.Android Studio 2.3.3 2.android-ndk-r14b-windows-x86_64 二.创建项目 1.新建android项目 2.新建文件 3.编译生 ...

  8. 【OpenCV for Android】Android Studio JNI和NDK配置及采坑记录

    在配置好Android studio的OpenCV环境后,我们就可以通过Java代码调用OpenCV的API了,但是在通常情况下,用Java代码编写图像处理算法的运行效率是没有C++代码高的,在应用层 ...

  9. Android Studio JNI体验

    近期项目中须要调用c/c++的实现,Android是支持JNI的.所以体验了一下JNI的全过程 1. 前期环境准备 (1) 下载NDK,网址是https://developer.android.com ...

随机推荐

  1. web测试项目总结

    一.输入框 1.字符型输入框: (1)字符型输入框:英文全角.英文半角.数字.空或者空格.特殊字符“~!@#¥%……&*?[]{}”特别要注意单引号和&符号.禁止直接输入特殊字符时,使 ...

  2. UVA1714 Keyboarding(bfs)

    UVA1714 Keyboarding bfs 坑点很多的一题(由于一本通的辣鸡翻译会错题意*n). 1.多组数据 2.如果某方向上没有不同字符光标不会动 我们每次预处理出每个点向四个方向下次到达的点 ...

  3. 20145105 《Java程序设计》第7周学习总结

    20145105 <Java程序设计>第7周学习总结 教材学习内容总结 第十三章 时间与日期 一.认识时间与日期 (一)时间的度量 格林威治标准时间 世界时 国际原子时 世界协调时 Uni ...

  4. 20145321 《网络对抗技术》 Web安全基础实践

    20145321<网络对抗技术> Web安全基础实践 基础问题回答 1.SQL注入攻击原理,如何防御? SQL注入就是通过把SQL命令插入到“Web表单递交”或“输入域名”或“页面请求”的 ...

  5. VC++ 删除一个文件目录下的所有文件以及目录

    BOOL DoRemoveDirectory(CString chrDirName); BOOL ReleaseDirectory(CString chrDirName) { BOOL bRemove ...

  6. SpringCloud请求响应数据转换(二)

    上篇文章记录了从后端接口返回数据经过切面和消息转换器处理后返回给前端的过程.接下来,记录从请求发出后到后端接口调用过的过程. web请求处理流程 源码分析 ApplicationFilterChain ...

  7. 在Visual C#中使用XML指南之读取XML

    网站:http://www.yesky.com/155/1915155all.shtml#p1915155  

  8. Linxu内核版本号后面多出字符串或者+号【学习笔记】

    作者:庄泽彬 之前一直没有留意到但是最近在编译内核的时候版本号竟然多出了个加号+号或字符串, 后面终于找到原因了,原来config如果设置了CONFIG_LOCALVERSION_AUTO=y,内核的 ...

  9. Python 逗号的几种作用

    转自http://blog.csdn.net/liuzx32/article/details/7831247 最近研究Python  遇到个逗号的问题 一直没弄明白 今天总算搞清楚了 1.逗号在参数传 ...

  10. 论文笔记之:Human-level control through deep reinforcement learning

    Human-level control through deep reinforcement learning Nature 2015 Google DeepMind Abstract RL 理论 在 ...