Android : Play Service 6.5.+ granular dependencies not working correctly

on Wednesday, April 1, 2015


I'm working on a project which uses the location, gcm, ads and identity components of Google Play Services (version 7.0.0).


I've defined them as such in the build.gradle of the app module:



compile 'com.google.android.gms:play-services-location:7.0.0'
compile 'com.google.android.gms:play-services-ads:7.0.0'
compile 'com.google.android.gms:play-services-identity:7.0.0'
compile 'com.google.android.gms:play-services-gcm:7.0.0


NOTE: Don't know if it's relevant (I don't expect it to be), but the project also includes two additional library modules, each of which declares a subset of the above as dependencies:



compile 'com.google.android.gms:play-services-location:7.0.0'
compile 'com.google.android.gms:play-services-ads:7.0.0'
compile 'com.google.android.gms:play-services-identity:7.0.0'


Still, after trying to build the app, the dexing fails due to overstepping of the 64k method count limit. I was a bit suspicious of this, since before the fine folk at Google introduced granular dependency management, I used another, more crude approach, by manually stripping away packages from the play services jar in a gradle build task. This worked fine, and the 64k method limit was not overstepped.


So now, I begrudgingly introduced multi-dex into the project, was finally able to build an .apk, and take a look at the method count by package, using the dex-method-counts command line tool, which was brought to my attention in a post by Jake Wharton concerning the unwieldiness of the Play Services monolith.


These are the results:



google: 18687
ads: 127
mediation: 96
admob: 23
customevent: 41
android: 11873
gms: 11873
actions: 4
ads: 387
doubleclick: 84
identifier: 22
mediation: 75
admob: 2
customevent: 48
purchase: 16
search: 81
analytics: 656
ecommerce: 34
auth: 78
common: 1611
api: 409
data: 141
images: 100
internal: 580
safeparcel: 76
dynamic: 213
gcm: 35
identity: 86
intents: 75
model: 41
internal: 4914
location: 516
places: 232
ui: 7
maps: 2395
internal: 822
model: 1020
internal: 505
security: 12
tagmanager: 955
common: 5798
annotations: 3
base: 558
internal: 11
collect: 4195
io: 299
net: 72
primitives: 383
util: 288
concurrent: 288
gson: 889
annotations: 5
internal: 485
bind: 284
reflect: 18
stream: 102


TL;DR The Play Services are listed as having over 18k methods, and also seem to include some components that I never defined as dependencies in build.gradle (e.g. maps).


So then, I dexed the components I use, one by one, straight from android-sdk-linux/extras/google/m2repository/com/google/android/gms/play-services-<component_name>, using the approach from Jake Wharton's article referenced above.


The results are as follows:



Base:

Read in 3592 method IDs.
<root>: 3592
: 6
android: 420
accounts: 5
app: 62
content: 71
pm: 12
res: 9
database: 21
graphics: 42
drawable: 21
net: 11
os: 102
support: 56
v4: 56
app: 45
content: 4
util: 7
text: 1
util: 22
view: 4
widget: 23
com: 2831
google: 2831
android: 2831
gms: 2831
actions: 4
auth: 78
common: 1611
api: 409
data: 141
images: 100
internal: 580
safeparcel: 76
dynamic: 213
internal: 913
security: 12
java: 324
io: 25
lang: 143
ref: 2
reflect: 13
math: 2
nio: 17
util: 137
concurrent: 26
atomic: 4
locks: 7
regex: 6
org: 11
json: 11
Overall method count: 3592

---

Location:

Read in 1554 method IDs.
<root>: 1554
android: 65
app: 1
content: 13
location: 3
net: 1
os: 41
text: 1
util: 5
com: 1417
google: 1417
android: 1417
gms: 1417
common: 75
api: 13
data: 8
internal: 53
safeparcel: 36
internal: 833
location: 505
places: 232
ui: 7
maps: 4
model: 4
java: 72
lang: 31
util: 41
concurrent: 1
Overall method count: 1554

---

GCM:

Read in 72 method IDs.
<root>: 72
android: 27
app: 2
content: 16
pm: 1
os: 8
util: 1
com: 24
google: 24
android: 24
gms: 24
gcm: 24
java: 21
io: 1
lang: 12
util: 8
concurrent: 5
atomic: 2
Overall method count: 72

---

Ads:

Read in 3878 method IDs.
<root>: 3878
android: 471
app: 50
content: 75
pm: 5
res: 7
database: 13
sqlite: 7
graphics: 12
drawable: 1
location: 4
media: 5
net: 25
os: 67
provider: 1
telephony: 3
text: 2
util: 16
view: 67
webkit: 64
widget: 67
com: 3059
google: 3059
ads: 127
mediation: 96
admob: 23
customevent: 41
android: 2932
gms: 2932
ads: 353
doubleclick: 84
mediation: 75
admob: 2
customevent: 48
purchase: 16
search: 81
analytics: 2
common: 39
internal: 37
safeparcel: 27
dynamic: 5
internal: 2533
java: 318
io: 16
lang: 126
ref: 2
reflect: 3
math: 7
net: 23
security: 11
spec: 1
text: 2
util: 133
concurrent: 28
atomic: 7
org: 30
json: 30
Overall method count: 3878

---

Identity

Read in 179 method IDs.
<root>: 179
android: 34
accounts: 1
app: 2
content: 5
os: 23
text: 1
util: 2
com: 135
google: 135
android: 135
gms: 135
common: 28
api: 4
internal: 21
safeparcel: 15
identity: 75
intents: 75
model: 41
internal: 32
java: 10
lang: 6
util: 4
Overall method count: 179

TOTAL: 9275


TL;DR The total method counts for all components I use is in fact 9275, less than half of what ends up in the .apk produced with the gradle build from the beginning of the question!


Trying to build the .apk without multi-dex support fails, again overstepping the 64k method limit.


I really have no idea what's going on here, and would appreciate some help. Multi-dex is nice and all, but 8k methods is quite a large buffer for my project alone, and if the granular dependencies worked as expected, I wouldn't have to introduce multi-dex for a long time to come.


Also, please don't suggest proguard as a solution. It's a band-aid at best, and would not be necessary for debug builds if the dependencies were handled correctly.


0 comments:

Post a Comment