前言

  不废话太多,Java与C之间联系的JNI的概念,这个要了解可以参考下面这个博客:

  https://www.jianshu.com/p/87ce6f565d37

  此博客只说明如何将.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 <jni.h>
/* 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']
}
}
//需要添加的部分
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 即可.

Android 开发 DNK开发将.c文件打包成os的更多相关文章

  1. windows下如何将Python文件打包成.exe可执行文件

    在使用Python做开发的时候,时不时会给自己编写了一些小工具辅助自己的工作,但是由于开发依赖环境问题,多数只能在自己电脑上运行,拿到其它电脑后就没法运行了.这显得很不方便,不符合我们的初衷,那么有没 ...

  2. PyQt(Python+Qt)学习随笔:windows下使用pyinstaller将PyQt文件打包成exe可执行文件

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 在<windows下使用pyinstaller将多个目录的Pyt ...

  3. windows下使用pyinstaller将多个目录的Python文件打包成exe可执行文件

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.引言 需要将一个工程涉及两个目录的模块文件打包成exe,打包环境如 ...

  4. 把java文件打包成.jar (jar命令详解)

    把java文件打包成.jar (jar命令详解) 先打开命令提示符(win2000或在运行框里执行cmd命令,win98为DOS提示符),输入jar Chelp,然后回车(如果你盘上已经有了jdk1. ...

  5. 如何将class文件打包成jar 这里提供两种方式!

    原地址:http://blog.163.com/09zzy@126/blog/static/711976652011101001530/ 如何将class文件打包成jar文件,这是一个很严肃的问题,当 ...

  6. 使用Eclipse把java文件打包成jar 含有第三方jar库的jar包

    使用Eclipse把java文件打包成jar 含有第三方jar库的jar包   网上打包说用eclipse安装fat jar插件,但是貌似现在都不能用了,所以我只能按照eclipse自带的方法打包了. ...

  7. python的py文件打包成exe

    一.首先需要安装Pyinstaller-- 使用pip来安装模块 (我电脑上装的是python的一个编译环境Anaconda,如果电脑上装的是python自带的IDE的话,就直接进入python的安装 ...

  8. Ubuntu下将现有的文件打包成deb包

    转自:http://www.linuxidc.com/Linux/2008-04/12297.htm deb是Debian Linux的软件包格式.一般来说是需要通过编译源码然后制作deb包,今天由于 ...

  9. 如何把py文件打包成exe可执行文件

    如何把py文件打包成exe可执行文件 1.安装 pip install pyinstaller 或者 pip install -i https://pypi.douban.com/simple pyi ...

随机推荐

  1. 混合云存储组合拳:基于云存储网关与混合云备份的OSS数据备份方案

    前言 阿里云对象存储(OSS)用户众多.很多用户因为业务或者合规性需求,需要对OSS内的数据做备份,无论是线上备份,还是线下备份.用户可以选择使用OSS的开放API,按照业务需求,做数据的备份,也可以 ...

  2. duilib教程之duilib入门简明教程9.界面布局

    上一个教程实现的标题栏代码中,并没有看到处理自适应窗口大小的代码,但是窗口大小变化后,按钮的位置会跟着变化,这是因为我们将按钮放到了HorizontalLayout.VerticalLayout,这样 ...

  3. (转)Android中RelativeLayout各个属性的含义

    转:http://blog.csdn.net/softkexin/article/details/5933589 android:layout_above="@id/xxx"  - ...

  4. Linux课程---15、域名相关

    Linux课程---15.域名相关 一.总结 一句话总结: 先购买域名,再备案,再解析,域名即可使用 1.域名备案是怎么回事(比如二级域名,三级域名)? 每个二级域名需要备案一次,三级域名不需要备案, ...

  5. PHP实现对短信验证码发送次数的限制

    http://www.jb51.net/article/94878.htm 对用户获取短信验证码的手机号.ip.和浏览器(使用唯一标识)进行限制.本文介绍的方法是对用户每天只能通过同一浏览器或同一ip ...

  6. LightOJ-1138-Trailing Zeroes (III)-二分+求N!末尾0

    You task is to find minimal natural number N, so that N! contains exactly Q zeroes on the trail in d ...

  7. AtCoder ABC 129F Takahashi's Basics in Education and Learning

    题目链接:https://atcoder.jp/contests/abc129/tasks/abc129_f 题目大意 给定一个长度为 L ,首项为 A,公差为 B 的等差数列 S,将这 L 个数拼起 ...

  8. centos下 安装python相关

    centos 安装python相关 python3 https://blog.csdn.net/tanxiaob/article/details/78725301 yum -y install zli ...

  9. deployment资源

    目的:用rc在滚动升级之后,会造成服务访问中孤单,于是k8s引入了deploymentziyuan 创建deployment vim k8s_deploy.yml apiVersion: extens ...

  10. JVM 内存模型及垃圾回收

    java内存模型 根据 JVM 规范,JVM 内存共分为虚拟机栈.堆.方法区.程序计数器.本地方法栈五个部分. 程序计数器:程序计数器是指CPU中的寄存器,它保存的是程序当前执行的指令的地址(也可以说 ...