一、创建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#include 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 #includeclass 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#include #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()
项目源码