Android Studio 使用JNI
来源:互联网 发布:淘宝客服销售技巧 编辑:程序博客网 时间:2024/05/22 01:32
转载注明出处:http://www.cnblogs.com/aliflycoris/p/5507236.html
0x01 前言
本文讲述使用Android Studio通过静态注册、动态注册使用JNI的方法,以及加载第三方so文件的方法
0x02 Android Studio静态注册的方式使用JNI
1. 添加native接口
public class MainActivity extends Activity implements OnClickListener { static{ System.loadLibrary("JniTest"); } private native int Add(double num1,double num2); private native int Sub(double num1,double num2); private native int Mul(double num1,double num2); private native int Div(double num1,double num2); @Override protected void onCreate(Bundle savedInstanceState) { }}
在Java类中使用System.loadLibrary("JniTest")加载我们要写的so库名称,Add/Sub/Mul/Div这四个方法在Java类中声明就可以使用了。
2.Build->Make Project
验证工程中并无其他错误,并对工程进行编译,生成.class文件
在Build/intermediates/classes/debug里面
3.javah 生成.h文件
cmd 进入工程目录在工程的app/src/main/java ,执行 javah com.example.caculate.MainActivity 命令,就会生成so库所需要的.h文件
在/app/src/main/下建立jni目录,将.h拷贝进去
4.jni目录下新建一个.c文件,完成so库的函数实现(注:这里的Android.mk文件并不需要,可以不写,用法在下面会提到)
5.Build->Make Project 会报错,这里在android studio中添加ndk路径编译生成so文件
①在local.properties文件中增加ndk的路径
②在/app/目录下的build.gradle文件里增加 so的名称
ndk { moduleName "JniTest" abiFilters "armeabi", "armeabi-v7a", "x86"}
6.Build->Make Project 就可以编译出so文件了
生成的so在app/Build/intermediates/ndk/debug/lib下面
7.点击运行,就可以使用我们实现的so中的代码了
(注:在so库中实现在原结果基础上加2)
使用模拟器利用busybox安装grep命令之后,我们可以通过/proc/<pid>/maps文件中保存的进程加载模块,查看我们写的so文件是否被加载了。
8.我们JNI的实现文件
①com_example_caculate_MainActivity.h文件
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_example_caculate_MainActivity */#ifndef _Included_com_example_caculate_MainActivity#define _Included_com_example_caculate_MainActivity#ifdef __cplusplusextern "C" {#endif/* * Class: com_example_caculate_MainActivity * Method: Add * Signature: (DD)I */JNIEXPORT jint JNICALL Java_com_example_caculate_MainActivity_Add (JNIEnv *, jobject, jdouble, jdouble);/* * Class: com_example_caculate_MainActivity * Method: Sub * Signature: (DD)I */JNIEXPORT jint JNICALL Java_com_example_caculate_MainActivity_Sub (JNIEnv *, jobject, jdouble, jdouble);/* * Class: com_example_caculate_MainActivity * Method: Mul * Signature: (DD)I */JNIEXPORT jint JNICALL Java_com_example_caculate_MainActivity_Mul (JNIEnv *, jobject, jdouble, jdouble);/* * Class: com_example_caculate_MainActivity * Method: Div * Signature: (DD)I */JNIEXPORT jint JNICALL Java_com_example_caculate_MainActivity_Div (JNIEnv *, jobject, jdouble, jdouble);#ifdef __cplusplus}#endif#endif
②so库中实现函数的main.c文件
#include <jni.h>#define jintJNICALL#ifndef _Included_com_example_caculate_MainActivity#define _Included_com_example_caculate_MainActivity#ifdef __cplusplusextern "C" {#endifJNIEXPORT jintJNICALL Java_com_example_caculate_MainActivity_Add (JNIEnv *env, jobject obj, jdouble num1, jdouble num2){ return (jint)(num1 + num2+2);}JNIEXPORT jintJNICALL Java_com_example_caculate_MainActivity_Sub (JNIEnv *env, jobject obj, jdouble num1, jdouble num2){ return (jint)(num1 - num2+2);}JNIEXPORT jintJNICALL Java_com_example_caculate_MainActivity_Mul (JNIEnv *env, jobject obj, jdouble num1, jdouble num2){ return (jint)(num1 * num2+2);}JNIEXPORT jintJNICALL Java_com_example_caculate_MainActivity_Div (JNIEnv *env, jobject obj, jdouble num1, jdouble num2){ if (num2 == 0) return 0; return (jint)(num1 / num2+2);}#ifdef __cplusplus}#endif#endif
0x03 Android Studio动态注册的方式使用JNI
1.jni目录下直接编写so库中的.c文件
JNI_Onlad会作为so库被加载后的第一个执行函数,最后通过RegisterNatives函数将JNI函数注册
#include <jni.h>#include <stdio.h>//#include <assert.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>JNIEXPORT jint JNICALL native_Add(JNIEnv *env, jobject obj, jdouble num1, jdouble num2){return (jint)(num1 + num2 +1);}JNIEXPORT jint JNICALL native_Sub (JNIEnv *env, jobject obj, jdouble num1, jdouble num2){ return (jint)(num1 - num2 +1);}JNIEXPORT jint JNICALL native_Mul (JNIEnv *env, jobject obj, jdouble num1, jdouble num2){ return (jint)(num1 * num2 +1);}JNIEXPORT jint JNICALL native_Div (JNIEnv *env, jobject obj, jdouble num1, jdouble num2){ if (num2 == 0) return 0; return (jint)(num1 / num2 +1);}//Java和JNI函数的绑定表static JNINativeMethod gMethods[] = { {"Add", "(DD)I", (void *)native_Add}, {"Sub", "(DD)I", (void *)native_Sub}, {"Mul", "(DD)I", (void *)native_Mul}, {"Div", "(DD)I", (void *)native_Div},};//注册native方法到java中static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods){ jclass clazz; clazz = (*env)->FindClass(env, className); if (clazz == NULL) { return JNI_FALSE; } if ((*env)->RegisterNatives(env, clazz, gMethods,numMethods) < 0){ return JNI_FALSE; } return JNI_TRUE;}int register_ndk_load(JNIEnv *env){ return registerNativeMethods(env, "com/example/caculate/MainActivity", gMethods,sizeof(gMethods) / sizeof(gMethods[0])); //NELEM(gMethods));}JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved){ JNIEnv* env = NULL; jint result = -1; if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) { return result; } register_ndk_load(env); // 返回jni的版本 return JNI_VERSION_1_4;}
(注:这里Android.mk文件也不需要,在下面会提到)
2.在Java类中添加native接口,加载JniTest.so,以及声明native函数,声明之后,函数可以直接使用。
public class MainActivity extends Activity implements OnClickListener { static{ System.loadLibrary("JniTest"); } private native int Add(double num1,double num2); private native int Sub(double num1,double num2); private native int Mul(double num1,double num2); private native int Div(double num1,double num2); @Override protected void onCreate(Bundle savedInstanceState) { }}
3.make Project 生成so库,如果之前没有修改/app/build.gradle文件和在local.properties中指定ndk路径则会报错。报错参考静态使用JNI中的步骤5,指定ndk路径,并且指定so名称和输出的架构。
生成成功,则在/app/build/intermediates/ndk/debug/lib目录下生成相应的so文件
4.在虚拟机中运行
(注:这里的结果在原结果上加1)
0x04 Android Studio加载第三方库
1.使用ndk生成so文件
①建立jni目录(随便在哪个地方)
②编写so库中的.c函数,这里完全使用0x03 Android Studio动态注册的方式使用JNI中的c文件,使用动态注册的方式
③编写Android.mk文件(单独使用ndk编译so文件的时候需要用到)
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llogLOCAL_PRELINK_MODULE := falseLOCAL_MODULE := JniTestLOCAL_SRC_FILES := MyJniCalc.cLOCAL_SHARED_LIBRARIES := libandroid_runtimeinclude $(BUILD_SHARED_LIBRARY)
④使用cmd进入jni目录,执行ndk-build,生成so文件
2.加载生成的so文件,打包进apk中
①我们在/app目录下建立libs目录,将我们的so文件拷贝进去
这里可以使用ndk自己生成的so文件,也可以使用其他第三方so文件
②改写/app/build.gradle文件,编译的时候将so生成上图中的libJniTest.jar文件
apply plugin: 'com.android.application'android { compileSdkVersion 16 buildToolsVersion "23.0.3" defaultConfig { applicationId "com.example.caculate" minSdkVersion 8 targetSdkVersion 16 } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' } } sourceSets.main { jni.srcDirs = [] jniLibs.srcDir 'src/main/libs' } task nativeLibsToJar(type: Zip, description: "create a jar archive of the native libs") { destinationDir file("$projectDir/libs") baseName "libJniTest" extension "jar" from fileTree(dir: "libs", include: "**/*.so") into "lib" } tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn(nativeLibsToJar) }}dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:support-v4:18.0.0' compile files('libs/libJniTest.jar')}
其中into "lib" 是生成的jar文件存放的目录,include: "**/*.so" 为所依赖的so文件
③在Java类中添加so的接口
public class MainActivity extends Activity implements OnClickListener { static{ System.loadLibrary("JniTest"); } private native int Add(double num1,double num2); private native int Sub(double num1,double num2); private native int Mul(double num1,double num2); private native int Div(double num1,double num2); @Override protected void onCreate(Bundle savedInstanceState) { }}
4.Make Project,点击运行
这里不需要指定ndk路径,so库的名称也不需要在/app/build.gradle中指定,在Android.mk中指定
(注:这里结果在原结果上加1)
0x05 总结
这里是Android Studio中的使用方法,刚开始也是各种百度,弄得很复杂,在后面的学习中也懂得了很多,所以今天将使用方法重新整理了一遍,希望大家可以不要浪费太多时间。静态注册方法主要要用javah生成.h文件,显得比较复杂,每次添加函数都要重新生成.h文件,不过如果知道函数名称的格式也可以不生成.h文件,实践中,在jni目录下只有main.c文件也是可以运行成功的。动态注册方法直接在函数中注册比较容易动态扩展,但是需要对注册的数据类型有所了解,可以参考静态方法生成的.h文件中有对应的数据类型。加载第三方库感觉是最实用的,不管是so文件加密,还是使用不开源的so库,都需要加载已经生成的so文件。
注意/app/build.gradle中的sdk版本要改成自己android studio中sdk有的版本,如果没有也可根据android studio提示下载。
代码下载:http://pan.baidu.com/s/1dFyWHhf
0 0
- android studio JNI使用
- Android Studio使用JNI
- android studio使用jni
- Android Studio 使用JNI
- ANDROID STUDIO JNI使用
- Android studio 使用jni
- Android studio 使用jni
- Android Studio里使用JNI
- Android Studio 使用JNI入门
- 使用Android Studio开发 JNI
- Android Studio下使用JNI
- Android studio 中使用Jni
- android studio 使用JNI开发
- Android studio使用JNI实例
- Android Studio JNI使用实例
- Android studio JNI的使用
- Android Studio 使用JNI库
- Android studio使用JNI实例
- Swift元组
- 常用链接
- 自制摄像头+鱼眼镜头校正+极线校正+直接输出双目视频
- Xcode 8遇见新问题打印 subsystem: com.apple.siri等
- apktool下载地址
- Android Studio 使用JNI
- Mybatis 生成Oracle 数据库代码生成器
- explain详解
- 第18个python程序:命名变量代码函数
- 应聘时漂亮的回答
- [leetcode] 402. Remove K Digits 解题报告
- 房地产库存两极分化态势明显
- 【VLC-Android】vlc-android简例
- 规格化数据方法