环境搭建
1. android studio2021.2.1
2. JDK版本1.8
一、创建一个android项目
File ——> New ——> New Project ——> Empty Activity
创建后如下图所示

二、C调用java代码过程
2.1 写java类代码
创建一个java的JNI类,写触发C代码,让C调用java的cCallJava()方法
    /**
     * 触发C代码让其调用cCallJava()方法
     */
    public native void callbackCCallJava();
    public void cCallJava(){
        System.out.println("C调用到了java的方法cCallJava");
    } 

2.2 生成对应的C代码的头文件
(1)AS打开Terminal窗口
点击底部导航栏Terminal

(2) 用命令打开JNI类所在的目录
在Terminal窗口中输入cd app\src\main\java\com\zaq\ccalljava,按键盘Enter键

(3)用命令生成头文件
javac -encoding utf8 -h . JNI.java(注意:-encoding utf8 指定源文件编码格式,-h后面有个点, 点 前后面都有个空格,点的意思是头文件生成在当前目录下)
执行后过会会自动生成一个jni头文件com_zaq_ccalljave_JNI.h,如下图所示:

2.3 设置编译方式ndk-build相关配置
(1)在main下创建一个jni文件夹

(2) 把头文件移到jni文件夹下,删除JNI.class

(3)在jni下创建C/C++ Source File,命名为Test.c。

(4)在jni下创建文件Android.mk
Android.mk里面的内容
#表示Android.mk所在目录
LOCAL_PATH := $(call my-dir)
#CLEAR_VARS变量指向特殊 GNU Makefile,用于清除部分LOCAL_变量
include $(CLEAR_VARS)
#模块名称
LOCAL_MODULE    := javacallc
#构建系统用于生成模块的源文件列表
LOCAL_SRC_FILES := Test.c
#BUILD_SHARED_LIBRARY 表示.so动态库
#BUILD_STATIC_LIBRARY 表示.a静态库
include $(BUILD_SHARED_LIBRARY) 

(5)在gradle.build中的配置,生成so库文件
①android里面的defaultConfig配置
//定义ndkBuild默认配置属性
 externalNativeBuild {
     ndkBuild {
         cppFlags ""
     }
 }
 ndk {
     // 生成指定CPU平台对应的so库文件
     abiFilters "arm64-v8a"
 } 
②跟defaultConfig同级的配置
//定义ndkBuild对应的Android.mk路径(重要)
externalNativeBuild {
    ndkBuild{
        path file("src/main/jni/Android.mk")
    }
} 

查看so生成文件
重新Rebuild Project,即点击状态栏的 File ——> Rebuild Project
so文件的最终命名是lib+ccalljava(Android,mk文件里面的模块名称).so,即:libccalljava.so
最终生成so库文件的路径如下:

2.4 T代码的实现
(1)Test.c代码实现调用java方法
#include "com_zaq_ccalljava_JNI.h"
#include <jni.h>
#include <stdlib.h>
#include <stdio.h>
/**
 * 调用java代码中JNI类里面的public void cCallJava()
 * @param env
 * @param jobj
 */
JNIEXPORT void JNICALL Java_com_zaq_ccalljava_JNI_callbackCCallJava
        (JNIEnv *env, jobject jobj){
    // 1.得到字节码
    // jclass      (*FindClass)(JNIEnv*, const char*);
    jclass jclazz=(*env)->FindClass(env,"com/zaq/ccalljava/JNI");
    // 2.得到方法
    // jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
    jmethodID jmethodIDs=(*env)->GetMethodID(env,jclazz,"cCallJava", "()V");
    // 3.实例化该类
    // jobject     (*AllocObject)(JNIEnv*, jclass);
    jobject obj=(*env)->AllocObject(env,jclazz);
    // 4.调用方法
    // void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
    (*env)->CallVoidMethod(env,obj,jmethodIDs);// 可成功调用JNI类中的public void cCallJava()
} 

(2)MainActivity调动JNI类的方法

(3)JNI类加载so文件

(4)运行安装apk,点击按钮有日志输出,说明C成功调用java方法












![[数据结构 -- C语言] 队列(Queue)](https://img-blog.csdnimg.cn/img_convert/6dbb63a1b5f184a2f1f5413eba102d33.png)







