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

本文详细介绍了如何在Android Studio中进行JNI开发,包括创建工程、编写Myjni类、配置External Tools生成.h文件、编写native代码、创建Android.mk和Application.mk文件,以及最终编译和测试调用Native方法的代码。通过这些步骤,开发者可以学习到如何从Native层调用Java方法和Android API。

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


一、创建工程


1.创建名为Jnitest01的工程



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


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


1.创建Myjni类



填写类名并点击OK




2.为Myjni类添加代码


代码:

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..->


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



2.设置tool信息


不愿意添加宏照抄即可,需要注意的是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文件



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

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


4.使用tool生成头文件




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




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

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


四、编写native代码


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



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


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




点击OK创建即可



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文件







代码如下:

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





代码如下:

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

7.修改Build.gradle  进行编译


Build.gradle:



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


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

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


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


1.添加两个测试按钮




2.为按钮添加回调方法



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




代码:

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 测试吧






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值