Android studio 中使用Jni
来源:互联网 发布:seajs 源码分析 玉伯 编辑:程序博客网 时间:2024/05/22 12:40
在使用Jni之前,我们需要对android studio进行一些配置:
有网的时候:在设置 - plugin - Android NDK Support 勾选--install plugin for disk
然后再打开设置---system setting--android SDK --sdk tool ---勾选上NDK
没网的时候:直接下载下来并进行解压
下载链接:点击打开链接
下载链接:点击打开链接
一、环境配置:
1、解压ndk到指定目录(该目录不能出现中文和空格)
修改系统的环境变量,在path里加上D:\soft\ndk\android_ndk_r10e;
2、创建Project
1)在local.properties文件里添加ndk路径ndk.dir=D\:\\soft\\ndk\\android_ndk_r10e
2)在build里添加
ndk{ moduleName "Hello" //可根据自己取,表示.so文件的前缀 ldLibs "log" //打印日志 abiFilters "armeabi", "armeabi-v7a", "x86" //指定CPU }
注意://如果你编写的.c文件include的时候报红,在build.gradle里添加
sourceSets.main { jni.srcDirs 'src/main/source' }最后build.gradle的代码:
android { compileSdkVersion 23 buildToolsVersion "23.0.2" defaultConfig { applicationId "com.suixi.ndkproject" minSdkVersion 15 targetSdkVersion 23 versionCode 1 versionName "1.0" ndk{ moduleName "javaCallC" ldLibs "log" //打印日志 abiFilters "armeabi", "armeabi-v7a", "x86" } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }}dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.2.1' compile 'com.jakewharton:butterknife:6.0.0'}3、兼容老的NDK
在gradle.properties里添加:
android.useDeprecatedNdk=true
二、若要在C语言中进行LOG日志
在build.gradle
ndk{ moduleName "cCallJava" ldLibs "log" //打印日志 abiFilters "armeabi", "armeabi-v7a", "x86" }
在.c文件中添加如下代码
#include <android/log.h> #define LOG_TAG "linzhenxiang" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)<span style="font-family:Consolas;background-color:#ffffff"></span>
三、编写java调用c语言的方式
1、写一个java类JNI(类名可自取),用于写native代码
public class JNI { public native String sayHello();//简单的调用 public native String sayAddHello(String s);//字符串拼接 public native int add(int x,int y);//加法运算 public native int[] increaseArray(int[] arr );//给数组的每个元素都增加10 public native int checkPwd(String s);//检查密码是否正确,并返回值}
2、动态的生成你所需要的C的头文件的两种方法
1)、在\NDKDEMO\app\src\main\java
执行命令:javah com.suixi.ndkproject.JNI(包名+类名)
2)、在studio底部中的terminal 里执行javah javah com.suixi.ndkproject.JNI
会自动生成如下的代码:
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_suixi_ndkproject_JNI */#ifndef _Included_com_suixi_ndkproject_JNI#define _Included_com_suixi_ndkproject_JNI#ifdef __cplusplusextern "C" {#endif/* * Class: com_suixi_ndkproject_JNI * Method: sayHello * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_suixi_ndkproject_JNI_sayHello (JNIEnv *, jobject);/* * Class: com_suixi_ndkproject_JNI * Method: sayAddHello * Signature: (Ljava/lang/String;)Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_suixi_ndkproject_JNI_sayAddHello (JNIEnv *, jobject, jstring);/* * Class: com_suixi_ndkproject_JNI * Method: add * Signature: (II)I */JNIEXPORT jint JNICALL Java_com_suixi_ndkproject_JNI_add (JNIEnv *, jobject, jint, jint);/* * Class: com_suixi_ndkproject_JNI * Method: increaseArray * Signature: ([I)[I */JNIEXPORT jintArray JNICALL Java_com_suixi_ndkproject_JNI_increaseArray (JNIEnv *, jobject, jintArray);/* * Class: com_suixi_ndkproject_JNI * Method: checkPwd * Signature: (Ljava/lang/String;)I */JNIEXPORT jint JNICALL Java_com_suixi_ndkproject_JNI_checkPwd (JNIEnv *, jobject, jstring);#ifdef __cplusplus}#endif#endif
3、在java中右键新建JniFodler,将上一步生成的.h文件移入改文件夹中
4、rebuild Project 下,会在build-->intermediates生成ndk文件夹
5、在JNI类下加载动态链接库
public class JNI { { System.loadLibrary("javaCallC");//动态加载。so文件,只要在用之前加载就成,不一定在这个类里加载 } public native String sayHello();//简单的调用 public native String sayAddHello(String s);//字符串拼接 public native int add(int x,int y);//加法运算 public native int[] increaseArray(int[] arr );//给数组的每个元素都增加10 public native int checkPwd(String s);//检查密码是否正确,并返回值 }
6、在jni文件夹下新建test.c文件,进行代码编写
#include "test.h"#include "com_suixi_ndkproject_JNI.h"#include <stdio.h>#include <stdlib.h>#include <android/log.h>#include <string.h>#define LOG_TAG "linzhenxiang"//打印日志的别名,可自己去#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)//jstring to char* jString 转换成 char*指针char *jstringTochar(JNIEnv *env, jstring jstr) { char *rtn = NULL; jclass clsstring = (*env)->FindClass(env, "java/lang/String"); jstring strencode = (*env)->NewStringUTF(env, "utf-8"); jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr = (jbyteArray) (*env)->CallObjectMethod(env, jstr, mid, strencode); jsize alen = (*env)->GetArrayLength(env, barr); jbyte *ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE); if (alen > 0) { rtn = (char *) malloc(alen + 1); memcpy(rtn, ba, alen); rtn[alen] = 0; } (*env)->ReleaseByteArrayElements(env, barr, ba, 0); return rtn;}JNIEXPORT jstring JNICALL Java_com_suixi_ndkproject_JNI_sayHello (JNIEnv *env, jobject jobject1) { // jstring (*NewStringUTF)(JNIEnv*, const char*); char *s = "I AM FROM C"; return (*env)->NewStringUTF(env, s);};/** * 返回带有参数的字符串 */JNIEXPORT jstring JNICALL Java_com_suixi_ndkproject_JNI_sayAddHello (JNIEnv *env, jobject jobject1, jstring js) { char *from = jstringTochar(env, js); char *to = "I am from c"; strcat(from, to);//字符串拼接,会把拼接后的结果放在第一个参数里 return (*env)->NewStringUTF(env, from);};/** * 加法运算 */JNIEXPORT jint JNICALL Java_com_suixi_ndkproject_JNI_add (JNIEnv *env, jobject jobject1, jint x, jint y) { return x + y;};/** * 给数组的每个元素添加10 */JNIEXPORT jintArray JNICALL Java_com_suixi_ndkproject_JNI_increaseArray (JNIEnv *env, jobject jobject1, jintArray array) { //jsize (*GetArrayLength)(JNIEnv*, jarray); jsize size = (*env)->GetArrayLength(env,array);//获取数组的长度 // jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*); jint* jint1 = (*env)->GetIntArrayElements(env,array,JNI_FALSE);//获取数组中的元素 int i; for(i=0;i<size;i++){ *(jint1+i)+=10; } return array;};/** * 检查密码是否正确 */JNIEXPORT jint JNICALL Java_com_suixi_ndkproject_JNI_checkPwd (JNIEnv * env, jobject jobject1, jstring js){ char * from = jstringTochar(env,js); char * origin = "123456"; //extern int strcmp(const char *, const char *) __purefunc; int code = strcmp(from,origin);//strcmp函数用于比较两个字符串是否相等 LOGE("code = %d",code); if(code==0){ return 400; }else{ return 200; }};
7、在activity中实例化JNI,并进行调用
四:在C中调用Java的方式
3、在java中右键新建JniFodler,将上一步生成的.h文件移入改文件夹中
4、rebuild Project 下,会在build-->intermediates生成ndk文件夹
定位到:build-->intermediates-->classes-->debug
按住 shift+鼠标右键 ----->点击此处打开命令窗口
执行:javap -s com/suixi/myapplication/JNI.class
生成如下签名:
7、在activity中调用
public class MainActivity extends Activity { private JNI jni; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.inject(this); jni = new JNI(); } @OnClick({R.id.btn1,R.id.btn2,R.id.btn3,R.id.btn4,R.id.btn5}) public void onClick(View v){ switch (v.getId()){ case R.id.btn1: String result = jni.sayHello(); Toast.makeText(this,result,Toast.LENGTH_LONG).show(); break; case R.id.btn2: String result1 = jni.sayAddHello("I am from java"); Toast.makeText(this,result1,Toast.LENGTH_SHORT).show(); break; case R.id.btn3: int result2 = jni.add(99,1); Toast.makeText(this,result2+"==",Toast.LENGTH_SHORT).show(); break; case R.id.btn4: int[] arr = {1,2,3,4,5}; jni.increaseArray(arr); for(int i=0;i<arr.length;i++){ Log.e("iii",arr[i]+"=="); } break; case R.id.btn5: String pwd = "1234566"; int code = jni.checkPwd(pwd); Toast.makeText(this,code+"--",Toast.LENGTH_SHORT).show(); break; } }}
四:在C中调用Java的方式
1、写一个java类JNI(类名可自取),用于写native代码
public class JNI { /** * 当执行这个方法的时候,让C代码调用 * public void helloFromJava() */ public native void callbackHelloFromJava(); public void helloFromJava() { Log.e("TAG", "helloFromJava()"); }}
2、动态的生成你所需要的C的头文件的两种方法
1)、在\NDKDEMO\app\src\main\java
执行命令:javah com.suixi.ndkproject.JNI(包名+类名)
2)、在studio底部中的terminal 里执行javah javah com.suixi.ndkproject.JNI3、在java中右键新建JniFodler,将上一步生成的.h文件移入改文件夹中
4、rebuild Project 下,会在build-->intermediates生成ndk文件夹
5、在JNI类下加载动态链接库
public class JNI { { System.loadLibrary("cCallJava"); } /** * 当执行这个方法的时候,让C代码调用 * public void helloFromJava() */ public native void callbackHelloFromJava(); public void helloFromJava() { Log.e("TAG", "helloFromJava()"); }}6、编写.c文件
#include "Test2.h"#include <jni.h>#include <stdlib.h>#include <stdio.h>JNIEXPORT void JNICALL Java_com_suixi_myapplication_JNI_callbackHelloFromJava(JNIEnv *env, jobject instance) { //jclass (*FindClass)(JNIEnv*, const char*); jclass jclazz = (*env)->FindClass(env,"com/suixi/myapplication/JNI");//第二个参数表示的是JNI所在的包名+类名 //第三个参数表示的是你要调用的java类中的方法, //第四个参数表示的是签名:定位到JNI.class文件的位置,通过命令行:javap -s com/suixi/myapplication/JNI.class // 生成签名 jmethodID jmethodID1 = (*env)->GetMethodID(env,jclazz,"helloFromJava","()V"); // jobject (*AllocObject)(JNIEnv*, jclass); jobject jobject1 = (*env)->AllocObject(env,jclazz); //通过该方法调用即可 (*env)->CallVoidMethod(env,jobject1,jmethodID1);};注意:GetMethodID的签名的生成方法
定位到:build-->intermediates-->classes-->debug
按住 shift+鼠标右键 ----->点击此处打开命令窗口
执行:javap -s com/suixi/myapplication/JNI.class
生成如下签名:
7、在activity中调用
public class MainActivity extends Activity { private JNI jni; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.inject(this); jni = new JNI(); } @OnClick({R.id.bt1}) public void onClick(View v){ switch (v.getId()){ jni.callbackHelloFromJava(); } }}源码下载:下载代码
0 0
- Android studio 中使用Jni
- Android studio中如何使用Ndk(Jni)?
- Android Studio 中使用JNI的步骤
- 在Android Studio中使用Jni
- Android Studio中使用NDK/JNI
- Android Studio中jni的使用
- Android Studio中使用NDK/JNI
- 【笔记】Android Studio中使用NDK-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 Jni开发之Android Studio中使用Android.mk
- 如何使用Android Studio开发/调试Android源码
- iOS - KeyChain
- HDU 2601:An easy problem【数学】
- 配置局域网网关
- JAVA多线程基础
- Android studio 中使用Jni
- C++ 多线程编程总结
- 让Python程序在线执行
- android-native 反编译环境
- 面向对象的基本设计原则
- Oracle中手动删除数据库
- java中double变量保留小数问题
- ubuntu下一些常见的apt命令
- BOM知识汇总