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
}
}
@Hoermann
Copy link

Google released GooglePlayServicesLib 6.5 you can now only compile the parts of GooglePlayServices you need http://android-developers.blogspot.de/2014/11/google-play-services-65.html

@octa-george
Copy link

Starting with version 6.5, of Google Play services, you’ll be able to pick from a number of individual APIs, and you can see which ones have their own include files in the documentation. For example, if all you want to use is Maps, you would instead have:

  compile 'com.google.android.gms:play-services-maps:6.5.87'

Note that this will transitively include the ‘base’ libraries, which are used across all APIs. You can include them independently with the following line:

  compile 'com.google.android.gms:play-services-base:6.5.87'

http://android-developers.blogspot.de/2014/12/google-play-services-and-dex-method.html

Google Play services API Description in build.gradle
Google+ com.google.android.gms:play-services-plus:6.5.+
Google Account Login com.google.android.gms:play-services-identity:6.5.+
Google Activity Recognition com.google.android.gms:play-services-location:6.5.+
Google App Indexing com.google.android.gms:play-services-appindexing:6.5.+
Google Cast com.google.android.gms:play-services-cast:6.5.+
Google Drive com.google.android.gms:play-services-drive:6.5.+
Google Fit com.google.android.gms:play-services-fitness:6.5.+
Google Maps com.google.android.gms:play-services-maps:6.5.+
Google Mobile Ads com.google.android.gms:play-services-ads:6.5.+
Google Panorama Viewer com.google.android.gms:play-services-panorama:6.5.+
Google Play Game services com.google.android.gms:play-services-games:6.5.+
Google Wallet com.google.android.gms:play-services-wallet:6.5.+
Android Wear com.google.android.gms:play-services-wearable:6.5.+
Google Actions Google Analytics Google Cloud Messaging com.google.android.gms:play-services-base:6

@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