JNI开发实践

1 创建一个java类,定义native方法

public static native boolean login(String name,String pw);

2 Build–>make project编译java代码

编译后,会在module目录下的生成.class文件,目录如图一
在这里插入图片描述
注意: .class文件的存放地址根据自己build–intermediates的具体情况而定

3 生成class文件后,编译生成.h头文件

打开Terminal命令窗口
进入到main目录下
输入如下命令
D:\dayuproject\ITCustom\app\src\main>javah -d jni -classpath D:\dayuproject\ITCustom\app\build\intermediates\javac\debug\compileDebugJavaWithJavac\classes tao.deepbaytech.com.itcustom.jni.LoginTest

注意 classes 后面有空格,即classes之前都是路径,需用\连接,而classes之后,从包名开始,使用.连接。

输入此命令后,按回车,运行命令后,就会在main目录下生成jni文件夹,并且,文件夹下会生成.h头文件
在这里插入图片描述
4 将jni文件剪切放到根目录下
在这里插入图片描述
5 在jni目录下,新建Android.mk文件和Application.mk文件用于配置本地方法

Android.mk

#LOCAL_PATH 获取当前路径一般都是call my-dir
LOCAL_PATH:=$(call my-dir)
#清除上次编译获取的编译环境变量会保存LOCAL_PATH
include $(CLEAR_VARS)

#libtestjni.so
#指定编译生成的模块名字叫什么 生成的.so名字回家上lib前缀和.so后缀
LOCAL_MODULE := loginjni
#指定要编译的.c源文件叫什么名字
LOCAL_SRC_FILES := test.cpp
LOCAL_LDLIBS := -llog
#生成动态链接库 .so文件
include $(BUILD_SHARED_LIBRARY)

Application.mk

APP_ABI := armeabi

#它表示CPU的构架平台类型.目前市场上常见的构架平台有armeabi,x86和mips,其中在移动设备中占据主要地位的是armeabi,这也是大部分apk中只包含armeabi类型的so库的原因,如果不配置此文件,就会生成arm64-V8a armeabi-v7a x86 x86_64

6 在build.gradle中配置externalnativeBuild

 externalNativeBuild {
    ndkBuild {
        path '../jni/Android.mk'
    }
}

####注意 externalNativeBuild{}对应的是ExternalNativeBuild

ExternalNativeBuild的属性:

1.cmake:CMake工具编译选项。
2.ndkBuild:ndk-build选项。


在externalNativeBuild{}中有2个模块,cmake{}和ndkBuild{}模块

------------------------------------------------
cmake{}对应的是CmakeOptions

CmakeOption的属性:
1.path:你的CmakeLists.txt编译脚本的相对路径。

--------------------------------------------------
ndkBuild{}对应的是NdkBuildOptions

NdkBuildOptions的属性:
1.path:你的Android.mk文件的相对路径。

--------------------------------------------------


externalNativeBuild{}的用法:

externalNativeBuild{
    ndkBuild{
        path file("src\\main\\jni\\Android.mk")
    }

    cmake {
        path "src/main/cpp/CMakeLists.txt"
    }
}

7 配置好后,利用Build-make project编译,就会生成.so文件
在这里插入图片描述
8 在module的main目录下创建jniLibs文件夹,将生成的.so文件拷贝到该文件夹下

因为在AS中,默认识别so文件的目录即为jniLibs,所以需要将so文件放置在此目录下,如果想要使用其他目录,可以按照如下方式修改App的build.gradle文件,其中jniLibs.srcDirs选项指定了新的存放so库的目录

 sourceSets {
    main {
        jniLibs.srcDirs = ['libs']
    }
}

因为在eclipse中,so文件是放在libs目录下的,所以,一般情况下,在build.gradle中配置此方法,也有去重的作用

9 在java代码中加载编译后生成的so类库,调用本地方法

 static {
        System.loadLibrary("loginjni");
    }

全部代码如下

public class LoginTest {

    private static LoginTest mLoginTest;
    private LoginTest(){}

    public static LoginTest getInstance(){
        if (mLoginTest==null){
            synchronized (LoginTest.class){
                if (mLoginTest==null){
                    mLoginTest=new LoginTest();
                }
            }
        }
        return mLoginTest;
    }

    public static native boolean login(String name,String pw);

    static {
        System.loadLibrary("loginjni");
    }
}

10 根据生成的.h文件,在jni目录中创建一个c文件,定义一个函数实现本地方法,函数名必须使用本地方法的全类名,点改为下划线

##.h文件

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

#ifndef _Included_tao_deepbaytech_com_itcustom_jni_LoginTest
#define _Included_tao_deepbaytech_com_itcustom_jni_LoginTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     tao_deepbaytech_com_itcustom_jni_LoginTest
 * Method:    login
 * Signature: (Ljava/lang/String;Ljava/lang/String;)Z
 */
JNIEXPORT jboolean JNICALL Java_tao_deepbaytech_com_itcustom_jni_LoginTest_login
  (JNIEnv *, jobject, jstring, jstring);

#ifdef __cplusplus
}
#endif
#endif

##对应的c文件

#include <jni.h>
#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif
//java程序还是应用的入口 在C中只是实现一些函数 等待着java去调用

//native函数命名规则  Java_包名_类名(包含native方法的java类)_native方法名
//JNIEnv* env
//JNIEnv 是结构体 JNINativeInterface的一级指针
//env是JNIEnv的一级指针 所以env就是结构体JNINativeInterface的二级指针
//JNINativeInterface 这个结构体中声明了大量的函数指针 这些函数指针在Jni开发中做用非常重要

//jobject thiz 哪个java对象通过jni调用到这个方法 这个jobject 就是这个java对象
//对于当前的案例来说 这个jobject就是MainActivity
//jstring  Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
//         jobject thiz )
//JNIEnv* env,jobject thiz 这两个参数是必须传入的
JNIEXPORT jboolean JNICALL Java_tao_deepbaytech_com_itcustom_jni_LoginTest_login
  (JNIEnv * env, jobject thiz, jstring name, jstring pw){
    return 0;
  }
}

调用

public void send(View view) {
    boolean login = LoginTest.getInstance().login(mName.getText().toString(), mPw.getText().toString());
    if (login){
        startActivity(new Intent(JniActivity.this,LoginActivity.class));
    }else {
        Toast.makeText(getApplicationContext(), "用户名或密码错误", Toast.LENGTH_SHORT).show();
    }
 
}

运行结果如下
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值