文档章节

JNI 入门

 草帽行者
发布于 2017/04/28 10:42
字数 708
阅读 16
收藏 0

JNI 入门

[TOC]

环境

anddroid studio 2.2

安装: NDK,CMake,LLDB

Android Studio

准备工作

  1. 配置ndk目录

local.properties

```
# header note.
#Mon Mar 20 15:50:38 CST 2017
ndk.dir=/Users/cj/Library/Android/sdk/ndk-bundle
```
  1. 兼容老的ndk

gradle.properties

```
# org.gradle.parallel=true
# 兼容老的ndk
android.useDeprecatedNdk="true"
```

使用步骤

  1. 使用java文件创建一个native方法,用于调用c代码对应的方法:Jni.java

    	public class Jni {
    
    	public native String sayHello();
    
    	}
    
  2. 创建存放c/c++文件的目录jni

main/jni

  1. 创建.c文件:hello.c

main/jni/hello.c

  1. 添加头文件:hello.c

    	#include <stdio.h>
    	#include <stdlib.h>
    	#include <jni.h>
    
  2. 编写供java调用的方法: hello.c

方法名:已java文件为标准 --> Java_包名_类名_方法名

```
/**
* 方法名命名规则:Java_包名(点换成下划线)_类名_方法名
* jstring:返回值
* JNIEnv:相当于类库,里面有很多方法
* jobject:  谁调用这个方法就是谁的实例
*/
jstring Java_com_myc_jni_Jni_sayHello(JNIEnv *env, jobject instance) {
	char *text = "Hello Jni";
	return (*env)->NewStringUTF(env, text);
}
```

or

```
JNIEXPORT jstring JNICALL
Java_com_myc_jni_Jni_sayHello(JNIEnv *env, jobject instance) {
    char *txt = "Hello Jni";
    return (*env)->NewStringUTF(env, txt);
}
```
  1. 指定编译不同的CPU

app/build.gradle

```
defaultConfig {
    ...

    ndk{
        moduleName "Hello"  // 生产的so文件名:lib+moduleName+.so
        abiFilters "armeabi","armeabi-v7a","x86"    // cpu的类型
    }
}
```
  1. 加载动态链接库:Jni.java

链接库的名字为build.gradle配置的moduleName

```
public class Jni {
	{
    	System.loadLibrary("Hello");    
	}

	...
}
```
  1. 使用_java调c

    • 本项目中使用: 通过new Jni(),然后调用其中的方法 导出:Rebuild project

      app --> build --> intermediates --> ndk --> debug --> lib

    • 外部使用

      1. 将对应的cpu的so文件放入到libs目录中

      2. 将so文件导入项目,修改build.gradle,添加如下配置信息

      导入成功:切换到android视图下,我们可以看到app目录下自动生成了一个jniLibs目录,打开该目录,可以看到我们导入的so

        ```
        android {
        	...
      
        	sourceSets {
        		main {
            		jniLibs.srcDirs = ['libs']
        	}
        }
        ```
      
      1. 在当前项目中(src/main/java)创建一个新包,报名为so库编译native时使用的包名,然后再在该包下新建.java文件,eg:JniOther.java

        	public class JniOther {
        
        		/**
        		* 加载动态链接库
        		*/
        		{
        			System.loadLibrary("Hello");    // 名字:build.gradle文件中的moduleName
        		}
        
        		/**
        		* so 提供的方法
        		* @return
        		*/
        		public native String sayHello();
        
        	}
        
      2. 使用: new JniOther() 调用相关的native方法

  2. 使用_c调java

    1. 准备工作:

      • java文件中存在方法addJava(int a, int b)
      	public int addJava(int a, int b) {
          return a + b;
      }
      
      • 准备一个java调c的方法:cAddJava()
      	public native int cAddJava();
      
      
    2. 在c文件中实现方法:cAddJava() a. 得到类字节码

      b. 得到方法,最后一个参数是方法签名(见博客:方法签名)

      c. 实例化该类

      d. 调用方法

      	JNIEXPORT jint JNICALL
      	Java_com_myc_jni_Jni_cAddJava(JNIEnv *env, jobject instance) {
      	    // 1. 得到字节码
      	    jclass jclass1 = (*env)->FindClass(env, "com/myc/jni/Jni");
      	    // 2. 得到方法,最后一个参数是方法签名  int addJava(int a, int b)
      	    jmethodID methodID = (*env)->GetMethodID(env, jclass1, "addJava", "(II)I");
      	    // 3. 实例化该类
      	    jobject jobj = (*env)->AllocObject(env, jclass1);
      
      	    // 4. 调用方法
      	    return (*env)->CallIntMethod(env,jobj,methodID,13,12);
      	}
      
    3. 测试

      	int cAdd = jni.cAddJava();
      System.out.println("---c调用java:" + cAdd);
      
      // 结果
      I/System.out: ---c调用java:25
      

© 著作权归作者所有

共有 人打赏支持
粉丝 6
博文 35
码字总数 29999
作品 0
广州
程序员
Android NDK 原理

本文介绍Android NDK 原理, 熟悉此教程, 需要有JNI的基础, 以及Android 应用程序的入门知识(环境搭建, 工程运行等), 可以查看本站的其它文章. 本文关注Android NDK的原理知识. 关于JNI的基本...

晨曦之光
2012/03/09
363
0
Android NDK 原理

本文介绍Android NDK 原理, 熟悉此教程, 需要有JNI的基础, 以及Android 应用程序的入门知识(环境搭建, 工程运行等), 可以查看本站的其它文章. 本文关注Android NDK的原理知识. 关于JNI的基本...

晨曦之光
2012/03/07
449
0
用Android NDK编译FFmpeg

原文转自:http://abitno.me/compile-ffmpeg-android-ndk Android内置的编解码器实在太少,于是我们需要FFmpeg。Android提供了NDK,为我们使用FFmpeg这种C语言代码提供了方便。 不过为了用N...

华宰
2011/09/08
12.6K
1
Android NDK 入门

原文转自:http://abitno.me/a-simple-tutorial-to-android-ndk 我理解的NDK是允许你把程序的一部分代码用C或C++来实现,通过JNI与Java代码交互。不要想整个程序都用C/C++完成,Android是不允...

华宰
2011/09/08
2.3K
1
【jni 编程】—— NDK环境搭建

在《站在巨人的肩膀上,谈app的创新性》一文中 http://my.oschina.net/liusicong/blog/311971,我提到过构建app技术壁垒的必要性。在构建技术壁垒时,我们往往需要调用许多库函数,例如:图像...

刘小米
2014/09/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

打开eclipse出现an error has occurred see the log file

解决方法: 1,打开eclipse安装目录下的eclipse.ini文件; 2,打开的文本文件最后添加一行 --add-modules=ALL-SYSTEM 3,保存重新打开Eclipse。...

任梁荣
昨天
3
0
搞定Northwind示例数据库,无论哪个版本的SQLServer都受用

Northwind数据库 从这里可以找到突破口: http://social.msdn.microsoft.com/Forums/zh-CN/Vsexpressvb/thread/8490a1c6-9018-40c9-aafb-df9f79d29cde 下面是MSDN: http://msdn2.microsoft......

QQZZFT
昨天
1
0
mysql主从同步,安装配置操作

准备 两台mysql服务,我这里准备了如下: 主库:192.168.176.128 从库:192.168.176.131 如何在Linux上安装mysql服务,请看https://blog.csdn.net/qq_18860653/article/details/80250499 操作...

小致dad
昨天
3
0
一个手机装天下,走遍中国都不怕!

导读 “1200元(人民币,下同),微信支付,可以,你扫我。”来自西非马里共和国的展商Albert拿着手机,和一位买走他手鼓的中国游客用简单的汉语交流着。 近日,“第十四届中俄蒙经贸洽谈暨商品...

问题终结者
昨天
2
0
Redis的“死键”问题

大规模的数据库存储系统中,数据的生命周期管理是很有必要的;从业务角度发现过期数据,数据归档和数据碎片整理等。以MySQL为例,1个运行很久的TB级MySQL实例中,极有可能数百GB的数据,对业...

IT--小哥
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部