Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save coplas/05ee118d701324db55f5 to your computer and use it in GitHub Desktop.
Save coplas/05ee118d701324db55f5 to your computer and use it in GitHub Desktop.
import groovy.transform.Field
// This is a drop-in Gradle script that allows you to easily strip out the packages you don't need
// from the Google Play Services library. The script will keep track of previous runs to prevent
// restripping each time you build.
// HOW TO USE THIS
//
// 1) Download/copy this strip_google_play_services.gradle file into the same location of your app's
// build.gradle file.
//
// 2) In your app's build.gradle file, add the following underneath the Android application plugin
// declaration:
//
// apply plugin: 'com.android.application'
// apply from: 'strip_google_play_services.gradle' <--- ADD THIS
//
// 3) Tweak the packagesToStrip map to suit your needs. Set the boolean value to 'false' if you'd
// like the package to NOT be stripped.
//
// 4) Optional: Add or remove items from the additionalPackagesToStrip map. The current value in
// there does not have the same package prefix as the rest.
// NOTE: The packages list below are based on the Google Play Services package index found at the
// following location: http://developer.android.com/reference/gms-packages.html
// This list is current as of version 6.1.71.
//
// The 'common' package was not included in the list because its... well... common to all packages
// and cannot be removed.
// THANKS to Dario Marcato & Cedric Gatay for providing the starting point.
@Field packagesToStrip = [
'actions' : true,
'ads' : false,
'analytics' : true,
'appindexing' : true,
'appstate' : true,
'auth' : true,
'cast' : true,
'drive' : true,
'fitness' : true,
'games' : true,
'gcm' : true,
'identity' : true,
'location' : true,
'maps' : true,
'panorama' : true,
'plus' : true,
'security' : true,
'tagmanager' : true,
'wallet' : true,
'wearable' : true
]
@Field additionalPackagesToStrip = [
"com/google/ads/**"
]
@Field packageFormat = "com/google/android/gms/PACKAGE_NAME/**"
def toCamelCase(String string) {
String result = ""
string.findAll("[^\\W]+") { String word ->
result += word.capitalize()
}
return result
}
def getPackageListToExclude() {
def packageListToExclude = []
for (item in packagesToStrip) {
if (item.value == true) {
packageListToExclude.add(packageFormat.replaceFirst(/PACKAGE_NAME/, item.key))
}
}
if (additionalPackagesToStrip.size() > 0) {
packageListToExclude.addAll(additionalPackagesToStrip)
}
return packageListToExclude
}
afterEvaluate { project ->
Configuration runtimeConfiguration = project.configurations.getByName('compile')
println runtimeConfiguration
ResolutionResult resolution = runtimeConfiguration.incoming.resolutionResult
// Forces resolve of configuration
ModuleVersionIdentifier module = resolution.getAllComponents().find {
it.moduleVersion.name.equals("play-services")
}.moduleVersion
def playServicesLibName = toCamelCase("${module.group} ${module.name} ${module.version}")
String prepareTaskName = "prepare${playServicesLibName}Library"
File playServiceRootFolder = project.tasks.find { it.name.equals(prepareTaskName) }.explodedDir
def packageListToExclude = getPackageListToExclude()
def tmpDir = new File(project.buildDir, 'intermediates/tmp')
tmpDir.mkdirs()
def libFile = new File(tmpDir, "${playServicesLibName}.marker")
def strippedClassFileName = "${playServicesLibName}.jar"
def classesStrippedJar = new File(tmpDir, strippedClassFileName)
Task stripPlayServices = project.tasks.create(name: 'stripPlayServices', group: "Strip") {
inputs.files new File(playServiceRootFolder, "classes.jar")
outputs.dir playServiceRootFolder
description 'Strip useless packages from Google Play Services library to avoid reaching dex limit'
doLast {
def packageExcludesAsString = packageListToExclude.join(",")
if (libFile.exists()
&& libFile.text == packageExcludesAsString
&& classesStrippedJar.exists()){
println "Play services already stripped"
copy {
from(file(classesStrippedJar))
into(file(playServiceRootFolder))
rename { fileName ->
fileName = "classes.jar"
}
}
}else {
copy {
from(file(new File(playServiceRootFolder, "classes.jar")))
into(file(playServiceRootFolder))
rename { fileName ->
fileName = "classes_orig.jar"
}
}
tasks.create(name: "stripPlayServices" + module.version, type: Jar) {
destinationDir = playServiceRootFolder
archiveName = "classes.jar"
from(zipTree(new File(playServiceRootFolder, "classes_orig.jar"))) {
exclude packageListToExclude
}
}.execute()
delete file(new File(playServiceRootFolder, "classes_orig.jar"))
copy {
from(file(new File(playServiceRootFolder, "classes.jar")))
into(file(tmpDir))
rename { fileName ->
fileName = strippedClassFileName
}
}
libFile.text = packageExcludesAsString
}
}
}
project.tasks.findAll {
it.name.startsWith('prepare') && it.name.endsWith('Dependencies')
}.each { Task task ->
task.dependsOn stripPlayServices
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment