Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API

这一篇主要内容是Native调用java方法和Native调用Android API,以及External Tools快速生成.h文件,依然是使用NDK方式编译,如果是复制粘贴党,建议跟本文用一样的工程名,本文后面会提供demo链接


一、创建工程


1.创建名为Jnitest01的工程

Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第1张图片


2.点击Next 选择API等级,我选择的是26,Activity选择Empty Activity,一路next后点击Finish创建工程


二、创建Myjni类并编写load与Native接口


1.创建Myjni类

Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第2张图片


填写类名并点击OK


Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第3张图片


2.为Myjni类添加代码

Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第4张图片

代码:

public class Myjni {

    private Context lContext;
    static
    {
        System.loadLibrary("Myjni");
    }
    public Myjni(Context context){
        this.lContext = context;
    }

    public void MyToast(String s)
    {
        Toast.makeText(lContext, s, Toast.LENGTH_SHORT).show();
    }

    //native
    public native void MyjniToast(String s);
    //native
    public static native void NativeToast(Context context, String s);
    //native
    public static native String NativeString();
}

三、配置External tools快速生成.h头文件

1.打开External对话框

在菜单栏找到 File->Settings..->

Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第5张图片

然后找到 Tools->External tools点击添加Tool按钮

Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第6张图片


2.设置tool信息

Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第7张图片

不愿意添加宏照抄即可,需要注意的是Android SDK 的JAR包路径要根据自己的路径修改以下

Name:Javah

Description:Javah

Program:$JDKPath$\bin\javah

Parameters:-d jni -classpath D:\Android\android-sdk\platforms\android-19\\android.jar;$OutputPath$ $FileClass$

这里需要特别注意一下  D:\Android\android-sdk\platforms\android-19\\android.jar    这个SDK包的位置请根据自己的机器环境填写 否则会发生错误)

Working directory:$ProjectFileDir$

设置完毕点击OK即可


3. Make Project生成class文件

Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第8张图片


点击Make Project后会在工程路径  \app\build\intermediates\classes\debug\com\example\file\jnitest01 中生成出class文件,

下面生成头文件需要class文件


4.使用tool生成头文件


Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第9张图片


点击 javah 后会开始自动生成,生成成功会提示处理完成 错误为0个


Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第10张图片


由于宏设置的工作目录在工程的根目录,所以头文件会生成在工程根目录下面的jni文件夹中,

比如的我工程目录在 D:\AndroidStudioProjects\Jnitest01 ,那么在头文件会生成在 D:\AndroidStudioProjects\Jnitest01\jni 中


四、编写native代码


1.在Java目录下新建Jni文件夹

Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第11张图片


2.把上面生成的com_example_file_test01_Myjni.h 移动到新建的jni目录下


3.在jni目录下新建一个cpp文件名为Myjni.cpp


Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第12张图片


点击OK创建即可


Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第13张图片


4.为新建的Myjni.cpp编写native代码

由于代码有点长就不截图了,直接上代码


// Created by file on 2017/10/24.
#include 
#include 

#define  LOG_TAG    "native-dev"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)


JNIEXPORT void JNICALL Java_com_example_file_jnitest01_Myjni_MyjniToast
(JNIEnv* env, jobject job, jstring jStr)
{
    jclass myjniclass = NULL;
    jmethodID mid = NULL;
    const char* pNativeStr = NULL;
    jstring szOut = NULL;

    LOGI("MyjniToast---FindClass");
    myjniclass = env->FindClass("com/example/file/jnitest01/Myjni");
    if(myjniclass == NULL) {
        return;
    }
    mid = env->GetMethodID(myjniclass,"MyToast","(Ljava/lang/String;)V");
    if(mid == NULL) {
        return;
    }
    //jstring 转 char* 需要开内存所以下面必须使用ReleaseStringUTFChars释放  防止泄露
    pNativeStr = env->GetStringUTFChars(jStr, 0);
    if(pNativeStr == NULL) {
        return;
    }
    //重新生成一个jstring  也需要释放一下szOut
    szOut = env->NewStringUTF(pNativeStr);
    if(szOut == NULL) {
        return;
    }
    //调用Myjni.MyToast 方法
    env->CallVoidMethod(job, mid, szOut);
    //释放pNativeStr char*指针
    env->ReleaseStringUTFChars(jStr, pNativeStr);
    //释放szOut
    env->DeleteLocalRef(szOut);
}

JNIEXPORT void JNICALL Java_com_example_file_jnitest01_Myjni_NativeToast
(JNIEnv* env, jclass jc, jobject context, jstring jStr)
{
    jclass tclass = NULL;
    jmethodID mID = NULL;
    jobject job = NULL;
    jmethodID showId = NULL;

    tclass = env->FindClass("android/widget/Toast");
    if(tclass == NULL) {
        return;
    }
    //获取makeText方法ID
    mID = env->GetStaticMethodID(tclass,"makeText","(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;");
    if(mID == NULL) {
        return;
    }
    //调用makeText  第5个参数是makeText的duration
    job = env->CallStaticObjectMethod(tclass, mID, context, jStr , 0);
    if(job == NULL) {
        return;
    }
    showId = env->GetMethodID(tclass,"show","()V");
    if(showId == NULL) {
        return;
    }
    env->CallVoidMethod(job, showId, context, jStr);
}

JNIEXPORT jstring JNICALL Java_com_example_file_jnitest01_Myjni_NativeString
(JNIEnv* env, jclass)
{
    return env->NewStringUTF("NativeString");
}


5.创建Android.mk文件


Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第14张图片


Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第15张图片


Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第16张图片


代码如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := cpp
LOCAL_MODULE    := Myjni
LOCAL_SRC_FILES := Myjni.cpp
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)


6.创建Application.mk

Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第17张图片


Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第18张图片


代码如下:

APP_ABI := all
APP_STL := stlport_static
APP_OPIM := debug

7.修改Build.gradle  进行编译


Build.gradle:

Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第19张图片


ndk{
    moduleName "myjni"                              //so文件名
}


 
  
externalNativeBuild {
    ndkBuild {
        path "src/main/jni/android.mk"
    }
}

6.修改完成点击 Build->Build APK ,提示编译成功的话就可以添加调用Native方法的代码了


五、为Activity添加两个测试按钮


1.添加两个测试按钮


Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第20张图片


2.为按钮添加回调方法

Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第21张图片


3.在 MainActivity中实现回调方法并调用Native方法


Android Studio Jni开发(二)实现Native调用java方法和Native调用Android API_第22张图片


代码:

public void button_MyjniToast(View view) {

    jni.MyjniToast("Myjni.MyjniToast->Myjni->MyToast");
}


public void button_NativeToast(View view) {
    jni.NativeToast(this, "Myjni.NativeToast->android.widget.Toast");
}

六、Build APK 测试吧






你可能感兴趣的:(Android,JNI开发)