Android SDK 开发纪要
一、前言
笔者在做Android SDK开发的过程中,也算从0到1,遇坑填坑了,今天分享的是在封装aar时遇到的那些坑,以及对SDK设计的改进等等。
二、配置清单
1、AndroidManifest
,若SDK在配置清单中申请权限,编译时就会报合并重复错误,只能去除主项目中原有的声明。因此,不建议在SDK内部声明,应改为在接入文档中说明,由主项目配置。
2、<application/>
标签,常见默认属性如:android:name
,android:theme
,android:lable
... 如无切实必要,请去除这些属性,避免打包时与主项目冲突。
三、Gradle文件
打包编译重命名,抽取aar+版本号自动重命名并复制到指定目录下
apply plugin: 'com.android.library'
static def releaseTime() {
return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}
android {
compileSdkVersion 25
buildToolsVersion '26.0.2'
defaultConfig {
minSdkVersion 19
targetSdkVersion 25
versionCode 6
versionName "5.1.0"
}
...
repositories {
flatDir {
dirs 'libs'
}
}
libraryVariants.all { variant ->
if (variant.buildType.name == 'release') {
variant.assemble.doLast {
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('release.aar')) {
def fileName = "${project.name}-release-${android.defaultConfig.versionName}-${releaseTime()}"
def outputPath = "/build/aar"
copy {
from outputFile
into outputPath
}
copy {
from outputFile
into outputPath
rename { fileName + ".aar" }
}
}
}
}
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
testImplementation 'junit:junit:4.12'
implementation 'com.android.support:appcompat-v7:25.4.0'
}
四、资源id命名规范
Values中的colors、strings、styles中的id命名应当注意保持一定的唯一性(如:命名统一加项目前缀),避免与主项目中的资源id冲突,造成SDK中的资源被覆盖,如theme、string等等。
当然,从另一个角度来看,这个特性也可以作为定制UI的一个思路,用主项目中定义的相同资源覆盖掉SDK中的资源属性,从而实现灵活改变SDK的样式。
五、避免创建Application对象
若SDK中定义了Application对象,而主项目也定义了Application或者应用了第三方Application,则需将android:name属性替换掉,才能正常编译,因为一个App只能指定一个Application,若直接替换,则会造成SDK中的Application无法初始化,引起一大波问题。
解决方案有二:
1、避免在SDK中创建Application对象,暴露出一个初始化方法,在主项目的Application相关方法如onCreate()
中注入相关参数执行;
2、若无法避免,则可指定主项目的Application继承自SDK中的内置Application,问题可以解决。
/**
* <pre>
* author : fdm
* time : 2018/03/09
* desc : SDK初始化
* version: 1.0
* </pre>
*/
public class MySDK {
private static Context sContext;
public MySDK() {
}
//提供给第三方调用,进行初始化
public static void initSDK(Context context) {
sContext = context;
initLog(context);
}
private static void initLog(Context context) {
new LogUtil.Builder(context)
.setLogSwitch(true)
.setGlobalTag("fdm")
.setLogHeadSwitch(true)
.setLogFilter(LogUtil.D);
}
public static Context getContext() {
return sContext;
}
}
六、无法将第三方库打包进aar的问题
library打包出来的 AAR ,不会将依赖的第三方库打包进去。这个问题也是由来已久,详情可见: Android Studio how to package single AAR from multiple library projects?
解决方案有两个:
1、将AAR发布到远程仓库,这样gradle依赖下来的时候就会自动依赖第三方库了。
2、在主项目中显式指定SDK中的第三方依赖包,如常见的gson、okhttp等等...
七、混淆问题
在Android开发中,我们一般都会对代码进行混淆后发布,所以在测试SDK时必须考虑到这个情况。
默认情况下,proguard-rules.pro
中的混淆配置是不会被打包进aar中的,所以一般需要在主项目中手动指定混淆规则。
但是,为了提高接入体验,能否将SDK中的混淆配置也打包进aar中,让项目自动配置SDK的混淆文件呢?答案是肯定的,我们可以指定consumerProguardFiles
属性,自定义引入的混淆规则,即可将*.pro
文件打包进入aar
中,项目打包时就会自动合并该配置文件。 值得一提的是该属性只镇对library有效,对app无效。
consumerProguardFiles
配置如下:
defaultConfig {
minSdkVersion 17
targetSdkVersion 26
versionCode 1
versionName "1.0"
consumerProguardFiles 'proguard-rules.pro'//一行代码解决SDK内部混淆问题
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
八、结语
今天的分享就到这里了,由于本人水平所限,内容难免错漏,欢迎批评指正!