如何在Android Gradle中添加原生so文件依赖
2015-07-31 23:02
706 查看
@author ASCE1885的 Github 简书 微博 CSDN
原文链接
由于它使用到了原生C++代码,因此最终生成的文件除了Jars包还有so文件。
通过Maven仓库发布我们的函数库没有什么问题(只要你通过繁琐的发布流程),maven-android-plugin可以帮助我们包含共享库。Maven依赖规则使得我们可以指定想要获取的ABI(不同的CPU架构)的类型以及函数库的格式(我们的是.so格式)。
例如,为SnappyDB获取ARM平台共享库:
如果你使用的是Maven+Eclipse ADT来构建你的Android应用,使用这个方法没有问题,但如果你将工程迁移到Android Studio+Gradle上,问题就来了。
例如,在build.gradle文件中声明依赖:
但是当需要依赖原生函数库时就遇到问题了,类比于Maven,我们不再能够以下面这种方式来加载了:
这是因为Android Studio插件对于NDK的支持还做不到这一点。
这个特性很强大,不过开发者还是需要下载预先编译好的.so文件,并手动拷贝到这个目录中,当我们使用类似Jenkins或者Travis的持续集成系统时就显得不完美了。
已经有很多hacks技巧和解决方法尝试解决这个问题,但很多实际上很繁琐同时要求用户手动下载并拷贝这些原生函数库依赖。
因此,我们需要有更好的解决方案。
这个插件使用跟声明查找jar包一样的仓库,下面是一个例子:
group:name:version[:classifier]缩写
映射风格
在每种语法中,classifier都是可选的。这意味着,当忽略classifier时,插件将会尝试获取所有类型CPU架构(armeabi, armeabi-v7a, x86和mips)的artifacts。
我同时推荐另一个很棒的由Jake Wharton写的Gradle插件:android-sdk-manager,它可以帮助你下载和管理Android SDK。
文末摄影鉴赏
原文链接
背景
几个月前,基于Google的LevelDB,我为Android平台写了一个名为SnappyDB的键值数据库(NoSQL)。由于它使用到了原生C++代码,因此最终生成的文件除了Jars包还有so文件。
通过Maven仓库发布我们的函数库没有什么问题(只要你通过繁琐的发布流程),maven-android-plugin可以帮助我们包含共享库。Maven依赖规则使得我们可以指定想要获取的ABI(不同的CPU架构)的类型以及函数库的格式(我们的是.so格式)。
例如,为SnappyDB获取ARM平台共享库:
<dependency> <groupId>com.snappydb</groupId> <artifactId>snappydb-native</artifactId> <version>0.2.0</version> <classifier>armeabi</classifier> <type>so</type> </dependency>
如果你使用的是Maven+Eclipse ADT来构建你的Android应用,使用这个方法没有问题,但如果你将工程迁移到Android Studio+Gradle上,问题就来了。
Android Studio & Gradle
Android的Gradle插件能够很好的处理使用maven仓库的所有的jars依赖(以及其他)。例如,在build.gradle文件中声明依赖:
dependencies { classpath 'commons-io:commons-io:2.4' }
但是当需要依赖原生函数库时就遇到问题了,类比于Maven,我们不再能够以下面这种方式来加载了:
dependencies { classpath 'com.snappydb:snappydb-native:2.+:arm-v7a' }
这是因为Android Studio插件对于NDK的支持还做不到这一点。
jniLibs拯救了我们
在Android Studio的0.7.2版本的Android插件中,Google在工程的source sets中引入了一个新的目录‘jniLibs’。这意味着我们可以把预先编译好的.so文件拷贝到这个目录中,之后Android插件就会帮我们将这些原生函数库打包进APK中。. ├── AndroidManifest.xml └── jniLibs ├── armeabi │ └── libsnappydb-native.so ├── armeabi-v7a │ └── libsnappydb-native.so ├── mips │ └── libsnappydb-native.so └── x86 └── libsnappydb-native.so
这个特性很强大,不过开发者还是需要下载预先编译好的.so文件,并手动拷贝到这个目录中,当我们使用类似Jenkins或者Travis的持续集成系统时就显得不完美了。
已经有很多hacks技巧和解决方法尝试解决这个问题,但很多实际上很繁琐同时要求用户手动下载并拷贝这些原生函数库依赖。
因此,我们需要有更好的解决方案。
android-native-dependencies的引入
android-native-dependencies是我写的一个自动处理查找&下载&拷贝原生函数库依赖到jniLibs目录的Android插件,这样在APK构建过程中可以自动包含这些函数库。这个插件使用跟声明查找jar包一样的仓库,下面是一个例子:
buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.10.+' classpath 'com.nabilhachicha:android-native-dependencies:0.1' } } apply plugin: 'android' apply plugin: 'android-native-dependencies' native_dependencies { artifact 'com.snappydb:snappydb-native:0.2+:armeabi' artifact 'com.snappydb:snappydb-native:0.2+:x86' } dependencies { //regular Jar dependencies ... }
规约
DSL artifact遵循Maven artifacts的命名规则。因此,我们下面两种语法都可以使用:group:name:version[:classifier]缩写
//adding x86 classifier will resolve only intel's (.so) lib native_dependencies { artifact 'com.snappydb:snappydb-native:0.2+:x86' } //omit the classifier will resolve all supported architectures native_dependencies { artifact 'com.snappydb:snappydb-native:0.2+' }
映射风格
//adding x86 classifier will resolve only intel's (.so) lib native_dependencies { artifact group: 'com.snappydb', name: 'snappydb-native', version: '0.2+', classifier: 'x86' } //omit the classifier will resolve all supported architectures native_dependencies { artifact group: 'com.snappydb', name: 'snappydb-native', version: '0.2+' }
在每种语法中,classifier都是可选的。这意味着,当忽略classifier时,插件将会尝试获取所有类型CPU架构(armeabi, armeabi-v7a, x86和mips)的artifacts。
总结
在Android Gradle插件完全支持NDK之前,使用android-native-dependencies可以帮助我们构建CI和自动化原生依赖的重复性的任务。我同时推荐另一个很棒的由Jake Wharton写的Gradle插件:android-sdk-manager,它可以帮助你下载和管理Android SDK。
文末摄影鉴赏
![](http://image226-c.poco.cn/mypoco/myphoto/20140418/21/17361611220140418210603035.jpg?1024x683_120)
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories