终于建了一个自己个人小站:https://huangtianyu.gitee.io,以后优先更新小站博客,欢迎进站,O(∩_∩)O~~
以前做过一段时间的JNI开发但是总是容易忘记一些简单的jni操作,最近重拾走过的jni开发之路,这里记录下如何在c层调用Java层类及方法,这里的类和方法可以是SDK里面的,也可以是自己编写的。这里分别给出测试工程,工程地址在文章末尾给出。JNI开发的环境配置及简单的JNI介绍百度一下资料很多。
首先编写MyTest.java类
import android.content.Context;
import android.widget.Toast;
/**
* Created by hty on 2016/8/5.
*/
public class MyTest {
static {
System.loadLibrary("mytest");
}
private Context mContext;
public MyTest(Context mContext){
this.mContext = mContext;
}
public void show(String msg){
Toast.makeText(mContext,msg,Toast.LENGTH_SHORT).show();
}
//调用自定义类的方法
public native void callShow(String msg);
//调用SDK里面的方法
public native void callToastShow(Context context,String msg);
}
然后利用javah生成对应的头文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
#include
/* Header for class com_scu_jnidemo_MyTest */
#define TAG "mytest"
#define LOGE(...) __android_log_print(__ANDROID_LOG_ERROR,TAG,__VA_ARGS_)/*这里是LOGE日志*/
#ifndef _Included_com_scu_jnidemo_MyTest
#define _Included_com_scu_jnidemo_MyTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_scu_jnidemo_MyTest
* Method: callShow
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_scu_jnidemo_MyTest_callShow
(JNIEnv *, jobject, jstring);
/*
* Class: com_scu_jnidemo_MyTest
* Method: callToastShow
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_scu_jnidemo_MyTest_callToastShow
(JNIEnv *, jobject,jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
最后编写对应的.cpp文件
//
// Created by hty on 2016/8/5.
//
#include "com_scu_jnidemo_MyTest.h"
/*
* Class: com_scu_jnidemo_MyTest
* Method: callShow
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_scu_jnidemo_MyTest_callShow
(JNIEnv *env, jobject thiz, jstring str){
jclass myclass = env->FindClass("com/scu/jnidemo/MyTest");
jmethodID mid = env->GetMethodID(myclass,"show","(Ljava/lang/String;)V");
env->CallVoidMethod(thiz,mid,str);
}
/*
* Class: com_scu_jnidemo_MyTest
* Method: callToastShow
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_scu_jnidemo_MyTest_callToastShow
(JNIEnv *env, jobject thiz,jobject context, jstring str){
jclass tclss = env->FindClass("android/widget/Toast");
jmethodID mid = env->GetStaticMethodID(tclss,"makeText","(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;");
jobject job = env->CallStaticObjectMethod(tclss,mid,context,str);
jmethodID showId = env->GetMethodID(tclss,"show","()V");
env->CallVoidMethod(job,showId,context,str);
}
最后在主程序里面进行测试:
package com.scu.jnidemo;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity implements View.OnClickListener{
private TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView)findViewById(R.id.text);
findViewById(R.id.button1).setOnClickListener(this);
findViewById(R.id.button2).setOnClickListener(this);
}
@Override
public void onClick(View view) {
MyTest myTest = new MyTest(this);
switch (view.getId()){
case R.id.button1:
myTest.callShow("这个是调用MyTest类里面的show");
break;
case R.id.button2:
myTest.callToastShow(this,"这个是JNI直接调用Toast");
break;
}
}
}
在程序里面需要注意的是在local.propreties里面需要将对应的sdk.dir和ndk.dir改成自己的路径
这里给出工程源码地址:JNI实现C层调用Java层函数