详细解读Android开发DNK开发将.c文件打包成os

简介: 详细解读Android开发DNK开发将.c文件打包成os

前言

  不废话太多,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 即可.

本文来自博客园,作者:观心静 ,转载请注明原文链接:

本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。

相关文章
|
1天前
|
安全 Android开发 iOS开发
探索安卓与iOS开发的差异:平台特性与用户体验的深度对比
在移动应用开发的广阔天地中,安卓和iOS两大平台各占半壁江山。本文旨在通过数据驱动的分析方法,深入探讨这两大操作系统在开发环境、用户界面设计及市场表现等方面的差异。引用最新的行业报告和科研数据,结合技术专家的观点,本文将提供对开发者和市场分析师均有价值的洞见。
|
1天前
|
编解码 开发工具 Android开发
技术心得:打造自己的智能投屏体验——Android投屏开发入门
技术心得:打造自己的智能投屏体验——Android投屏开发入门
|
2天前
|
缓存 测试技术 Shell
详细解读Android开发命令行完全攻略
详细解读Android开发命令行完全攻略
|
24天前
|
存储 Linux 数据处理
探索Linux操作系统的内核与文件系统
本文深入探讨了Linux操作系统的核心组件,包括其独特的内核结构和灵活的文件系统。文章首先概述了Linux内核的主要功能和架构,接着详细分析了文件系统的工作原理以及它如何支持数据存储和检索。通过比较不同的文件系统类型,本文旨在为读者提供一个关于如何根据特定需求选择合适文件系统的参考框架。
|
14天前
|
存储 缓存 安全
Linux基础——冯诺依曼体系结构与操作系统
Linux基础——冯诺依曼体系结构与操作系统
41 1
Linux基础——冯诺依曼体系结构与操作系统
|
10天前
|
Linux 网络安全 虚拟化
Linux操作系统第一章(Linux操作系统的带入,vmware-17虚拟化软件运用,FinalShell远程连接Linux )
Linux操作系统第一章(Linux操作系统的带入,vmware-17虚拟化软件运用,FinalShell远程连接Linux )
|
16天前
|
Linux API 云计算
探索Linux操作系统的模块化设计
【6月更文挑战第12天】本文深入探讨了Linux操作系统的模块化设计,揭示了其背后的技术原理与实践应用。通过分析Linux内核的模块化特性,我们了解到这一设计如何促进了系统的灵活性、可维护性以及安全性。文章将详细阐述模块加载机制、模块间的通信方式以及模块化给系统开发和维护带来的影响。
|
15天前
|
网络协议 Linux 数据安全/隐私保护
【Linux操作系统】权限管理和粘滞位
【Linux操作系统】权限管理和粘滞位
【Linux操作系统】权限管理和粘滞位
|
15天前
|
Linux
【Linux操作系统】基本指令-2
【Linux操作系统】基本指令
【Linux操作系统】基本指令-2
|
15天前
|
Ubuntu Unix 大数据
【Linux操作系统】历史与环境
【Linux操作系统】历史与环境
【Linux操作系统】历史与环境