一、创建Native项目
1、新建 Native 项目
1)新建项目
选择最下面的 Native C++ 下一步即可
2)填写项目信息
3)选择C++版本可以直接选择默认
2、下载并配置NDK及CMake
1)进入Studio 设置 SDK 设置界面
这里选择需要的 NDK 和 CMake 版本进行下载。
2)加载 ndk
通过 File -> Project Structure 或 点击图标进入设置界面。
选择对应 ndk 版本。也可以在local.properties中直接添加 ndk 路径。
## This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Fri Jan 06 14:13:10 CST 2023
sdk.dir=/home/chen-xu-neu/Android/Sdk
ndk.dir=/home/chen-xu-neu/Android/Sdk/ndk/21.0.6113669
3、Native 项目结构
1)代码结构
主要就是再 main 下增加了 cpp 文件夹以及下面的文件,这部分代码主要用来生成 so 库中代码。
2)build.gradle(app)
android {
defaultConfig {
// 对应创建项目时选择的 C++ 版本
externalNativeBuild {
cmake {
cppFlags ''
// 生成so库类型
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}
}
}
// CMakeLists.txt 文件路径
externalNativeBuild {
cmake {
path file('src/main/cpp/CMakeLists.txt')
version '3.10.2'
}
}
}
3)CMakeLists.txt
# cmke版本
cmake_minimum_required(VERSION 3.10.2)
# 项目名称
project("nativetestdemo")
# 生成so库配置
add_library( # 设置库名称
native_xiaoxu
# 将库设置为共享库
SHARED
# 引入代码文件
native-lib.cpp)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
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)
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # 指定目标库
native_xiaoxu
# Links the target library to the log library
# included in the NDK.
${log-lib})
4)native-lib.cpp
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_wm_auto_nativetestdemo_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello XiaoXu";
return env->NewStringUTF(hello.c_str());
}
标准Native写法:Java_包名_类名_方法名
5)MainActivity
public class MainActivity extends AppCompatActivity {
// 加载so库,与上面生成的库名对应
static {
System.loadLibrary("native_xiaoxu");
}
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// Example of a call to a native method
TextView tv = binding.sampleText;
tv.setText(stringFromJNI());
}
/**
* 添加 native 方法
*/
public native String stringFromJNI();
}
这样整个项目就完成了,运行项目会输出“Hello XiaoXu”,在build/intermediates/cmake/debug/obj/下就会生成对应的so库。这样最原始的so库就生成完了。
4、代码优化
so库代码优化
在模块化开发及业务逻辑比较复杂时,将代码都写在 native-lib.cpp 中显然是不合理的,这就需要将代码抽取出来。
1)创建 .cpp 和 .h 文件
2)NativeImpl.h
#ifndef MYNATIVE_CLIENTIMPL_H
#define MYNATIVE_CLIENTIMPL_H
#include <vector>
class NativeImpl {
public:
NativeImpl();
virtual ~NativeImpl();
virtual char* getUserName();
};
#endif //MYNATIVE_CLIENTIMPL_H
3)NativeImpl.cpp
#include "NativeImpl.h"
NativeImpl::NativeImpl(){
}
NativeImpl::~NativeImpl(){
}
char* NativeImpl::getUserName(){
// 这里处理代码逻辑
return "XiaoXu";
}
4)CMakeLists.txt 增加 cpp 文件引入
add_library( # Sets the name of the library.
native_xiaoxu
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp
src/NativeImpl.cpp)
5)native-lib.cpp 增加对应方法
#include <jni.h>
#include <string>
#include "src/NativeImpl.h"
/* 获取NativeImpl */
NativeImpl nativeImpl;
NativeImpl* getNativeImpl(){
return &nativeImpl;
}
/* 将Activity方法提取到NativeImpl中 */
extern "C" JNIEXPORT jstring JNICALL
Java_com_wm_auto_nativetestdemo_NativeImpl_getUserName(
JNIEnv* env,
jclass clazz) {
char* c = getNativeImpl()->getUserName();
return env->NewStringUTF(c);
}
so库使用优化
1)将Activity方法提取到NativeImpl中
public class NativeImpl {
// 加载so库
static {
System.loadLibrary("native_xiaoxu");
}
/**
* 添加 native 方法
*/
public static native String getUserName();
}
2)Activity中使用
NativeImpl.getUserName()
项目源码