一、SO库是什么?
SO(Shared Object)库是一种动态库,它可以在程序运行时被动态地加载到内存中,并提供给应用程序使用。SO库通常使用C/C++编写,并且被编译成二进制可执行文件。SO库可以提供一些应用程序需要访问的功能,比如图形库、音频库等等。
在Android开发中,使用SO库可以使应用程序更加紧凑,同时还能提供更高的性能。通过使用SO库,可以将一些常用的、底层的功能模块封装成库的形式,供应用程序动态链接,并使用其中的功能,这可以降低应用程序本身的大小,同时提高代码的复用性。
二、如何使用SO库?
在Android中,可以使用Java Native Interface(JNI)实现Java代码与C/C++函数库之间的调用。JNI可以将Java代码编译为Native代码,并与Native库进行交互。下面是一个使用SO库的Java代码示例:
public class MyNativeLib { static { System.loadLibrary("my-lib"); // 加载名为"my-lib"的SO库 } public native void nativeMethod(); // 声明Native方法 }
上面的代码中,静态块中使用System.loadLibrary()方法加载名为"my-lib"的SO库。在Java中声明了nativeMethod()本地方法,这个方法实际上是在SO库中实现的,Java运行时会通过JNI来调用SO库中的函数。
三、SO库的优势和劣势?
优势:
- 高性能:SO库编译成机器码,因此更加高效,能够提供更高的性能。
- 代码重用:将一些底层的功能模块封装成SO库,可以在多个应用程序中重复使用。
- 动态加载:SO库能够被动态地加载到内存中,因此可以在需要时再加载,可以节省内存资源。
劣势:
- 编译难度:编写C/C++代码的难度相对Java较大,编译过程也较为繁琐。
- 兼容性问题:不同的CPU架构可能需要不同的SO库,同时不同的Android版本也可能会有兼容性问题。
四、SO库的注意事项?
在使用SO库时,还需要注意以下几点:
- SO库只能包含C/C++代码,不能包含Java代码
- SO库编译需要使用对应CPU架构的编译器,比如armeabi-v7a架构需要使用armv7a编译器,则编译的SO库也需要以这个架构为目标
- 在使用SO库时,需要确保SO库的兼容性,避免出现兼容性问题
- 在动态加载SO库时,需要确保SO库已经被正确地安装到设备上
最后,展示一下使用Android Studio编写C/C++代码和编译SO库的示例:
1. 创建Native库
在Android Studio中,可以通过创建"C/C++"类型的Android工程,来创建Native库。具体步骤如下:
- 选择"File"->"New"->"New Module...",在弹出的窗口中选择"C/C++"->"JNI/Library"。
- 在下一步中,可以指定项目的名称、创建的Native库的名称等信息。
- 创建完成后,在项目的"app/src/main"下会生成一个命名为"java"和"jni"的文件夹。
2. 编写Native代码
在"jni"文件夹下可以创建一个"native_lib.c"文件,并编写C代码。例如,下面的代码将实现从Java代码调用的Native方法:
#includeJNIEXPORT jstring JNICALL Java_com_example_mytestproject_MainActivity_stringFromJNI( JNIEnv *env, jobject obj) { return (*env)->NewStringUTF(env, "Hello from native code!"); }
3. 编写CMake配置文件
在"app/src/main/cpp"下创建一个CMake文件,指定编译配置等信息。例如,下面的CMake文件将创建一个名为"native-lib"的SO库,并将"native_lib.c"文件中的函数打包到该SO库中:
cmake_minimum_required(VERSION 3.4.1) add_library( # Sets the name of the library. native-lib # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). native_lib.c ) # Searches for a specified prebuilt library and stores the path as a # variable. Because system libraries are included 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 the # same build directory. If the imported library has dependencies or # transitive dependencies, they are automatically added to the link # command. target_link_libraries( # Specifies the target library. native-lib # Links the target library to the log library # included in the NDK. ${log-lib} )
4. 构建Native库
在Gradle Script中的"build.gradle(Module:app)"文件下,添加如下配置,通过Sync Now来同步更新:
externalNativeBuild { cmake { path "src/main/cpp/CMakeLists.txt" } }
然后,执行Build->Make Module 'app',即可生成SO库文件。