首页 > 代码库 > c调用java

c调用java

技术分享

public class MainActivity extends AppCompatActivity {

    private JNI jni;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        jni = new JNI();
    }

    public void test1(View v){
        jni.callVoid();
    }
    public void test2(View v){
        jni.callInt();
    }
    public void test3(View v){
        jni.callString();
    }

    public void test4(View v){
        //jni.callShowToast();
        callShowToast();
    }

    public void showToast(String s){
        Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
    }

    public native void callShowToast();
}

 

public class JNI {
    static {
        System.loadLibrary("ccalljava");
    }
   // C调用java空方法
    public void helloFromJava(){
        Log.e("calljava","hello from java");
    }
   // C调用java中的带两个int参数的方法
    public int add(int x,int y) {
        return x+y;
    }
   // C调用java中参数为string的方法
    public void printString(String s){
        Log.e("calljava",s);
    }

    public native void callVoid();
    public native void callInt();
    public native void callString();
    public native void callShowToast();

}

技术分享

上面图片是下面代码的标题

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

#ifndef _Included_com_itheima_ccalljava_JNI
#define _Included_com_itheima_ccalljava_JNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_itheima_ccalljava_JNI
 * Method:    callVoid
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_itheima_ccalljava_JNI_callVoid
  (JNIEnv *, jobject);

/*
 * Class:     com_itheima_ccalljava_JNI
 * Method:    callInt
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_itheima_ccalljava_JNI_callInt
  (JNIEnv *, jobject);

/*
 * Class:     com_itheima_ccalljava_JNI
 * Method:    callString
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_itheima_ccalljava_JNI_callString
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

 Android.mk文件:下面

# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#LOCAL_PATH 获取当前路径
LOCAL_PATH := $(call my-dir)
# 清除上次编译获取的编译环境变量 会保存LOCAL_PATH
include $(CLEAR_VARS)

#指定编译生成的模块叫什么名字  生成的.so名字会加上lib前缀和.so后缀
LOCAL_MODULE    := ccalljava
#指定要编译的.c源文件叫什么名字
LOCAL_SRC_FILES := ccalljava.c
LOCAL_LDLIBS += -llog

#生成动态链接库 .so文件
include $(BUILD_SHARED_LIBRARY)

 

#include <jni.h>
// Created by fullcircle on 2017/2/19.
//
#include <android/log.h>
#define LOG_TAG "System.out"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
JNIEXPORT void JNICALL Java_com_zz_ccalljava_JNI_callVoid
(JNIEnv * env, jobject thiz){
    //①找到字节码对象  Class  jclass      (*FindClass)(JNIEnv*, const char*);
    //第二个参数 要找到的字节码的全类名
    jclass clazz = (*env)->FindClass(env,"com/zz/ccalljava/JNI");
    //②在Class 中找到要调用的方法 Method
    //jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
    //GetMethodID 第二个参数 clazz字节码对象 第三个参数方法的名字 第四个参数 方法签名 可以通过javap -s 获取
    //在Studio中到模块的 build/intermediates/classes/debug 执行javap -s 要生成方法签名的类的全路径
    jmethodID methodID = (*env)->GetMethodID(env,clazz,"helloFromJava","()V");
    //③通过Class获取对象(有时可以省略 当native方法和要回调的java方法在同一个类中就可以使用传过来的jobject调用方法)
    //④通过对象调用方法 void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
    (*env)->CallVoidMethod(env,thiz,methodID);
}

/*
 * Class:     com_zz_ccalljava_JNI
 * Method:    callInt
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_zz_ccalljava_JNI_callInt
(JNIEnv * env, jobject thiz){
    //①找到class
    jclass clazz =(*env)->FindClass(env,"com/zz/ccalljava/JNI");
    //②找到方法
    jmethodID  methodID = (*env)->GetMethodID(env,clazz,"add","(II)I");
    //③调用方法
    int result = (*env)->CallIntMethod(env,thiz,methodID,3,4);
    LOGE("result=%d",result);
}

/*
 * Class:     com_zz_ccalljava_JNI
 * Method:    callString
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_zz_ccalljava_JNI_callString
(JNIEnv * env, jobject thiz){
    jclass clazz = (*env)->FindClass(env,"com/zz/ccalljava/JNI");
    jmethodID methodID=(*env)->GetMethodID(env,clazz,"printString","(Ljava/lang/String;)V");
    jstring jstr = (*env)->NewStringUTF(env,"hello from c");
    (*env)->CallVoidMethod(env,thiz,methodID,jstr);
}

JNIEXPORT void JNICALL Java_com_zz_ccalljava_JNI_callShowToast
        (JNIEnv * env, jobject thiz){
    jclass clazz =(*env)->FindClass(env,"com/zz/ccalljava/MainActivity");
    jmethodID methodID = (*env)->GetMethodID(env,clazz,"showToast","(Ljava/lang/String;)V");
    //由于callShowToast这个native方法是在 jni这个类中 要调用的java方法是在MainActivity中 所以不能使用传入的jobject
    //需要创建一个对象 jobject     (*AllocObject)(JNIEnv*, jclass);
    jobject jobj =(*env)->AllocObject(env,clazz);
    jstring jstr = (*env)->NewStringUTF(env,"hello from c");
    (*env)->CallVoidMethod(env,jobj,methodID,jstr);
}


JNIEXPORT void JNICALL Java_com_zz_ccalljava_MainActivity_callShowToast
        (JNIEnv * env, jobject thiz){
    jclass clazz =(*env)->FindClass(env,"com/zz/ccalljava/MainActivity");
    jmethodID methodID = (*env)->GetMethodID(env,clazz,"showToast","(Ljava/lang/String;)V");
    //由于callShowToast这个native方法是在 jni这个类中 要调用的java方法是在MainActivity中 所以不能使用传入的jobject
    //需要创建一个对象 jobject     (*AllocObject)(JNIEnv*, jclass);
   // jobject jobj =(*env)->AllocObject(env,clazz);
    jstring jstr = (*env)->NewStringUTF(env,"hello from c");
    (*env)->CallVoidMethod(env,thiz,methodID,jstr);
}

 

c调用java