一. Android Studio --- 生成.so
step.1 新建空项目My Application
step.2 在local.properties添加ndk路径,并选择jdk版本
step.3 在 app\src\main 下创建文件夹jni
在jni下放入.c代码以及创建Android.mk 和 Application.mk文件,具体配置如下
如果是.cpp文件,Android.mk配置以下参考:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# 添加你的头文件目录
# LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
# 添加依赖库
LOCAL_LDLIBS := -lc++
# 生成.so的名称
LOCAL_MODULE := encode
# 用于封装的源文件
LOCAL_SRC_FILES := encode.cpp
include $(BUILD_SHARED_LIBRARY)
Application.mk配置如下参考:
step.4 把用于封装的源文件中的接口函数按jni格式修改
添加头文件
#include <jni.h>
上述为实现打印hello from C的接口函数代码示例,
Java_com_example_myapplication_MainActivity_helloC
Java _ 包名 _ 类名 _ 接口函数()
上述为实现encode的代码
***当封装的是Cpp文件时,接口函数需要加上extern "C"***
JNI格式ps:fopen函数中第一个路径参数必须为const char*,需要用
(*env)->GetStringUTFChars(env, originalfilePath, NULL)
或者
env->GetStringUTFChars(infilepath, NULL)
来将java string字符串转换为const char *,输出字符串同理,需要将字符串转化为java string
(*(*env)).NewStringUTF(env, "file open failed2")
env->NewStringUTF("outputFile open failed")
step.5 进行ndk-build cmd到jni目录下,运行ndk-build,会在main目录下生成libs文件夹,即生成的.so文件
二. Android Studio --- 调用.so
step.1 在build.gradle (:app) 中添加so库源路径
sourceSets {
main{
jniLibs.srcDirs 'src/main/libs'
}
}
step.2 在 java 下编写 java 文件进行调用
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.example.myapplication.R;
public class MainActivity extends AppCompatActivity {
//*********1.加载 so 库**********
static{
System.loadLibrary("encode"); //写入so库名称
//如果是编译的是cpp文件的话,可能需要链接一些C++中so库
//System.loadLibrary("c++_shared"); 链接的库也需要放入libs文件夹下
//参考路径 D:\SDK\ndk-bundle\sources\cxx-stl\llvm-libc++\libs
}
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 调用 C++ 函数并显示返回的字符串
String originalfilePath = "/storage/emulated/0/DCIM/1.bmp";
String outputfilePath="/storage/emulated/0/DCIM/output.bmp";
String plainfilePath = "asdxcnvvhdje";
String result = projectJNI(originalfilePath,outputfilePath,plainfilePath);
textView.setText(result);
}
});
}
上述为java调用libencode.so内的projectJNI()方法,实现encode过程,若成功返回字符串“success”给result,得到的结果如下图所示:
PS. 为了访问虚拟机内的文件,需要设置两个tip
tips1. 在 AndroidManifest.xml 中添加代码
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
tips2. 在虚拟机中设置安装app的Permission