前言
不废话太多,Java与C之间联系的JNI的概念,这个要了解可以参考下面这个博客:
此博客只说明如何将.C文件通过NDK打包成so库并且使用的一个简单demo.
第一步 创建用于引用本地os库的Java工具类
目录
工具类代码
package zq.ndkdemo;
public class NDKTools {
static {
System.loadLibrary("ndkdemomk-jni");//这里的"ndkdemomk-jni"是下面.mk文件里局部模块的值,这个到后面我会解释
}
public static native String getNDKcontent();//您在Java里调用so库的静态方法
}
第二步 将Java工具类打包成.h文件
打开Android studio的Terminal准备用javah打包.h文件, cd进入到app/src/目录下 然后输入 javah -o ndkdemoHFile.h -jni -classpath ./main/java/ zq.ndkdemo.NDKTools 命令.(下面会解释这条命令)
解释一下这行命令
javah -o ndkdemoHFile.h -jni -classpath ./main/java/ zq.ndkdemo.NDKTools
javah -o 你要打包的.h文件名加后缀 -jni -classpath 中间的路径 app包名+工具类名
输入这条命令后,如果没报错,你就会在src目录下获得您的.h文件,如下图:
打开.h可以看到:
/ DO NOT EDIT THIS FILE - it is machine generated /
#include
/ Header for class zq_ndkdemo_NDKTools /
#ifndef _Included_zq_ndkdemo_NDKTools
#define _Included_zq_ndkdemo_NDKTools
#ifdef cplusplus
extern "C" {
#endif
/
Class: zq_ndkdemo_NDKTools
Method: getNDKcontent
Signature: ()Ljava/lang/String;
/
JNIEXPORT jstring JNICALL Java_zq_ndkdemo_NDKTools_getNDKcontent
(JNIEnv , jclass);
#ifdef cplusplus
}
#endif
#endif
第三步 创建jni文件夹并且将.h文件移入
在main目录下创建一个jni文件夹
将我们打包好的.h文件移动到jni文件夹里
第四步 创建c语言函数文件
进入到jni文件夹里,点击创建任意名称加.c后缀的文件
打开写入代码如下:
#include "ndkdemoHFile.h"
JNIEXPORT jstring JNICALL Java_zq_ndkdemo_NDKTools_getNDKcontent
(JNIEnv env, jobject obj){
return (env)->NewStringUTF(env,"Hellow World,这是NDK的第一行代码");
}
注意!代码里最好别写注释特别是中文注释.
#include "ndkdemoHFile.h"
这行代码引用的就是.h文件名称
JNIEXPORT jstring JNICALL Java_zq_ndkdemo_NDKTools_getNDKcontent
这行代码中 jstring 为返回值
Java_zq_ndkdemo_NDKTools_getNDKcontent 为 Java + 路径 + 类名 + 方法名称
第五步 创建.mk文件
在jni目录下创建一个叫Android.mk的文件
内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ndkdemomk-jni
LOCAL_SRC_FILES := ndkdemoCFile.c
include $(BUILD_SHARED_LIBRARY)
LOCAL_PATH := $(call my-dir):
每个Android.mk文件必须以定义开始。它用于在开发tree中查找源文件。宏my-dir则由Build System 提供。返回包含Android.mk目录路径。
include $(CLEAR_VARS) :
CLEAR_VARS变量由Build System提供。并指向一个指定的GNU Makefile,由它负责清理很多LOCAL_xxx。例如LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_STATIC_LIBRARIES等等。但不是清理LOCAL_PATH。这个清理是必须的,因为所有的编译控制文件由同一个GNU Make解析和执行,其变量是全局的。所以清理后才能便面相互影响。
LOCAL_MODULE := ndkdemomk-jni:
LOCAL_MODULE模块必须定义,以表示Android.mk中的每一个模块。名字必须唯一且不包含空格。Build System 会自动添加适当的前缀和后缀。例如,demo,要生成动态库,则生成libdemo.so。但请注意:如果模块名字被定义为libabd,则生成libabc.so。不再添加前缀。另外我们一开始写的Java工具类里的System.loadLibrary("ndkdemomk-jni"); 就是这个值
OCAL_SRC_FILES := ndkdemCFile.c:
这行代码表示将要打包的C/C++源码。不必列出头文件,build System 会自动帮我们找出依赖文件。缺省的C++ 源码的扩展名为.cpp。
include $(BUILD_SHARED_LIBRARY):
BUILD_SHARED_LIBRARY是Build System提供的一个变量,指向一个GUN Makefile Script。它负责收集自从上次调用include $(CLEAR_VARS)后的所有LOCAL_xxxxinx。并决定编译什么类型
BUILD_STATIC_LIBRARY:编译为静态库
BUILD_SHARED_LIBRARY:编译为动态库
BUILD_EXECUTABLE:编译为Native C 可执行程序
BUILD_PREBUILT:该模块已经预先编译
第六步 在build.gradle文件里添加部分代码
android {
compileSdkVersion 28
defaultConfig {
applicationId "zq.ndkdemo"
minSdkVersion 27
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
//需要添加的部分
ndk{
moduleName "ndkdemo-jni"
abiFilters "armeabi-v7a", "x86"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
//需要添加的部分
externalNativeBuild {
ndkBuild {
path 'src/main/jni/Android.mk'
}
}
//需要添加的部分
sourceSets.main {
jni.srcDirs = 【】
jniLibs.srcDirs = 【'src/main/jniLibs'】
}
}//代码效果参考:http://www.ezhiqi.com/zx/art_7908.html
//需要添加的部分
sourceSets{
main {
jni.srcDirs = 【】
}
}
}
第七步 检查Android studio是否已经下载配置过ndk
点击local.properties打开
查看是否有ndk
ndk.dir=/media/E/tools/SDK/androidsdklinux/ndk-bundle
sdk.dir=/media/E/tools/SDK/androidsdklinux
如果没有就需要进入到File ] Settings 里下载ndk
第八步 编译SO文件
在Android studio的工具栏里,点击Build ] clean Project 先清理一下之前的编译
在点击Build ] Rebuild Project 重新创建编译文件
然后可以打开下图所示路径,就可以看到我们的so文件了
第九步 调用工具类方法,run APP
public class MainActivity extends AppCompatActivity {
private TextView mDemoText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDemoText = findViewById(R.id.demo_text);
String content = NDKTools.getNDKcontent();
mDemoText.setText(content);
}
}
运行APP 即可.
本文来自博客园,作者:观心静 ,转载请注明原文链接:
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。