————————————这篇笔记不去介绍如何配置jni开发环境了,上一篇有说明——————————————
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <Button android:onClick="javaCallCForAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="java调用C代码加法运算" /> <Button android:onClick="javaCallCForString" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="java调用C代码字符串运算" /> <Button android:onClick="javaCallCForArray" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="java调用C代码数组运算" /> </LinearLayout>MainActivity.java
package com.atguigu.javacallc; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; public class MainActivity extends Activity { private JNI jni; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); jni = new JNI(); } //点击事件-Java代码调用C代码执行加法运算 public void javaCallCForAdd(View view){ int result = jni.add(99, 1); Log.e("TAG","result=="+result ); } public void javaCallCForString(View view){ String result = jni.sayHelloInC("I am from java"); Log.e("TAG","result=="+result ); } public void javaCallCForArray(View view){ int iArray[] = {1,2,3,4,5,6}; jni.arrElementsIncrease(iArray); for(int i=0;i<iArray.length;i++){ Log.e("TAG","result=="+iArray[i] ); } } }
JNI.java
package com.atguigu.javacallc; public class JNI { { //加载动态链接库 System.loadLibrary("atguigu"); } /** * 让C语言实现加法运算,并且把结果返回给java代码 */ public native int add(int x, int y); /** * 让C语言实现字符串运算,并且把结果返回给java代码 */ public native String sayHelloInC(String s); /** * 传入int类型的数组,让C语言把每个元素都加上10 * 应用场景:图片处理,像素矩阵。 */ public native int[] arrElementsIncrease(int[] intArray); }
下面是jni目录下的文件
Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := atguigu LOCAL_SRC_FILES := atguigu.c LOCAL_LDLIBS += -llog #1.liblog.so llog include $(BUILD_SHARED_LIBRARY)
atguigu.c
#include "com_atguigu_javacallc_JNI.h" #include<stdio.h> #include<stdlib.h> #include <android/log.h> #define LOG_TAG "atguigu" #define LOGD(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) /** * 把一个jstring转换成一个c语言的char* 类型. */ char* _JString2CStr(JNIEnv* env, jstring jstr) { char* rtn = NULL; jclass clsstring = (*env)->FindClass(env, "java/lang/String"); jstring strencode = (*env)->NewStringUTF(env,"GB2312"); jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid, strencode); // String .getByte("GB2312"); jsize alen = (*env)->GetArrayLength(env, barr); jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE); if(alen > 0) { rtn = (char*)malloc(alen+1); //"\0" memcpy(rtn, ba, alen); rtn[alen]=0; } (*env)->ReleaseByteArrayElements(env, barr, ba,0); return rtn; } /** * 做加法运算,把结果返回Java中的JNI.java类中的int add(int x, int y) */ JNIEXPORT jint JNICALL Java_com_atguigu_javacallc_JNI_add (JNIEnv * env, jobject jobj, jint ji, jint jy){ int result = ji + jy; //在Android平台上,失效了 LOGD("LOGD --result==%d\n",result); return result; } /** * 把Java代码传入进来的I am from java 后面加上add I am from C */ JNIEXPORT jstring JNICALL Java_com_atguigu_javacallc_JNI_sayHelloInC (JNIEnv * env, jobject jobj, jstring jstr){ //c 语言有字符串吗 jstring -->char* char* text1 = _JString2CStr(env,jstr);//I am from java char* text2 = " add I am from C"; //拼接函数-把拼接的结果放在第一个参数里面 strcat(text1,text2); //jstring (*NewStringUTF)(JNIEnv*, const char*); return (*env)->NewStringUTF(env,text1); } /** * 让C语言代码把传入的数组,每个元素都加上10 */ JNIEXPORT jintArray JNICALL Java_com_atguigu_javacallc_JNI_arrElementsIncrease (JNIEnv *env, jobject jobj, jintArray jarray){ //1.得到数组的长度 // jsize (*GetArrayLength)(JNIEnv*, jarray); jsize jsizes = (*env)->GetArrayLength(env,jarray); //2.遍历数组 // jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*); jint* jarrays = (*env)->GetIntArrayElements(env,jarray,JNI_FALSE); int i; for(i=0;i<jsizes;i++){ //3.给每一个数组的元素加上10 *(jarrays+i) += 10; } return jarray; }
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:id="@+id/tv_status" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="登录状态" /> <EditText android:id="@+id/et_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/tv_status" android:hint="请输入登录密码" /> <Button android:id="@+id/btn_login" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/et_password" android:text="登录" /> </RelativeLayout>
package com.atguigu.checkpassword; import android.app.Activity; import android.os.Bundle; import android.text.TextUtils; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { { System.loadLibrary("CheckPassword"); } private TextView tv_status; private EditText et_password; private Button btn_login; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_status = (TextView) findViewById(R.id.tv_status); et_password = (EditText) findViewById(R.id.et_password); btn_login = (Button) findViewById(R.id.btn_login); // 设置点击事件 btn_login.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 1.得到密码 String password = et_password.getText().toString().trim(); // 2.判断密码是否为空 if (TextUtils.isEmpty(password)) { Toast.makeText(MainActivity.this, "密码不能空", 1).show(); return; } // 3.传入密码给C语言 int coder = login(password); // 4.根据返回的状态码设置是否登录成功 if(coder ==200){ tv_status.setText("登录成功"); }else{ tv_status.setText("登录失败"); } } }); } /** * 判断密码是否正确,如果正确返回200 错误返回400 * * @param password * @return */ public native int login(String password); }以下是src同级目录jni文件夹下的文件
Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := CheckPassword LOCAL_SRC_FILES := CheckPassword.c include $(BUILD_SHARED_LIBRARY)
#include "com_atguigu_checkpassword_MainActivity.h" #include<stdlib.h> #include<stdio.h> /** * 把一个jstring转换成一个c语言的char* 类型. */ char* _JString2CStr(JNIEnv* env, jstring jstr) { char* rtn = NULL; jclass clsstring = (*env)->FindClass(env, "java/lang/String"); jstring strencode = (*env)->NewStringUTF(env,"GB2312"); jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid, strencode); // String .getByte("GB2312"); jsize alen = (*env)->GetArrayLength(env, barr); jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE); if(alen > 0) { rtn = (char*)malloc(alen+1); //"\0" memcpy(rtn, ba, alen); rtn[alen]=0; } (*env)->ReleaseByteArrayElements(env, barr, ba,0); return rtn; } /** 判断密码是否正确,如果正确返回200 错误返回400 */ int login(char* password){ //判断密码 //原始密码 char* originPassword = "atguigu123"; int coder = strcmp(password,originPassword); if(coder==0){ return 200; } else{ return 400; } } JNIEXPORT jint JNICALL Java_com_atguigu_checkpassword_MainActivity_login (JNIEnv * env, jobject jobj, jstring jstr){ //jstring-->char* char* text = _JString2CStr(env,jstr); int result = login(text); return result; }