之前介绍过了,之前创建一个基本的NDK的例子,所以下边我就直接给代码截图,总的来说假如你熟悉Java反射的话,那你理解可能回好一点,在NDK中也是使用反射去调用
使用javap打印方法签名
如果要是有javap 命令在AS中必须去该目录下才能使用,javap得到签名使用(javap -s Activity路径,斜杠以点代替)
这是hello.c
#include <jni.h>
#include <string.h>
#include <unistd.h> // sleep 的头文件
//引入log
#include <android/log.h>
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
char *JString2CStr(JNIEnv *env, jstring jstr) {
char *str = NULL;
jclass classStr = (*env)->FindClass(env, "java/lang/String");
jstring strencode = (*env)->NewStringUTF(env, "GB2312");
jmethodID mid = (*env)->GetMethodID(env, classStr, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray array = (*env)->CallObjectMethod(env, jstr, mid, strencode);
jsize alength = (*env)->GetArrayLength(env, array);
jbyte *byte = (*env)->GetByteArrayElements(env, array, JNI_FALSE);
if (alength > 0) {
str = (char *) malloc(alength + 1);// "\0"
str[alength] = '\0';
}
//recycle memory
(*env)->ReleaseByteArrayElements(env, array, byte, 0);
return str;
}
void showJavaDialog(JNIEnv* env,jobject obj,char* msg){
// 1.获取Java虚拟机,找到class的子节码
jclass jclazz = (*env)->FindClass(env, "com/wan/xiaofan/testndk/MainActivity");
/**
* jclazz 如果找到方法,返回的是一个内存地址,则大于0,反之等于0
*/
if(jclazz==0){
LOGD("没有找到类\n");
}else{
LOGD("找到类\n");
}
//获取字节码里的方法
jmethodID jmethod= (*env)->GetMethodID(env,jclazz,"showDialog","(Ljava/lang/String;)V");
if(jmethod==0){
LOGD("没有找到方法\n");
}else{
LOGD("找到方法\n");
}
// 调用方法
(*env)->CallVoidMethod(env,obj,jmethod,(*env)->NewStringUTF(env,msg));
}
void dismissJavaDialog(JNIEnv* env,jobject obj){
// 1.获取Java虚拟机,找到class的子节码
jclass jclazz = (*env)->FindClass(env, "com/wan/xiaofan/testndk/MainActivity");
/**
* jclazz 如果找到方法,返回的是一个内存地址,则大于0,反之等于0
*/
if(jclazz==0){
LOGD("没有找到类\n");
}else{
LOGD("找到类\n");
}
//获取字节码里的方法
jmethodID jmethod= (*env)->GetMethodID(env,jclazz,"dismissDialog","()V");
if(jmethod==0){
LOGD("没有找到方法\n");
}else{
LOGD("找到方法\n");
}
}
int safepay(JNIEnv *env, jobject obj, char *userName, char *pwd, float money, int radomCode,
long long time) {
LOGI("自定义的加密算法,加密userName\n");
//通知界面,更新UI,显示对话框
showJavaDialog(env,obj,"自定义的加密算法,加密userName");
sleep(1);
dismissJavaDialog(env,obj);
LOGI("检查本地环境\n");
showJavaDialog(env,obj,"检查本地环境");
sleep(2);
dismissJavaDialog(env,obj);
LOGI("验证支付证书,扫描本地支付环境\n");
showJavaDialog(env,obj,"验证支付证书,扫描本地支付环境");
sleep(2);
dismissJavaDialog(env,obj);
LOGI("交易金额是否超过最大限度\n");
showJavaDialog(env,obj,"交易金额是否超过最大限度");
sleep(3);
dismissJavaDialog(env,obj);
LOGI("提交数据到服务器,服务器端查询数据库,检查用户名和密码是否正确,连接网银接口\n");
showJavaDialog(env,obj,"提交数据到服务器,服务器端查询数据库,检查用户名和密码是否正确,连接网银接口");
sleep(4);
dismissJavaDialog(env,obj);
char *tempName = "zhangsan";
char *tempPwd = "123";
if (strcmp(tempName, userName) == 0 && strcmp(tempPwd, pwd) == 0 && money < 5000) {
return 200;
} else {
return 404;
}
}
/**
* env jvm环境的指针变化
* obj java对象
*/
JNIEXPORT jint JNICALL Java_com_wan_xiaofan_testndk_MainActivity_safePay(JNIEnv* env, jobject obj,
jstring jusername, jstring jpwd,
jfloat jmoney, jint jradomCode,
jlong jtime) {
//username 用户名 password 密码 money 金钱 randomcode 随机码 time 时间戳
char *name = JString2CStr(env, jusername);
char *pwd = JString2CStr(env, jpwd);
return safepay(env, obj, name, pwd, jmoney, jradomCode, jtime);
}
MainActivity
package com.wan.xiaofan.testndk;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private EditText editText_1, editText_2, editText_3;
private Button button;
private NDK ndk = null;
private ProgressDialog pd;
static {
System.loadLibrary("mytest");
}
/**
* username 用户名 password 密码 money 金钱 randomcode 随机码 time 时间戳
*/
public native int safePay(String username, String password, float money,int randomCode, long time);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ndk = new NDK();
initview();
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
String userName = editText_1.getText().toString().trim();
String pwd = editText_2.getText().toString().trim();
String money = editText_3.getText().toString().trim();
Log.i("wxf",""+userName);
Log.i("wxf",""+pwd);
Log.i("wxf",""+money);
int code=safePay(userName,pwd,Float.valueOf(money),(int) (System.currentTimeMillis() % 1000),System.currentTimeMillis());
if(code==200){
showToast("支付成功");
}else{
showToast("支付失败");
}
}
}).start();
}
});
}
private void initview() {
button = (Button) findViewById(R.id.button);
editText_1 = (EditText) findViewById(R.id.editText1);
editText_2 = (EditText) findViewById(R.id.editText2);
editText_3 = (EditText) findViewById(R.id.editText3);
}
/**
* 保证代码一定在主线程运行。
*
* @param msg
* 对话框的消息
*/
public void showDialog(final String msg) {
if ("main".equals(Thread.currentThread().getName())) {
// 工作在主线程
initDialog(msg);
} else {
// 子线程
runOnUiThread(new Runnable() {
@Override
public void run() {
initDialog(msg);
}
});
}
}
private void initDialog(final String msg) {
pd = new ProgressDialog(MainActivity.this);
pd.setTitle("提醒");
pd.setMessage(msg);
pd.show();
}
/**
* 关闭对话框的操作
*/
public void dismissDialog() {
if (pd != null && pd.isShowing()) {
pd.dismiss();
}
}
/**
* 显示土司
*
* @param msg
*/
public void showToast(final String msg) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
}
});
}
}
xml这是
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/editText1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:text="zhangsan"
android:hint="用户名默认zhangsan"
android:inputType="textPersonName" />
<EditText
android:id="@+id/editText2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:text="123"
android:hint="密码默认123"
android:inputType="textPersonName" />
<EditText
android:id="@+id/editText3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:text="2000.2"
android:hint="金额,单次不能超过5000"
android:inputType="textPersonName" />
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="提交" />
</LinearLayout>
在mk文件中加入
注意:
1、如果使用javap -s 在Activity中有该方法,而在签名中没有,运行一下项目即可,应该事文件还未过去