关于.so库
Android开发者使用的.so文件一般会有两种,一种是符合JNI标准的,就是方法以Java_包名_类名_方法名,Java可以调用;另一种是非JNI标准的,这种只能我们自己写JNI使用C/C++调用.so的库。
JNI标准.so库
生成libnative-lib.so文件的Java代码JNIUtils.java,包名为com.example.test
package com.example.test;
public class JNIUtils {
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public static native String stringFromJNI();
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
}
复制代码
在要引用libnative-lib.so的module的/src/main/java下创建目录com.example.test,并在该目录下创建文件JNIUtils.java,这里stringFromJNI()方法会报红,但不必创建对应的native-lib.cpp。
package com.example.test;
public class JNIUtils {
static {
System.loadLibrary("native-lib");
}
//方法要对应
public static native String stringFromJNI();
}
复制代码
在/src/main下创建目录jniLibs,并将libnative-lib.so文件添加到这里,
在Java代码中就可以直接调用方法import static com.example.test.JNIUtils.stringFromJNI;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = (TextView) findViewById(R.id.textview);
textView.setText(stringFromJNI());
}
}
复制代码
非JNI标准.so库
参考这篇,有源码的 如果使用非JNI标准的.so库,最好要有相应的.h头文件
配置.so文件存放位置,听说放在/app/libs比在/app/src/main/jniLibs好 build.gradle
sourceSets.main {
jniLibs.srcDirs = ['libs']
jni.srcDirs = []
}
复制代码
首先配置CMakeLists.txt文件,这里主要讲解下配置。先看下已经配置好的库文件:
# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.
cmake_minimum_required(VERSION 3.4.1)
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 )
#定位到.so文件目录
set(distribution_DIR ${CMAKE_SOURCE_DIR}/../../../../libs)
add_library( xxx-01
SHARED
IMPORTED )
set_target_properties( xxx-01
PROPERTIES IMPORTED_LOCATION
../../../../libs/${ANDROID_ABI}/libxxx-01.so )
add_library( xxx-02
SHARED
IMPORTED )
set_target_properties( xxx-02
PROPERTIES IMPORTED_LOCATION
../../../../libs/${ANDROID_ABI}/libxxx-02.so )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
add_library( native-lib
SHARED
src/main/cpp/native-lib.cpp )
include_directories(libs/include)
target_link_libraries( native-lib xxx-01 xxx-02
${log-lib} )
复制代码
cmake_minimum_required(VERSION 3.4.1):表示cmake的最低版本是3.4.1。 add_library():添加库,分为两种,一种是需要编译为库的代码,比如native-lib;一种是已经编译好的库文件,比如xxx-01,xxx-02。
这里用到的需要生成的.so文件
add_library( native-lib
SHARED
src/main/cpp/native-lib.cpp )
复制代码
最后的参数是源码的路径,如果有更多的源码就接下去写上。
add_library( xxx-01
SHARED
IMPORTED )
复制代码
这里xxx-01表示库的名称,SHARED表示是共享库,一般是.so文件;还有STATIC,一般是.a文件。IMPORTED表示引用的不是生成的。 set_target_properties:对于已经编译好的so文件需要引入,所以需要设置。
set_target_properties( xxx-01
PROPERTIES IMPORTED_LOCATION
../../../../libs/${ANDROID_ABI}/libxxx-01.so )
复制代码
这里xxx-01是名字,然后是PROPERTIES IMPORTED_LOCATION加上库的路径。 include_directories:一般外面引入的库文件需要头文件,所以可以通过这个来引入:
include_directories(libs/include)
复制代码
target_link_libraries:链接,把需要的so文件链接起来,这里native-lib需要链接ffmpeg的库文件。
最后看下和java,res同级的cpp目录下有native-lib.cpp文件,系统自动生成的。 首先是native-lib.cpp内容:
#include
#include
extern "C"
jstring
Java_com_example_MainActivity_stringFromJNI(
JNIEnv *env, jobject) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
复制代码
这里有一个函数Java_com_example_MainActivity_stringFromJNI,命名方式也可以知道,Java开头,com_example为包名,MainActivity是调用的java类,最后stringFromJNI是方法名。然后返回了hello from c++字符。 看下java的代码:
// Example of a call to a native method
TextView tv = (TextView) findViewById(R.id.sample_text);
tv.setText(avformatinfo());
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
// Used to load the 'native-lib' library on application startup.
static {
loadLibrary("native-lib");
}
复制代码
那么接下去就是第三方.so库的使用了。
根据需求修改jni部分的代码,也就是native-lib.cpp的代码,在这里调用第三方.so库中的C/C++方法,完成需要实现的功能。 以上就是简单的讲解调用.so库。