文档章节

Android 原生库依赖解析Gradle插件

l
 linsea
发布于 2016/11/11 15:36
字数 1518
阅读 50
收藏 0
点赞 0
评论 0

由于官方的Android Gradle插件无法解析在dependencies中声明的.so库依赖,所以编译时不会把.so文件自动拷贝到jniLibs目录下,这个插件主要就是为了解决这个问题的,并且提供so文件重命名和abi过滤的实用功能.
另外如果你是使用maven和android-maven-plugin 构建Android项目,并且项目里面有native依赖库的,如果现在想转移到Gradle构建系统上来,那么这个插件正好合适. 开源项目地址:https://github.com/linsea/native-dependencies-plugin

##使用说明 1. 引入插件

buildscript {
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
  }
  dependencies {
    classpath "gradle.plugin.com.github.linsea:native-dependencies-plugin:0.2.1"
  }
}

//在*主模块*项目中(比如APP项目中)应用插件,
//否则可能遇到Android官方插件中的这个BUG:https://code.google.com/p/android/issues/detail?id=158630
apply plugin: "com.github.linsea.native-dependencies"

2. 声明Native依赖库
Native依赖库的声明还是像通常一样写在dependencies里面,但要加上classifier和ext,比如:

dependencies {
    compile "org.ffmpeg:algorithm:1.2.3:armeabi-v7a@so"
}

如果你之前使用maven,应该明白这对应maven里面如下的声明:

<dependency>
    <groupId>org.ffmpeg</groupId>
    <artifactId>algorithm</artifactId>
    <version>1.2.3</version>
    <classifier>armeabi-v7a</classifier>
    <type>so</type>
</dependency>

3. 配置so文件的过滤与重命名规则
3.1 soFilters
在主模块的build.gradle文件中添加一个nativeso块,里面必须有一个soFilters属性,表示项目支持的平台架构种类, 通过这个属性区分so文件的类别属于哪个平台架构,以便拷贝时把相应类别的so文件放到jniLibs下面的相应目录中. 被依赖的so文件的文件名中必须包含这个类别标识符,比如所有armeabi-v7a平台的相应so文件,在仓库中文件的命名 必须包含有armeabi-v7a这个串,否则无法区别这个so文件到底是属于哪个平台的,也就无法拷贝.
3.2 renaming
通常Linux平台的so库文件有一定的命名规则,比如有lib前缀,但是有些开发者提供的库并没有按这些规则来命名,如果 命名与加载时没有对应起来,Android是加载不到so库的.如果APP中引用多个库,而命名又五花八门,为了能使我们把so库 拷贝到jniLibs下后Android可以加载到库,有时我们需要重命名so文件.
**renaming**就是定义命名规则的,一条renaming规则可以对应一个或多个so文件的命名,regex是以正则表达式的 方式匹配so文件名,如果匹配到任意一次,则so文件名不会再继续匹配下一条renaming规则. 重命名时可以定义 replaceAll或者replaceWith的方式,两者同时定义时, 仅replaceAll生效而忽略replaceWith. 以replaceAll方式重命名时,实际上是在so filename上执行String.replaceAll(regex,replaceAll). 而以replaceWith方式重命名时,则支持正则表达式的占位符($+数字表示)替换,功能更加强大,几乎可以满足所有命名需求. 具体可以参考Gradle文档中Copy的重命名.比如:

regex = '(.*)_OEM_BLUE_(.*)'
replaceWith = '$1$2'

prefix 表示so文件重命名后加入的前缀,一般需要lib前缀时可以配置这个.

注意
文件的重命名时,从上到下依次匹配规则,如果有一个匹配到了,则下面的规则会忽略跳过,如果最终一个规则都没有匹配到,则文件不会重命名.

以下是一个nativeso的配置示例及说明:

nativeso {

//.so filename MUST contains 'armeabi-v7a' or 'x86' to identify abi types
   soFilters = ['armeabi-v7a']     //['armeabi-v7a','x86']

//rename .so file: textsearch-1.2.3-armeabi-v7a.so -> libtextsearch.so
   renaming {
        prefix = 'lib'
        regex = 'textsearch-1.2.3-armeabi-v7a.*'
        replaceAll = 'textsearch' //not include ext .so
    }

//rename .so file: libhello-1.4.10-armeabi-v7a.so -> libhello.so
   renaming {
        regex = 'libhello(.*)'
        replaceWith = 'libhello'
    }

//rename .so file: libmysdk2-v7.0-armeabi-v7a.so -> libmysdk2.so
    renaming {
        regex = 'libmysdk(\\d+)-v(.*)'
        replaceWith = 'liblocSDK$1'
    }

//默认命名规则: name-version-armeabi-v7a.so -> libname.so
    renaming {
        prefix = 'lib'
        regex = '(.*)-([\\d\\.]+)-(.*)'
        replaceWith = '$1'
    }
}

##注意事项 插件会把so文件拷贝到jniLibs下对应的目录下,比如jniLibs/armeabi-v7a,而且会利用Gradle提供的缓存机制,提高编译速度,但是当依赖更新而过期时,需要重新下载并拷贝,在拷贝之前,插件会清空jniLibs目录.因此如果你的主模块项目已经包含了一些native依赖,并且.so文件已经放到jniLibs下的对应目录下,那么插件会同时把这些so文件也删除.为了避免这种情况发生,需要增加一个单独 的jniLibs目录给插件使用,比如:

android {
    sourceSets {
        main {
            //...
            jniLibs.srcDirs += 'src/main/nativeso' //一定要加在数组的最后
        }
    }

##使用技巧 1.插件增加了一个名为collectso的Task,并且利用了gradle的增量编译机制,如果文件是新的,Task不会重复执行.如果重命名时需要调试脚本,可以运行以下命令:

./gradlew -q --rerun-tasks collectso --info

查看插件的输出日志和重命名后的文件名,以便帮助定义重命名规则.

2.通常,如果你的APP仅支持有限的几种ABI,则其他所有不支持的ABI的so文件应该在APK打包中排除掉,否则在某些机型中无法加载 对应ABI上缺失的so,在android plugin 2.2及以上版本可以通过如下配置达到效果:

android {
    packagingOptions { //假设你的APP仅支持armeabi-v7a架构,则其他的所有架构的so需要排除之
        exclude '/lib/armeabi/**'
        exclude '/lib/arm64-v8a/**'
        exclude '/lib/x86/**'
        exclude '/lib/x86_64/**'
        exclude '/lib/mips/**'
        exclude '/lib/mips64/**'
    }
}

© 著作权归作者所有

共有 人打赏支持
l
粉丝 4
博文 11
码字总数 10693
作品 0
广州
技术主管
Android JNI学习(二)——实战JNI之“hello world”

本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Native相互调用 Android JNI学习(四)——JNI的常用方法...

隔壁老李头
05/09
0
0
Android Studio 升级到3.0后的gradle迁移(bing译文)

首先推荐按照官方版进行,如有疑问,评论中讨论; 官方步骤Migrate to Android Plugin for Gradle 3.0.0 英文水平高的可直接点击链接查看原文,以防翻译出错; Gradle 3.0.0 的 Android 插件...

我家有宝
2017/10/27
0
0
bulid.gradle 解析

外层的bulid.gradle文件 两处的repositories的闭包中都声明了jcenter() 这行配置。 jcenter是一个代码托管仓库,很多Androdi开源项目都会选择将代码托管到jcenter上,声明了这个配置之后,可...

Jerry_0221
06/12
0
0
【译】Gradle 的依赖关系处理不当,可能导致你编译异常

文章 | Ashesh Bharadwaj 翻译 | 承香墨影 授权 承香墨影 翻译、编辑并发布 在 Android Studio 中,Gradle 构建过程对于开发者来说,很大程度上是抽象的。作为一个新的 Android 开发者,我们...

承香墨影
04/03
0
0
Android studio gradle配置

Gradle 基本概念 首先我们学习几个gradle 的脚本语法,掌握了这几个语法,你就能非常简单的用gradle构建打包android项目了。 首先,我们来看下一个最简单android 。 build.gradle //设置脚本...

习惯_搬砖
2014/11/07
0
1
读书笔记--Android Gradle权威指南(下)

前言 最近看了一本书《Android Gradle 权威指南》,收获挺多,就想着来记录一些读书笔记,方便后续查阅。 本篇内容是基于上一篇:读书笔记--Android Gradle权威指南(上) 上一篇中我们讲了:...

请叫我大苏
05/27
0
0
迁移到 Android Gradle Plugin 3.0 | 中文教学视频

我们随 Android Studio 3.0 版本一起发布了 3.0 版的 Android Gradle 插件。此插件基于新的 Gradle API,支持变量感知依赖项解析,并且显著地加快多模块构建的速度。在切换到新插件版本时,您...

Android_开发者
04/18
0
0
android 如何引入gradle 插件源码

参考: 1,Android Gradle Plugin解析 2,Android Gradle Plugin 源码阅读与编译 方法步骤: 1,专门建立一个gradle 插件module。 建立一个 android lmodule。 删除src/main/下的所有文件 在src...

Carlyle_Lee
07/14
0
0
寄Android开发Gradle你需要知道的知识

初识Gradle Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具。它使用一种基于Groovy的特定领域语言来声明项目设置,而不是传统的XML。当前其支持的语言限于Java、Groovy和...

猴亮屏
05/22
0
0
安卓开发经验分享:资源、UI、函数库、测试、构建一个都不能少

除了高超的武艺,每位黑忍者还需要装备最好的武器。在软件开发的世界里,好的工具能让我们的生活变得更轻松,在更短的时间里写出更棒的代码。 时光回到2008年,那时安卓还很年轻。只有几个相...

拉偶有所依
2015/02/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

DUBBO 详细介绍

摘要: 主要核心部件: Remoting: 网络通信框架,实现了 sync-over-async 和 request-response 消息机制. RPC: 一个远程过程调用的抽象,支持负载均衡、容灾和集群功能 Registry: 服务目录框架...

明理萝
17分钟前
0
1
4 个快速的 Python 编译器 for 2018

简评:Python 和其他的解释型语言一样经常被吐槽性能不行,所以开发人员为了提升性能创建了不少编译器,本文则选取其中的四个做了基准测试。 Python 其实是一种相当快的语言,但它并不像编译...

极光推送
20分钟前
0
0
spring boot注册多个MQ服务器的问题

关于注册到多个MQ源的文章已经有很多了,这里记录一下声明queue的坑; 如果使用注册bean的方式声明queue,会导致声明的queue同时被注册到所有的MQ源上; //如果使用下面的声明方式,que...

placeholder
21分钟前
0
0
Java面试基础篇——第九篇:BIO,NIO,AIO的区别

现在IO模型主要分三类:BIO(同步阻塞IO),NIO(同步非阻塞IO),AIO()。 先来看看BIO。 1. BIO 服务端接受到请求后,要指派或新建一个线程去处理客户端的IO请求,直到收到断开连接的指令。这么做...

developlee的潇洒人生
26分钟前
0
0
@RequestMapping @ResponseBody 和 @RequestBody 用法与区别

1.@RequestMapping 国际惯例先介绍什么是@RequestMapping,@RequestMapping 是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为...

特拉仔
28分钟前
1
0
基于 HTML5 结合互联网+ 的 3D 隧道

前言 目前,物资采购和人力成本是隧道业发展的两大瓶颈。比如依靠民间借贷,融资成本很高;采购价格不透明,没有增值税发票;还有项目管控和供应链管理的问题。成本在不断上升,利润在不断下...

xhload3d
30分钟前
0
0
济南小程序热度分析

原文链接:http://www.jnqianle.cn/company/2072.html

tianma3798
31分钟前
1
0
大数据软件

beats 采集 kafka spark hive es grafana zeppelin

ArlenXu
33分钟前
0
0
Mac item2常用快捷键

标签 新建标签:command + t 关闭标签:command + w 切换标签:command + 数字 command + 左右方向键 切换全屏:command + enter 查找:command + f 分屏 水平分屏:command + d 垂直分屏:c...

说回答
36分钟前
0
0
mac常用软件

1.excel for mac http://www.pc6.com/mac/114205.html

小黑202
36分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部