1.新建一个Jni调用类
public class MyJni {
static {
System.loadLibrary("MyJni");
// System.load("/data/user/0/com.example.myapplication/app_libs/libMyJni.so");
// System.load("/storage/emulated/0/Android/data/com.example.myapplication/download/libMyJni.so");
// javah -jni -classpath E:\cdz\MyApplication2\app\build\intermediates\javac\debug\classes com.example.myapplication.MyJni
}
public native static String getString();
}
2.点击build-->make project
完成后会在app\build\intermediates\javac\debug\classes\com.example.myapplication\目录下生成一个MyJni.class文件
3.在main目录下新建一个jni文件夹
4.打开terminal:cd到jni目录下运行:
javah -jni -classpath E:\cdz\MyApplication2\app\build\intermediates\javac\debug\classes com.example.myapplication.MyJni
会在jni目录下生成一个com_example_myapplication_MyJni.h文件
5.新建一个test1.c文件
#include "jni.h"
#include "com_example_myapplication_MyJni.h"
#include
#include
#include
JNIEXPORT jstring JNICALL Java_com_example_myapplication_MyJni_getString
(JNIEnv *env, jclass jz){
/*手动加载指定位置的so动态库*/
void* handle = dlopen("/data/user/0/com.example.myapplication/app_libs/libMyAdd.so", RTLD_LAZY);
if (handle)
{
int (*add)(int a, int b);
/*根据动态链接库操作句柄与符号,返回符号对应的地址*/
add = dlsym(handle, "add");
int sum = add(7, 8);
printf("7+8 = %d\n", sum);
dlclose(handle);
return (*env)->NewStringUTF(env,"jni---->so---->so result=");
}else{
return (*env)->NewStringUTF(env, "open failed!");
}
}
6.新建一个Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MyJni
LOCAL_SRC_FILES := test1.c
include $(BUILD_SHARED_LIBRARY)
7.新建一个Application.mk文件
APP_CPPFLAGS += -fpermissive #兼容老的语法,使一些错误降为警告
APP_ABI := all
8.打开terminal cd到jni目录下 运行ndk-build命令生成libMyJni.so库
9.新建一个test2.c文件文件
int add( int x, int y)
{
return x + y;
}
10.修改Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MyAdd
LOCAL_SRC_FILES := test2.c
include $(BUILD_SHARED_LIBRARY)
11.打开terminal cd到jni目录下 运行ndk-build命令生成libMyAdd.so库
12.在工程的build.gradle文件中加入
sourceSets {
main() {
// jniLibs.srcDirs = ['src/main/libs']
// jni.srcDirs = [] //屏蔽掉默认的jni编译生成过程
jniLibs.srcDirs =['libs']
}
}
13.将生成的libMyAdd.so文件复制到/data/user/0/com.example.myapplication/app_libs/目录下
String path = LoadSoFileUtils.loadLibrary1(MainActivity.this, "/storage/emulated/0/C60/lib", "libMyAdd.so");
if (path!=null&&!"".equals(path)) {
LogUtils.e("so文件复制成功");
Log.e("cdz","result="+MyJni.getString());
}
public static String loadLibrary1(Context context, String libPath, String libName) {
File libs_dir = context.getDir("libs", Context.MODE_PRIVATE);
String new_file_name = libs_dir.getPath() + "/" + libName;
String old_file_name = libPath + "/" + libName;
if (!copyLibrary(new_file_name, old_file_name)) {
return "";
}else {
return new_file_name;
}
}
private static boolean copyLibrary(String new_file_name, String old_file_name) {
LogUtils.e("new file="+new_file_name);
FileInputStream fis = null;
FileOutputStream fos = null;
try {
File new_file = new File(new_file_name);
File old_file = new File(old_file_name);
if (new_file.exists()) new_file.delete();
fis = new FileInputStream(old_file);
fos = new FileOutputStream(new_file);
int dataSize;
byte[] dataBuffer = new byte[2048];
while ((dataSize = fis.read(dataBuffer)) != -1) {
fos.write(dataBuffer, 0, dataSize);
}
fos.flush();
return true;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fos != null) fos.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
if (fis != null) fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return false;
}
14.将生成的libMyJni.so文件复制到app/libs目录下
15.调用libMyJni.so 由于libMyJni.so调用了libMyadd.so所以必须先复制libMyAdd.so到相应目录下才能调用libMyAdd.so
String path = LoadSoFileUtils.loadLibrary1(MainActivity.this, "/storage/emulated/0/C60/lib", "libMyAdd.so");
if (path!=null&&!"".equals(path)) {
LogUtils.e("so文件复制成功");
Log.e("cdz","result="+MyJni.getString());
}