Create a gist now

Instantly share code, notes, and snippets.

google-play-services-strip-script
actions=true
ads=true
analytics=true
appindexing=true
appstate=true
auth=true
cast=true
common=true
drive=false
dynamic=true
games=false
gcm=true
identity=true
internal=true
location=false
maps=false
panorama=false
plus=true
security=true
tagmanager=true
wallet=false
wearable=true
#!/bin/sh
#
# Strips the Google Play Services JAR archive and removes the folders that are specified below.
# This should lower the methods count of the final DEX file and should lower the chance of hitting
# the (dreaded) 64K methods limit.
#
#
# Author: Sebastiano Gottardo
# @rotxed - dextorer[at]gmail[dot]com
#
PLAY_SERVICES_FILENAME="google-play-services.jar"
PLAY_SERVICES_TEMP_DIR="google-play-services-temp"
PLAY_SERVICES_STRIP_FILE="strip.conf"
PLAY_SERVICES_NESTED_PATH="com/google/android/gms"
PLAY_SERVICES_OUTPUT_FILE="google-play-services-STRIPPED.jar"
# Check if file exists in the same directory
if [ ! -f $PLAY_SERVICES_FILENAME ]; then
echo "\nPlease put this script in the Play Services JAR location, then run it again\n\n"
exit -1
fi
# Preventive cleanup
rm -rf $PLAY_SERVICES_TEMP_DIR
# Create temporary work folder
mkdir $PLAY_SERVICES_TEMP_DIR
cp $PLAY_SERVICES_FILENAME $PLAY_SERVICES_TEMP_DIR/
cd $PLAY_SERVICES_TEMP_DIR
# Extract the content of the Play Services JAR archive
echo "Extracting archive, please wait.."
jar xvf $PLAY_SERVICES_FILENAME > /dev/null
echo "Extracted.\n"
# If the configuration file doesn't exist, create it
if [ ! -f ../$PLAY_SERVICES_STRIP_FILE ]; then
# Create the file
touch ../$PLAY_SERVICES_STRIP_FILE
FOLDERS=`ls $PLAY_SERVICES_NESTED_PATH`
for index in $FOLDERS
do
echo "$index=true" >> ../$PLAY_SERVICES_STRIP_FILE
done
fi
# Read configuration from file
while read -r FOLDERS
do
CURRENT_FOLDER=$FOLDERS
CURRENT_FOLDER_NAME=`echo $CURRENT_FOLDER | awk -F'=' '{print $1}'`
CURRENT_FOLDER_ENABLED=`echo $CURRENT_FOLDER | awk -F'=' '{print $2}'`
if [ "$CURRENT_FOLDER_ENABLED" = false ]; then
echo "Removed $CURRENT_FOLDER_NAME folder"
rm -rf "$PLAY_SERVICES_NESTED_PATH/$CURRENT_FOLDER_NAME"
fi
done < ../"$PLAY_SERVICES_STRIP_FILE"
# Create final stripped JAR
jar cf $PLAY_SERVICES_OUTPUT_FILE com/
cp $PLAY_SERVICES_OUTPUT_FILE ../
cd ..
# Clean up
echo "\nFolders removed, cleaning up.."
rm -rf $PLAY_SERVICES_TEMP_DIR
echo "All done, exiting!"
exit 0
@megatronxxx

while read -r FOLDERS misses last line
It fixes like that while read -r FOLDERS || [[ -n "$FOLDERS" ]];

@sliskiCode

When I use your script with only maps=true I get java.lang.NoClassDefFoundError: com.google.android.gms.maps.MapView$b. Any ideas?

@medvedev84

I recommend to use "-p" flag for copying jar into temp directory to avoid permissions issue:
cp -p $PLAY_SERVICES_FILENAME $PLAY_SERVICES_TEMP_DIR/

@Daemon-Devarshi

I am trying to run above shell script in a mac machine, but I am always getting error: ' syntax error near unexpected token `do' :(

Any clues?

@ilya-shknaj

line 36: jar command not found
line 63: jar: command not found
cp: cannot stat 'google-play-services-STRIPPED.jar' : No suc file or directory

What do I wrong?

@aftabsikander

Can anyone tell me how to run this script a short tutorial will help
Thanks

@hoolrory

As a hint to anyone else who comes along, you will probably need to keep common, internal, and dynamic as it looks like those are used by a few of the other ones. Still getting a handle on it myself

@marinomeneghel

Found a problem using the stripped library. The file strip.conf is the same of the sample, except for the location that's true. When I check if play services are available, I get the error java.lang.NoClassDefFoundError: com.google.android.gms.R$string
on the line that shall show the error dialog from play service:
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
PLAY_SERVICES_ERROR_REQUEST_CODE).show();
Do anyone have a solution for this?

@MoMannn
MoMannn commented Nov 11, 2014

I have the same problem as: ilya-shknaj

EDIT: the problem was that I did not have java in PATH.

@NovopayVinay

maps=true I get java.lang.NoClassDefFoundError: com.google.android.gms.maps.MapView$b while doing maps with stripped google play services

@tamirherman

Also same problem with MapFragment (Like NovopayVinay)

@tamirherman

Fount the answer for the problem.

"maps=true I get java.lang.NoClassDefFoundError: com.google.android.gms.maps..."

Copy project from the sdk.
Store the stripped jar instead the original jar.

Import as a library.

Extend it to your project.

Thanks,
dextorer.

@pat2016
pat2016 commented Dec 17, 2016

I have read your articles about the 65K limit with great interest, and have tried using your strip-play-services.sh / strip.conf files, but with the following results :-

  1. The main computer is running java 1.6 with Windows 10 and it will not work; it requires java 1.4; I don't know if that is limited by google-play-services.jar or the .sh file. I have tried to include java 1.4 as an option on the computer but there doesn't seem to be a download site with this available.

  2. I have another computer which does have java 1.4 but it is running Windows XP, and this does not recognise the .sh file. I have tried using Git or Cygwin to recognize the .sh bash file but it registers CancelSynchronousIo not found in kernel32.dll and fails to run. I have tried many variants on this from different download sites (including fruitbat which supposedly overcomes this problem, but which wouldn't even download) and all suffer the same fate.

  3. I have tried converting your .sh file to a .bat file and running this with XP but I am having difficulty in fully translating it.

I can't think of any other solutions.

Can you offer any suggestions, or a stripped version of google-play-services.jar which I could use?

Thanks in advance.

Regards

@pat2016
pat2016 commented Dec 18, 2016

As a follow up to my comments above, I now have java 1.4 running on Windows 10 and have run strip-play-services.sh to generate google-play-services-STRIPPED.jar, but this is an even larger file than google-play-services.jar (5702 KB vs 5617 KB). I still get a Dalvik conversion failure due to exceeding 64K methods. The classes.dex file is showing 55663 or 28633 methods for an earlier successful version of the app (I'm not sure of the order of counting - big endian vs little endian) and the difference between both versions' methods count is unknown. The earlier version works well with the STRIPPED version of google-play-sevices.jar.

Why is the stripped version larger in size, and still unsuccessful in operation with the new version of the app?

Regards

@pat2016
pat2016 commented Dec 19, 2016

I have analyzed the STRIPPED jar file and its content is virtually the same as the original google-play-services.jar file with all the same jar-files content. I cannot see where the strip.conf file is being tested for which jar-files to accept.

Any comments?

Regards

@pat2016
pat2016 commented Dec 19, 2016

The problem was all mine. I had failed to copy your script accurately.

Regards

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