两分钟学会Android平台NDK编程(无须Eclipse和cygwin,可使用命令行打包多个so)
版权声明:本文为博主原创文章,未经博主同意不得转载。 https://blog.csdn.net/wangbin_jxust/article/details/37389383
之前在进行cocos2dx开发时。已经具体介绍了怎样将win32的c++代码移植到Android平台。当再次回想时,发现一些基础的东西理解并非非常彻底。今天使用Android NDK提供的一个样例做一个简单的移植。
在进行该demo前。请确认你已经配置了Android开发环境和安装了最新的Android NDK。
1.创建Android项目
创建一个Android项目 , 包名是com.example.hellojni。创建一个Activity作为程序进入的Acitivity。命名为HelloJni。
2.创建 C 文件
创建一个C文件,放一个函数。该函数的作用是获取当前cpu架构并以字符串的形式返回。
请注意该函数的格式: Java_包名的下划线连接_Java文件名称_java函数名。
#include <string.h>
#include <jni.h>
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
#if defined(__arm__)
#if defined(__ARM_ARCH_7A__)
#if defined(__ARM_NEON__)
#define ABI "armeabi-v7a/NEON"
#else
#define ABI "armeabi-v7a"
#endif
#else
#define ABI "armeabi"
#endif
#elif defined(__i386__)
#define ABI "x86"
#elif defined(__mips__)
#define ABI "mips"
#else
#define ABI "unknown"
#endif
return (*env)->NewStringUTF(env, "Hello from JNI ! Compiled with ABI " ABI ".");
}
3.配置JNI
在该Android项目的根文件夹(即AndroidManifest.xml文件所在文件夹)下创建一个文件夹,命名为jni(注意,文件名称不能写错哦)
在jni文件夹下,创建Android.mk和Application.mk两个文件。同一时候将C文件也放进jni文件夹以下来。
例如以下:
这里的nick文件夹,能够先忽略不看。这是为后面的打包多个so准备的。
a.配置Android.mk文件
Android.mk文件实际上一个非常小的NDK构建脚本,它的语法在: NDK安装文件夹/docs/ANDROID-MK.html,下文代码也对一些基本属性加入了凝视。
#返回当前文件在系统中的路径,mk文件開始时必须定义该变量
LOCAL_PATH := $(call my-dir)
#CLEAR_VARS 变量由构建系统提供,由于有大量的全局变量,在本次构建前,清除上一次的
include $(CLEAR_VARS)
#LOCAL_MODULE 实际是项目名,用于区分各个项目。名字必须是唯一的并且不包括空格,终于的so库,命名也会是 lib项目名.so
LOCAL_MODULE := hello-jni
#要编译的c or cpp文件,注意不须要在这里列举头文件或者include的文件,构建系统会自己主动帮你依赖这些文件
LOCAL_SRC_FILES := hello-jni.c
#构建系统提供的变量
include $(BUILD_SHARED_LIBRARY)
b.配置Application.mk文件
Application.mk文件实际上是相应用程序本身描写叙述的文件,它定义了应用程序须要的功能模块的列表、针对不同cpu架构打包不同的so]、要构建release或者debug包等。
APP_ABI := XXX,这里的XXX就是指不同的平台,能够选填的有x86,armeabi,armeabi-v7a,mips,all,值得一提的是,选择all,则会构建出全部平台的so,假设不填该项,默认构建为armeabi的。同一时候。作者也做过一个实验,构建armeabi平台的so是能够执行在intel x86架构cpu平台的。可是构建x86平台的so则不能在armeabi平台上执行的。这样看来。应该是intel针对armeabi做了兼容,可是假设想要so
以最小的能耗执行在intel x86平台。还是要指定构建的so为x86平台。
4.打包so以及怎样打包多个so
在当前Android项目的根文件夹下,执行 NDK安装路径/ndk-build,则開始打包so。
另外,假设执行 NDK安装路径/ndk-build clean,会clean当前全部的so;
执行 NDK安装路径/ndk-build -B V=1,则强制又一次打包。
假设想要打包多个so。则能够在Android.mk定义多个modules。或者写多个Android.mk,每一个Android.mk定义一个modules,我这里在jni文件夹下又创建了一个nick文件夹,用于放置新的C文件。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ2Jpbl9qeHVzdA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
此时,仅仅须要修改jni文件夹下的Android.mk,再次对nick文件夹的C代码打包就可以。jni下的Android.mk文件:
#返回当前文件在系统中的路径,mk文件開始时必须定义该变量
LOCAL_PATH := $(call my-dir)
#CLEAR_VARS 变量由构建系统提供,由于有大量的全局变量,在本次构建前。清除上一次的
include $(CLEAR_VARS)
#LOCAL_MODULE 实际是项目名,用于区分各个项目,名字必须是唯一的并且不包括空格,终于的so库。命名也会是 lib项目名.so
LOCAL_MODULE := hello-jni
#要编译的c or cpp文件,注意不须要在这里列举头文件或者include的文件,构建系统会自己主动帮你依赖这些文件
LOCAL_SRC_FILES := hello-jni.c
#构建系统提供的变量
include $(BUILD_SHARED_LIBRARY)
#对nick文件夹下的代码打包so
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni-mine
LOCAL_SRC_FILES := nick/hello-jni.c
include $(BUILD_SHARED_LIBRARY)
是的,你没看错,又一次加上LOCAL_MODULE和LOCAL_SRC_FILES变量又一次配置一下就可以。
5.jni调用
在Activity中。我们使用static 关键词将载入so放在函数体中,以保证直接先载入so.
static {
System.loadLibrary("hello-jni");
}
要注意的是。System.loadLibrary()中填写的并非完整的so名。而是去掉前缀lib和后缀.so的。也就是Android.mk中的LOCAL_MODULE变量。
java层的函数要用native关键词声明这次调用native层的函数,假设该java函数是public native String XXXX(),那么在这里就是调用C代码中的Java_com_example_hellojni_HelloJni_stringFromJNI()函数。
以上就是Android平台打包so和调用的一个最主要的demo,事实上整个流程还是比較简单的,有一些规定的命名是不能随便修改的,假设jni文件夹名。Android.mk,Application.mk文件名称,被java层调用的C函数命名等,这些都是有规则的。
两分钟学会Android平台NDK编程(无须Eclipse和cygwin,可使用命令行打包多个so)的更多相关文章
- Android平台NDK编程
转自:http://blog.csdn.net/wangbin_jxust/article/details/37389383 之前在进行cocos2dx开发时,已经详细介绍了如何将win32的c++代 ...
- 【公众号系列】两分钟学会SAP F1技巧
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[公众号系列]两分钟学会SAP F1技巧 写 ...
- Android Studio NDK编程初探
继上一篇学习了如何使用NDK编译FFMPEG后,接下来就是要学习如何在Android Studio中使用了. 经过参考和一系列的摸索,记录下具体步骤. 创建C++ Support的Android St ...
- android 7.0 多渠道打包 - 美团开源工具Walle 命令行打包
在Android 7.0(Nougat)推出了新的应用签名方案APK Signature Scheme v2后,之前快速生成渠道包的方式(美团Android自动化之旅-生成渠道包)已经行不通了,对此美 ...
- 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---6
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下: <Linux命令行与shell脚本 ...
- 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---5
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下: <Linux命令行与shell脚本 ...
- 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---4
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下: <Linux命令行与shell脚本 ...
- 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---3
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下: <Linux命令行与shell脚本 ...
- 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---2
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下: <Linux命令行与shell脚本 ...
随机推荐
- 使用Bind读取配置到C#的实例
在之前的一篇二级域名绑定的文章<.Net Core 二级域名绑定到指定的控制器>中,有一个小的地方是关于读取Json文件的配置信息的,当时是用了读取文件流的方式,一直以来觉得该方法太Low ...
- MVVM模式的3种command总结[1]--DelegateCommand
MVVM模式的3种command总结[1]--DelegateCommand 查了不少资料,大概理清楚的就是有3种.当然类名可以自己取了,不过为了便于记忆和区分,还是和看到的文章里面用一样的类名. 1 ...
- Java集合详解6:TreeMap和红黑树
Java集合详解6:TreeMap和红黑树 初识TreeMap 之前的文章讲解了两种Map,分别是HashMap与LinkedHashMap,它们保证了以O(1)的时间复杂度进行增.删.改.查,从存储 ...
- 三十 Python分布式爬虫打造搜索引擎Scrapy精讲—将selenium操作谷歌浏览器集成到scrapy中
1.爬虫文件 dispatcher.connect()信号分发器,第一个参数信号触发函数,第二个参数是触发信号,signals.spider_closed是爬虫结束信号 # -*- coding: u ...
- MVC,MVVM,MVP等设计模式的分析
从Script到Code Blocks.Code Behind到MVC.MVP.MVVM 三个模式按照大致的历史进程将这些概念进行划分: Script Code Blocks.Code Behind ...
- VMware虚拟机创建安装之后不出现VMnet1和VMnet8虚拟网卡
大家可能遇到过安装虚拟机之后,不出现这两张虚拟网卡,造成一系列的网络问题 VMware虚拟机无法将网络改为桥接状态 本人亲试可行的解决办法 首先把你之前安装的VMware虚拟机卸载,清理得一干二净: ...
- 08day03
一.eclipse的使用 可能是全宇宙最好用的IDE debug 查看执行过程 查看源码 二.模块的常用方法 __name__ __file__ __doc__ 三.函数 参数 参数默认值 可变参数 ...
- 026——VUE中事件修饰符之使用$event与$prevent修饰符操作表单
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 【51nod-1010】因子只含有2 3 5的数
K的因子中只包含2 3 5.满足条件的前10个数是:2,3,4,5,6,8,9,10,12,15. 所有这样的K组成了一个序列S,现在给出一个数n,求S中 >= 给定数的最小的数. 例如:n = ...
- vue单独给页面设置body属性
因项目需求:用户个人详细信息页面设置背景色,之前在这个页面设置最外层div发现不行.因为app.vue影响了它.后来直接在页面上用body设置样式,发现影响了其他页面. 后来想了通过vue的生命周期来 ...