Android NDK JNI开发<7>

这一节C回调java程序方法,这步骤如下:

<1> : 启动eclipse,新建一个android工程,取名:hellojnidemo5,MainActivity的包名:package com.example.hellojnidemo5;这里面我回调的函数不是在这个包下,另外重新新建了一个包:package java2c;

在package java2c下新建一个回调用的类:functionInteface,代码如下:

package java2c;

public class functionInteface {

    public native void javaToca();
    public native void javaTocb();
    public native void javaTocc();
    
    public void show(){
        System.out.println("show java information .");
    }
    
    public int multi(int x, int y) {
        return x * y;
    }

    public void msg(String m) {
        System.out.println("your information : " + m);
    }

}

 

有个细节要注意,要手动eclipse菜单project->clean一下,当然如果选择project->build automatically(如果勾上,会导致eclipse有点卡),那么就不需要手动.这样就可以让eclipse自动为我们生成.class文件了->functionInteface.class

<2> : 要将java类生成.h头文件,借助的是javah命令,当然前面可以用javac编译生成.class,就不要eclipse,但是javac只是在文件数目少的情况下,手工输入还行.

这个目录让人有点纠结,不知道为什么,其实很简单:

比如我的工程目录在 : D:\ADB\android-ndk-r9d\workspace-jni\hellojnidemo5,而生成的.class在工程目录下子目录/bin/classes/java2c目录下,

但是用javah命令不要求进入到java2c这个目录下才能编译,根据javah后面带的格式,只需要进入顶级包文件夹所在的目录即可,即这里只需要进入classes目录下就可以了,

所以,启动cmd.exe

然后输入的命令格式 : javah -jni packagename.classname(不带扩展名)

这里是: D:\ADB\android-ndk-r9d\workspace-jni\hellojnidemo5\bin\classes>javah -jni java2c.functionInteface

结果就在classes目录下生成了java2c_functionInteface.h的头文件(生成后的头文件可以修改文件名放到jni文件夹下),具体内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class java2c_functionInteface */

#ifndef _Included_java2c_functionInteface
#define _Included_java2c_functionInteface
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     java2c_functionInteface
 * Method:    javaToca
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_java2c_functionInteface_javaToca
  (JNIEnv *, jobject);

/*
 * Class:     java2c_functionInteface
 * Method:    javaTocb
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_java2c_functionInteface_javaTocb
  (JNIEnv *, jobject);

/*
 * Class:     java2c_functionInteface
 * Method:    javaTocc
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_java2c_functionInteface_javaTocc
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

 

另外一个javap -s packagename.classname可以获得方法的签名,这个签名信息非常重要,是后面c中事要用到的信息:

 

(如果经常报出javah找不到文件,这个问题上次在公司见过,其实没什么大不了的,是由于jdk设置环境变量导致的:

具体设置参考: http://blog.csdn.net/yusiguyuan/article/details/14123669(主要要设置JAVA_HOME变量,具体原因不清楚,我一直都是直接用jdk绝对路径)

 另外附加一条连接:http://361324767.blog.163.com/blog/static/11490252520103783716114/做参考.)

 <3> 折腾了半天,把c源码写出来(javatoc.h):

#include "java2c_functionInteface.h"
#include<android/log.h>
#include<string.h>

//修改日志tag中的值
#define LOG_TAG "logfromc"
//日志显示的等级
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

JNIEXPORT void JNICALL Java_com_example_hellojnidemo5_MainActivity_javaToca(JNIEnv * env,jobject obj){
    LOGI("in call java msg");

    //get class name firstly // 获取到functionInteface对象
    char* classname="java2c/functionInteface";
    jclass dpclazz=(*env)->FindClass(env,classname);
    if(dpclazz==0){
        LOGI("not find class!");
    }else{
        LOGI("find class");
    }

    //第三个参数 和第四个参数 是方法的签名,第三个参数是方法名  , 第四个参数是根据返回值和参数生成的
    jmethodID methodID=(*env)->GetMethodID(env,dpclazz,"show","()V");
    if(methodID==0){
        LOGI("not find method!");
    }else{
        LOGI("find class");
    }
    //获取到functionInteface要调用的方法
    (*env)->CallVoidMethod(env,obj,methodID);

}

JNIEXPORT void JNICALL Java_com_example_hellojnidemo5_MainActivity_javaTocb(JNIEnv * env,jobject obj){
    LOGI("in call java msg");

    //get class name firstly
    char* classname="java2c/functionInteface";
    jclass dpclazz=(*env)->FindClass(env,classname);
    if(dpclazz==0){
        LOGI("not find class!");
    }else{
        LOGI("find class");
    }

    jmethodID methodID=(*env)->GetMethodID(env,dpclazz,"msg","(Ljava/lang/String;)V");
    if(methodID==0){
        LOGI("not find method!");
    }else{
        LOGI("find class");
    }

    (*env)->CallVoidMethod(env,obj,methodID,(*env)->NewStringUTF(env,"zhibao.liu"));

}

JNIEXPORT void JNICALL Java_com_example_hellojnidemo5_MainActivity_javaTocc(JNIEnv * env,jobject obj){
    LOGI("in call java msg");

    //get class name firstly
    char* classname="java2c/functionInteface";
    jclass dpclazz=(*env)->FindClass(env,classname);
    if(dpclazz==0){
        LOGI("not find class!");
    }else{
        LOGI("find class");
    }

    jmethodID methodID=(*env)->GetMethodID(env,dpclazz,"multi","(II)I");
    if(methodID==0){
        LOGI("not find method!");
    }else{
        LOGI("find class");
    }

    (*env)->CallVoidMethod(env,obj,methodID,11,12);

}

<4> : 用cgywin编译后生成so文件.

<5> android调用代码:

package com.example.hellojnidemo5;

import java2c.functionInteface;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {

    private Button mShowBtn;
    private Button mMultiBtn;
    private Button mMsgBtn;
    private functionInteface fn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        fn=new functionInteface();
        
        mShowBtn=(Button)findViewById(R.id.button1);
        mShowBtn.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                Toast.makeText(MainActivity.this, "show message ! ", Toast.LENGTH_SHORT).show();
                fn.show();
                fn.javaTocb();
            }
            
        });
        
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    
    static{
        System.loadLibrary("jnilibs");
    }
    
}

 

 

 这一片文章最后要推荐一个参考链接:http://blog.csdn.net/furongkang/article/details/6857610

 似乎全部的网络和教材都TMD用一个例子再讲,汗死一片....

 

 

 

 

 

 

posted @ 2014-03-17 01:18  MMLoveMeMM  阅读(326)  评论(0)    收藏  举报