Skip to content

Instantly share code, notes, and snippets.

@dmarcato
Last active December 21, 2022 10:10
Show Gist options
  • Save dmarcato/d7c91b94214acd936e42 to your computer and use it in GitHub Desktop.
Save dmarcato/d7c91b94214acd936e42 to your computer and use it in GitHub Desktop.
Gradle task to strip unused packages on Google Play Services library
def toCamelCase(String string) {
String result = ""
string.findAll("[^\\W]+") { String word ->
result += word.capitalize()
}
return result
}
afterEvaluate { project ->
Configuration runtimeConfiguration = project.configurations.getByName('compile')
ResolutionResult resolution = runtimeConfiguration.incoming.resolutionResult
// Forces resolve of configuration
ModuleVersionIdentifier module = resolution.getAllComponents().find { it.moduleVersion.name.equals("play-services") }.moduleVersion
String prepareTaskName = "prepare${toCamelCase("${module.group} ${module.name} ${module.version}")}Library"
File playServiceRootFolder = project.tasks.find { it.name.equals(prepareTaskName) }.explodedDir
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 {
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 "com/google/ads/**"
exclude "com/google/android/gms/analytics/**"
exclude "com/google/android/gms/games/**"
exclude "com/google/android/gms/plus/**"
exclude "com/google/android/gms/drive/**"
exclude "com/google/android/gms/ads/**"
}
}.execute()
delete file(new File(playServiceRootFolder, "classes_orig.jar"))
}
}
project.tasks.findAll { it.name.startsWith('prepare') && it.name.endsWith('Dependencies') }.each { Task task ->
task.dependsOn stripPlayServices
}
}
@AidenChoi
Copy link

If you don't want to use play services 6.5+ try this:

compile('com.google.android.gms:play-services:6.1.71') {
        exclude group: "com/google/ads/**"
        exclude group: "com/google/android/gms/analytics/**"
        exclude group: "com/google/android/gms/games/**"
        exclude group: "com/google/android/gms/maps/**"
        exclude group: "com/google/android/gms/panorama/**"
        exclude group: "com/google/android/gms/plus/**"
        exclude group: "com/google/android/gms/drive/**"
        exclude group: "com/google/android/gms/ads/**"
        exclude group: "com/google/android/gms/wallet/**"
        exclude group: "com/google/android/gms/wearable/**"
}

@jiahaoliuliu
Copy link

I am trying to get rid of the unused library for Google Play services 7.3 with the previous code but it does not work.

This is the code:

    compile ('com.google.android.gms:play-services:7.3.+') {
        exclude group: "com/google/ads/**"
        exclude group: "com/google/android/gms/ads/**"
        exclude group: "com/google/android/gms/analytics/**"
        exclude group: "com/google/android/gms/appindexing/**"
        exclude group: "com/google/android/gms/appinvite/**"
        exclude group: "com/google/android/gms/appstate/**"
        exclude group: "com/google/android/gms/cast/**"
        exclude group: "com/google/android/gms/drive/**"
        exclude group: "com/google/android/gms/fitness/**"
        exclude group: "com/google/android/gms/games/**"
        exclude group: "com/google/android/gms/identity/**"
        exclude group: "com/google/android/gms/location/**"
        exclude group: "com/google/android/gms/maps/**"
        exclude group: "com/google/android/gms/nearby/**"
        exclude group: "com/google/android/gms/panorama/**"
        exclude group: "com/google/android/gms/plus/**"
        exclude group: "com/google/android/gms/safetynet/**"
        exclude group: "com/google/android/gms/wallet/**"
        exclude group: "com/google/android/gms/wearable/**"
    }

And I still can see them in the console:

:app:prepareComGoogleAndroidGmsPlayServices730Library
:app:prepareComGoogleAndroidGmsPlayServicesAds730Library
:app:prepareComGoogleAndroidGmsPlayServicesAnalytics730Library
:app:prepareComGoogleAndroidGmsPlayServicesAppindexing730Library
:app:prepareComGoogleAndroidGmsPlayServicesAppinvite730Library
:app:prepareComGoogleAndroidGmsPlayServicesAppstate730Library
:app:prepareComGoogleAndroidGmsPlayServicesBase730Library
:app:prepareComGoogleAndroidGmsPlayServicesCast730Library
:app:prepareComGoogleAndroidGmsPlayServicesDrive730Library
:app:prepareComGoogleAndroidGmsPlayServicesFitness730Library
:app:prepareComGoogleAndroidGmsPlayServicesGames730Library
:app:prepareComGoogleAndroidGmsPlayServicesGcm730Library
:app:prepareComGoogleAndroidGmsPlayServicesIdentity730Library
:app:prepareComGoogleAndroidGmsPlayServicesLocation730Library
:app:prepareComGoogleAndroidGmsPlayServicesMaps730Library
:app:prepareComGoogleAndroidGmsPlayServicesNearby730Library
:app:prepareComGoogleAndroidGmsPlayServicesPanorama730Library
:app:prepareComGoogleAndroidGmsPlayServicesPlus730Library
:app:prepareComGoogleAndroidGmsPlayServicesSafetynet730Library
:app:prepareComGoogleAndroidGmsPlayServicesWallet730Library
:app:prepareComGoogleAndroidGmsPlayServicesWearable730Library

What am I doing wrong?

@cyberrob-zz
Copy link

As of Play service 8.3.0 you can selectively choose which individual library used in the app. So there's no need to exclude anymore.
https://developers.google.com/android/guides/setup#split

@andanicalik
Copy link

I paste it to the bottom of app's build.gradle file and it failed : "Cannot get property 'moduleVersion' on null object"
What should I do ?

@FTExplore
Copy link

Cannot get property 'moduleVersion' on null object. I got this problem and the sync failed....

@steewsc
Copy link

steewsc commented Jun 13, 2016

Cannot get property 'moduleVersion' on null object. I got this problem and the sync failed....

at
ModuleVersionIdentifier module = resolution.getAllComponents().find { it.moduleVersion.name.equals("play-services") }.moduleVersion

Happened to me to, so I printed it:
`

ModuleVersionIdentifier module = resolution.getAllComponents().find {
    System.out.println("MODULE NAME ====> " + it.moduleVersion.name);
    /*it.moduleVersion.name.equals("play-services")*/
}.moduleVersion

`
....
MODULE NAME ====> recyclerview-v7
MODULE NAME ====> core
MODULE NAME ====> gson
MODULE NAME ====> hirondelle-date4j
MODULE NAME ====> play-services-analytics
:app:preBuild
:jawampaLib:preBuild
....

As You can see, there is no "play-services", but "play-services-analytics" (in my case) :)

@androuis
Copy link

Same happens in my case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment