最近入手安卓的开发与学习,就迫不及待的下载了最新版的AS3.4。可是当我开发JNI程序时,却发现网上的方法大多已经过时,所以在此更新一波以做备忘。
环境:Win10 X86 64位 Android Studio 3.4稳定版
1.JNI的作用
jni的全称就是Java Native Interface,就是Java和C/C++相互通信的接口,实现了一个工程,多种语言并存。那么什么时候需要用到JNI呢?
1.需要调用java语言不支持的依赖于操作系统平台的特性的一些功能;
2.为了整合一些以前使用非java语言开发的某些系统,例如C和C++;
3.为了节省程序的运行时间,必须采用一些低级或中级语言。
说道JNI就不得不提NDK,NDK(Native Development Kit)是Google提供的一套工具集,可以让你其他语言(C、C++或汇编)开发 Android的 JNI。NDK可以编译多平台的so(动态链接库).所以我们用AS开发JNI程序一般都会使用NDK开发。
而开发方法常见的一般有两种,第一种是使用安卓的mk工具,第二种是使用CMake工具。在这里,只讲CMake(了解过,哈哈).
2.JNI开发的环境配置
笔者使用的是Android Studio3.4,紧跟潮流嘛,感兴趣的可以更新一下。
1.JNI相关工具的下载:Tools->SDK Manager->SDK tools
说白了就是配置NDK,打对号的都清勾上下载,等待自动安装完毕。
waiting~~安装完之后检查NDK路径是否配置或是否配置正确:File->Project Structure->SDK location
3.JNI开发小Demo
新建工程HelloJNI:
新建一个SayHello的java类,声明一个native方法:
package com.example.hellojni;
public class SayHello {
public static native String sayHello();
在build.gradle文件下配置NDK和Cmake相关属性,然后点击右上角同步:
新建JNI folder用来放置C/C++文件
新建NativeHelloJNI.cpp文件,用来实现java层的sayHello方法:
在app目录下新建一个CMakeLists.txt文件,它用来编译C/C++代码:
配置CMakeLists.txt文件内容,附上了详细注释:
#指定CMake构建本地库时所需的最小版本
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library. 将资源文件生成动态链接库(so文件)的库名称(文件名称:“lib" +设置的名称)
hello
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).资源文件(C或C++)的相对位置
src/main/jni/NativeHelloJNI.cpp )
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
target_link_libraries( # Specifies the target library.将所有的add_library中的库链接起来,有多少个add_library成的库就将其添加到这里
hello #这个和add_library中的指定的so库名称一致
# Links the target library to the log library
# included in the NDK.
${log-lib} )
完善SayHello.class和MainActivity的代码:
package com.example.hellojni;
public class SayHello {
static {
System.loadLibrary("hello");
}
public static native String sayHello();
}
public class MainActivity extends AppCompatActivity {
public Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String str = SayHello.sayHello();
Toast.makeText(MainActivity.this,str, Toast.LENGTH_SHORT).show();
}
});
}
}
然后在jni目录下的cpp文件里实现这个方法,这个地方有两种实现方式:
1.在终端调用java和javah可执行文件,自动生成一个适配java层方法的.h文件,然后在cpp文件中实现方法。
2.直接在cpp文件中实现这个方法,我这里给出大致模板:
//
// Created by vashon on 2019/6/9.
//
#include "jni.h"
#ifndef _Included_com_example_hellojni_SayHello
#define _Included_com_example_hellojni_SayHello
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_test2_HelloWorld
* Method: sayHello
* Signature:
*/
JNIEXPORT jstring JNICALL Java_com_example_hellojni_SayHello_sayHello
(JNIEnv *env, jclass clasz){
return env->NewStringUTF("Hello From JNI!");
}
#ifdef __cplusplus
}
#endif
#endif
然后直接编译执行即可:
大致完成!代码已经上传仓库:https://github.com/Vashonisonly/JNI-Demo
需要说明一下的是:JNI有特定的语法,它的函数命名也有特定的规则,这些以后再补充说明吧!