您的位置:首页 > 移动开发 > Android开发

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

2017-10-24 22:01 891 查看
这一篇主要内容是Native调用java方法和Native调用Android API,以及External Tools快速生成.h文件,依然是使用NDK方式编译,如果是复制粘贴党,建议
c24b
跟本文用一样的工程名,本文后面会提供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 测试吧
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息