Android SDK开发与使用的那些事儿
前言
最近由于工作需要,将应用里的部分功能独立了出来,封装成 SDK 提供给合作伙伴使用。由于经验不足,网上也没多少写这方面内容的文章,遇到了不少的坑,决定记录下来。
SDK
其实,刚说到要写SDK也有点慌,印象中SDK一直是个复杂的东西,脑海中浮现的是Java SDK ,Android SDK这类庞然大物。
SDK全称 Software Development Kit,广义上的 SDK 是为特定的软件包、软件框架、硬件平台、操作系统等建立应用程序时所使用的开发工具的集合,狭义上的 SDK 则是基于系统 SDK 进行开发包装的、新的、独立的、能够完成特定功能并返回相关数据的一组工具的集合。
听起来一愣一愣的,其实,将一些业务逻辑独立出来,打包成jar、so、aar,暴露一些APIs给外部调用,也可以称为SDK。如推送SDK,支付SDK,地图SDK...既然是所谓的集合,那么自然有大有小。
下面说说我在封装SDK与使用的时候遇到的那些事,希望对大家有些帮助吧!
一、二次打包aar
大多时候,我们的业务依赖于第三方库,载体可能为jar、so、aar,如果是jar包那好办,直接丢进libs目录下就可以了;so库就不简单了,不少开发商只提供少数abi的so库,这时就需要根据需求选择了,要么全部一份,要么只保留一个目录,否则就会报错;aar则是包含了代码、资源(图片、布局等)、so库等的集合。
那么需求来了,如何将第三方aar包二次封装,加入自己的业务逻辑再打包成一个aar呢?其实这个问题我也没有找到直接的解决方案,如果你有,请联系我,感激不尽!但是这个问题又是可以曲线解决的,aar其实就是个压缩包而已,如下图所示:

Android Studio导入aar时也是将其视为一个module(library),使用其中的classes以及其他资源文件,那我们可不可以直接将其解压,直接导入?这样就避免了在aar的基础上封装成aar!跳过这个坑?实践证明确实是可以的。如果你要封装的aar只包含了jar包和so库,那就简单了,解压出来分别导入项目相关目录即可!不然可能就要手动合并某些资源了...更新:详情请看 二次打包(封装)AAR实用指南
还是期待谷歌能给出一个傻瓜式的一键合并方案吧!
二、SDK中Application对象的初始化
有次SDK接入方反馈说某个地方崩溃了,一看Log,是调用Application对象中的方法空指针了。我一想,混淆?不是。导入姿势不对?不是。文档没认真看?也不是?Demo可以正常运行啊......随即想到是接入方自定义Application对象的问题。
如果aar中定义了Application,theme,icon,那么编译时就要抛出如下异常:

由于项目与aar都定义了自己的Application,编译器不知道用谁的,这就产生了上图的异常,按照提示,在Application标签下添加如下代码:
tools:replace="android:name"
合并方案可以参考官方文档:合并多个清单文件| Android Studio - Android Developers
理虽如此,但是你很大概率就掉坑了,这个方案直接将SDK中的Application对象替换为你的,换句话说就是SDK中的Application对象根本没有初始化,这就是上文说的空指针的罪魁祸首了!确实之前在写文档的时候没有考虑到自定义Application的情况,还是经验不足啊!甚至一度将Application里初始化的方法全部移出来,后来转念一想,让接入方继承我的Application不就OK了吗!!测试一波,赶紧更新下文档,不然又被吐槽了...这下理解为什么接入某些第三方SDK时,有的会要求继承SDK里定义的Application对象。
三、Application多继承
作为一个SDK提供方,假如你的SDK需要用户继承你的Application,我觉得应当提供一个Application多继承的解决方案,毕竟用户可能不仅仅只用你一个SDK,当有多个SDK有这个需求时就尴尬了。
java 多继承,这里的需求是继承两个类,并不是通过实现接口的方式“继承”多个接口上的方法声明。语言原生不支持,这样就比较麻烦了。解决办法如下:
通过接口实现 + 反射 的方式来创建代理Application对象,曲线实现Application的多继承,由于代码较多,这里就不贴源码了,解决方案:ApplicationProxyDemo 源码配合注释食用,风味更佳!
四、导入aar的两种方法
解决一:采用Android Studio新建module的方法,选择jar/aar即可。

解决二:使用gradle脚本直接导入:
- 在项目build.gradle文件内android{}标签中加入如下代码申明本地仓库:
repositories {
flatDir {
dirs 'libs'
}
}
}
- 然后将aar包放入libs目录(没有就在app目录下创建一个),随后加入dependencies :
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
...
compile(name: 'xxxxxx-xxxx', ext: 'aar') //name为aar文件全名
}
解决三:来自网友精彩评论:
implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
五、SDK中不可忽视的混淆问题
- 常规的避免混淆,比如一些第三方类库中的要求
- 避免混淆对外提供方法与数据实体的类,并且添加到接入方的proguard-rules.pro中。
最后
其实在最近的SDK开发与对接中遇到了不少问题,但是也学到了不少东西,由于缺少相关经验,也在不断的摸索之中。正所谓实战出真知,纸上谈兵容易,真刀真枪时就会暴露出一些问题,还是要多动手。当然了,技术都是业务驱动的。
后续更新见:Android SDK 开发纪要
Android SDK开发与使用的那些事儿的更多相关文章
- Android SDK 开发指南
Android SDK 开发指南 视频详解 以下视频是对融云 Android SDK 开发使用的详细讲解,您可以在阅读文档时配合学习. 更多视频教程如下: CSDN 融云 Android SDK ...
- 配置Android SDK 开发环境(转)
1. 下载Eclipse 在前面我们配置好了JDK环境后,就可以开始配置Android的集成开发环境了,官方Google推荐的集成开发环境为Eclipse,所以我们就以Eclipse作为集成开发环境. ...
- Android SDK 开发——发布使用踩坑之路
前言 在 Android 开发过程中,有些功能是通用的,或者是多个业务方都需要使用的. 为了统一功能逻辑及避免重复开发,因此将该功能开发成一个 SDK 是相当有必要的. 背景 刚好最近自己遇到了类似需 ...
- 基于虹软人证核验 2.0 Android SDK开发集成入门
一.功能介绍虹软人证核验 2.0 SDK(以下简称SDK)包含人脸检测.人脸跟踪.人证核验等能力,主要实现人证的1:1比对.其中暴露对外的功能方法有:active 引擎激活init 引擎初始化inpu ...
- Android SDK开发常用工具的使用及其异常处理
由于以下操作都是命令操作,所以在执行以下操作之前确保环境变量 ANDROID_HOME 指向的是正确的Android SDK的路径: 一.启动Android SDK Manager: android ...
- Google Android SDK开发范例------------20141119
一.Edit和Checkbox完成对登陆密码的查看:添加Edit的setOnCheckedChageListener和对CheckBox的状态通过isCHecked判断 大体代码如下 CheckBox ...
- android SDK开发 -- TitleBar封装(一)
假设app的title 统一的都是这种左中右结构的 代码如下 <LinearLayout xmlns:android="http://schemas.android.com/apk/r ...
- Google Android SDK开发范例大全笔记 二
网络设备管理相关相关 代码地址 1 WifiManager LocationManager分别控制 wifi及GPS WifiManager 判断网络状态 ,LocationManager判断定位状态 ...
- Google Android SDK开发范例大全笔记 一
方法讲解 1 获取手机分辨率方法 DisplayMetrics private void getDiaplayMetrics() { DisplayMetrics dm = new DisplayMe ...
随机推荐
- 并发编程>>四种实现方式(三)
概述 1.继承Thread 2.实现Runable接口 3.实现Callable接口通过FutureTask包装器来创建Thread线程 4.通过Executor框架实现多线程的结构化,即线程池实现. ...
- [JZOJ6088] [BZOJ5376] [loj #2463]【2018集训队互测Day 1】完美的旅行【线性递推】【多项式】【FWT】
Description Solution 我们考虑将问题一步步拆解 第一步求出\(F_{S,i}\)表示一次旅行按位与的值为S,走了i步的方案数. 第二步答案是\(F_{S,i}\)的二维重复卷积,记 ...
- Prufer序列与树的计数(坑)
\(prufer\)序列: 无根树转\(prufer\)序列: 不断找编号最小的叶子节点,删掉并在序列中加入他相连的节点. \(prufer\)转无根树: 找到在目前\(prufer\)序列中未出现且 ...
- Ngin 简单配置文件
#user nobody; worker_processes ; #error_log logs/error.log; #error_log logs/error.log notice; #error ...
- Spring Security OAuth 2开发者指南译
Spring Security OAuth 2开发者指南译 介绍 这是用户指南的支持OAuth 2.0.对于OAuth 1.0,一切都是不同的,所以看到它的用户指南. 本用户指南分为两部分,第一部分为 ...
- Java简单聊天室
实现Java简单的聊天室 所用主要知识:多线程+网络编程 效果如下图 /** * * @author Administrator * * 简单的多人聊天系统——重点:同时性,异步性 * 1.客户端:发 ...
- [作业] Python入门基础---九九乘法表
1.while 循环 : x = 1 while x < 10: y = 1 while y <=x: print('%d*%d=%2d' % (y,x,x*y),end = '\t') ...
- P2P 行业解决方案
P2P指个人与个人之间的借贷,而P2P理财是指以公司为中介机构,把这借贷双方对接起来实现各自的借贷需求.借款方可以是无抵押贷款或是有抵押贷款.而中介一般是收取双方或单方的手续费为盈利目的或者是赚取一定 ...
- javascript图形动画设计--以简单正弦波轨迹移动
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- Could not find gradle wrapper within android sdk
问题: IONIC 3.9.2 为ionic项目添加android platform后再build android时,出现如下提示: 问题原因: cordova-android在升级版本之后,从原来基 ...