真实开发中如何使用jni
如阿里旺旺 :登陆的具体实现 c/c++
安全性要求很高:socket http
步骤:
1、C工程师编写核心的登陆实现
int login(char* username,char * password){
//取每一个字符和正确是字符进行比较
//开启一个socket 连接服务器 , 把username 和 password传给服务器.
//服务器返回 200 登陆成功
//服务器返回404 登陆失败
}
2、Java中声明native方法
public native int callLogin(String username, String pwd);
3、javah 生成native方法的签名
4、在android工程目录中,建立jni目录,根据ndk文档,编写android.mk文件,编写c代码,在生成签名的c代码中,调用c工程师写好的login方法
jint Java_xxx_xxx_xxx_xxx_Login(JNIENV* env , jobject obj , jstring username, jstring pwd){
char* cusername = JStr2Cstr();
char* cpwd = JStr2Cstr();
int result = login(cusername ,cpwd);
if(result == 200){
}
}
5、在Android工程中,就可以通过调用native方法callLogin()来调用c代码实现登录
|
代码: 1、myLogin.c-C工程师写的核心登录代码和java调用的代码 #include <stdio.h>
#include <stdlib.h>
#include <android/log.h>
#include <jni.h>
#include "cn_zengfansheng_realdevp_LoginNative.h"
#define LOG_TAG "System.out.c" //在LogCat上打印出来的Tag #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) //0、工具类:返回值 char* 这个代表char数组的首地址
//Jstring2CStr 把java中的jstring的类型转化成一个c语言中的char 字符串
char* Jstring2CStr(JNIEnv* env, jstring jstr) {
char* rtn = NULL;
jclass clsstring = (*env)->FindClass(env, "java/lang/String"); //String
jstring strencode = (*env)->NewStringUTF(env, "GB2312"); // 得到一个java字符串 "GB2312"
jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes",
"(Ljava/lang/String;)[B"); //[ String.getBytes("gb2312");
jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid,
strencode); // String .getByte("GB2312");
jsize alen = (*env)->GetArrayLength(env, barr); // byte数组的长度
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;
} //1、登录核心,用C代码实现
int login(char* username, char* password) {
//1、取每一个字符和真实密码的字符进行比较
char* realuser = "hacket";
char* realpwd = "123456";
int i = 0;
for (; *(realuser + i) != '\0'; i++) {
if (*(username + i) != *(realuser + i)) { //如果有一个字符不相等,返回404;
return 404;
}
}
printf("----------------\n");
int j = 0;
for (; *(realpwd + j) != '\0'; j++) {
if (*(password + j) != *(realpwd + j)) {
return 404;
}
}
return 200;
}
//2、java调用的登录代码
JNIEXPORT jint JNICALL Java_cn_zengfansheng_realdevp_LoginNative_callLogin(
JNIEnv *env, jobject obj, jstring juser, jstring jpwd) { //1、将java的字符串转成c语言中的char*
char* cuser = Jstring2CStr(env, juser);
char* cpwd = Jstring2CStr(env, jpwd);
LOGD("cuser=%s", cuser);
LOGD("cpwd=%s", cpwd); //2、调用login进行登录
int resultcode = login(cuser, cpwd);
LOGD("resultcode=%d", resultcode); //3、返回给java上层调用
return resultcode;
} |
2、android.mk LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MyLogin
LOCAL_SRC_FILES := myLogin.c
#查看ndk官方文档:LOCAL_LDLIBS := -lz
LOCAL_LDLIBS += -llog
include $(BUILD_SHARED_LIBRARY)
|
3、LoginNative-java中声明的本地native方法 package cn.zengfansheng.realdevp;
public class LoginNative {
public native int callLogin(String username, String pwd);
} |
4、MainActivity.java-java中调用本地native方法 package cn.zengfansheng.realdevp;
import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity { private EditText et_user;
private EditText et_pwd; static {
// libMyLogin.so
System.loadLibrary("MyLogin");
} @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_user = (EditText) this.findViewById(R.id.et_username);
et_pwd = (EditText) this.findViewById(R.id.et_password);
}
public void loginFromC(View view) {
String username = et_user.getText().toString();
String password = et_pwd.getText().toString();
if (TextUtils.isEmpty(username) || TextUtils.isEmpty(password)) {
Toast.makeText(this, "用户名或密码不能为空·", Toast.LENGTH_LONG).show();
return;
}
LoginNative loginNative = new LoginNative();
int resultCode = loginNative.callLogin(username, password);
if (resultCode == 200) {
Toast.makeText(this, "登录成功~", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "用户名或密码不能为空:" + resultCode, Toast.LENGTH_LONG).show();
}
}
} |
结果: |