为什么要研究jni?
首先,Java语言提供的类库无法满足要求,且在数学运算,实时渲染的游戏上,音视频处理等方面上与C/C++相比效率稍低。
然后,Java语言无法直接操作硬件,C/C++代码不仅能操作硬件而且还能发挥硬件的最佳性能。
接着,使用Java调用本地的C/C++代码所写的库,省去了重复开发的麻烦,并且可以利用很多开源的库提高程序效率。
JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信。
JNI技术分为两部分:Java端和C语言端,实现步骤如下:
首先,Java程序员在Java端声明一些native方法,并将这些方法以C语言头文件的方式提供给C程序员。(生成头文件)
然后,C程序员使用C语言,来实现Java程序员提供的头文件中定义的函数。
接着,C程序员将函数打包成一个库文件,并将库文件交给Java程序员。
最后,Java程序员在Java程序中导入库文件,然后调用native方法。System.loadLibrary("media_jni");
详细步骤如下:
-------------------------------------------------------------------------------eclipse工程下:-------------------------------------------------------------------------------
1.创建一个Android工程
2.在设置-workspace中设置UTF-8
3.在设置-Android-NDK中,添加ndk工具开发
4.添加native依赖,选中项目名-Android Tools-art native support,命名一下,如(hehe),会生成jni目录
5.写一个显示c++代码里面返回的字符串
//写一个Button按钮
public void showNativeText(View view){
//此处调用接口方法使用
Toast.makeText(this,getNativeText(),Toast.LENGTH_SHORT).show();
}
7.写一个native接口方法
//例子是返回值是String类型
public native String getNateveText();
8.在项目文件夹根目录app下,打开命令行,输入
javah -d..\jni cn.android.hellojni.MainActivity//全类名
9.回到项目刷新一下,会多一个.h文件
10.在.cpp文件中
#include "cn_android_hellojni_MainActivity.h"
11.在.cpp文件中,实现
JNIEXPORT jstring JNICALL java_cn_android_hellojni_MainActivity_getNativeText//此处 jstring 为步骤 7 中的String返回值类型,getNativeText为步骤 7 中的接口方法;
(JNIEnv * env,jobject jo){//JNIEnv * 代表指针,指针:指向内存的地址;
return env->NewStringUTF("这是c++代码");
}
12.编译一下,会在libs--armeabli中生成一个.so库
13.如果模拟器使用的x86架构,需要在jni创建一个Application.mk的文件,里面加这么一句话:
APP_ABI := armeabli armeable-v7ax86
14.也可以写成所有的都生成:
APP_ABI :=all
15.然后在MainActivity中写一个静态代码块:
static{
System.LOadLibrary("hehe");//hehe 是上面依赖时重命名的那个名字
}
如果报错:INSTAL_FAILED_NO_MATCHING_ABIS 请执行第 14 步;
............................................................................................................................................................................
关键步骤打日志:
1.在Android.mk文件中加入
LOCAL_LDLIBS += -llog
2.在.cpp文件中加入
#include <android/log.h>
3.在.cpp文件中打日志
//_android_log_write(int prio,const char *tag,const char *text);//int prio 日志级别;const char *tag 字符型指针;const char *text 字符串内容
_android_log_write(ANDROID_LOG_INFO,"MainActivity的test","这是c++的日志");
-------------------------------------------------------------------------------Android Studio工程中-------------------------------------------------------------------------------
1.创建工程
2.在设置-SDK Location-Android NDK location中,添加ndk工具开发
3.配置
1.app-build.gradle中:除dependencies不动外,其他代码全部替换为:
apply plugin: "com.android.model.application"
model {
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
ndk {
moduleName "hehe" //native重命名的名称
ldLibs.add("log")
}
defaultConfig {
applicationId "cn.android.hellojni" //包名
minSdkVersion.apiLevel 19
targetSdkVersion.apiLevel 22
versionCode 1
versionName "1.0"
}
}
}
2.根目录-build.gradle中:dependencies{
//上面系统2.1.0这一行注释掉,使用以下插件
//classpath 'com.android.tools.build:gradle:2.1.0'
classpath 'com.android.tools.build:gradle-experimental:0.7.0'
}
3.gradle-wrapper-gradle-wrapper.properties中:2.10版本
4.写一个显示c++代码里面返回的字符串如下代码:
5.//写一个Button按钮
public void showNativeText(View view){
//此处调用接口方法使用
Toast.makeText(this,getNativeText(),Toast.LENGTH_SHORT).show();
}
6.写一个native接口方法
//例子是返回值是String类型
public native String getNateveText();//在这里Alt+Enter可能会出现在jni中有一个hehe.c文件,步骤参见7
7.选中jni目录,右键New-c/c++ 创建hehe.cpp文件,删除hehe.c文件
8.在项目文件夹根目录app下,打开命令行,输入
javah -d..\jni cn.android.hellojni.MainActivity//全类名
9.回到项目刷新一下,会多一个.h文件
10.在.cpp文件中
#include "cn_android_hellojni_MainActivity.h"
11.在.cpp文件中,实现
JNIEXPORT jstring JNICALL java_cn_android_hellojni_MainActivity_getNativeText//此处 jstring 为步骤 7 中的String返回值类型,getNativeText为步骤 7 中的接口方法;
(JNIEnv * env,jobject jo){//JNIEnv * 代表指针,指针:指向内存的地址;
return env->NewStringUTF("这是c++代码");
}
12.然后在MainActivity中写一个静态代码块:
static{
System.LOadLibrary("hehe");//hehe 是上面依赖时重命名的那个名字
}