In android applications we include many library files such as google-play-services-lib and Facebook-SDK etc. But we never really use all features and classes from those libraries, so my question is when .apk file gets created does all those classes are included or the only classes we use are included in our application? If yes then is there a way we can get around that? ie can we remove or do something to avoid inclusion of all classes?
Thank You...
You should keep your Android application as small as possible. Therefore you should only include classes in the jars which you really need.
http://www.vogella.com/blog/2010/02/11/java-library-jar-android/
It is better to obfuscate your code using Proguard.
ProGuard is a Java class file shrinker, optimizer, obfuscator, and preverifier. The shrinking step detects and removes unused classes, fields, methods, and attributes. The optimization step analyzes and optimizes the bytecode of the methods
Obfuscation also secures your code to an extent.
To enable ProGuard in your project, edit project.properties
# Project target.
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt
target=Google Inc.:Google APIs:16
android.library.reference.1=../actionbarsherlock
http://developer.android.com/tools/help/proguard.html
http://proguard.sourceforge.net/index.html#manual/introduction.html
Related
I am trying to improve my understanding about usage of ProGuard for Android build. Am not very sure what to keep ( not obfuscate ) exactly and what to obfuscate.
Couple of libraries are being used in my App, some of them are listed below
com.android.support:appcompat
com.android.support:design
io.reactivex:rxandroid
io.reactivex:rxjava
com.jakewharton.rxbinding
com.trello:rxlifecycle
Question 1:
Should I obfuscate above libraries ? they are already open source.. will it not be wise to keep all support libraries using proguard rule:
keep class android.support.** { *; }
Similar way I can do with io.reactivex and jakewharton libraries
Question 2
Other than support and external libraries, I have application specific classes, coded for this application. Is it ok to keep the class names which are mentioned in AndroidManifest.xml and specifically their public members, and let obfuscate rest of the code.
Let me know if I am missing something or my understanding is not correct. just to repeat this is not a question on how to do it technically, but more on what to include and what to exclude for obfuscation/optimization/ shrink.. and more specifically reason behind it ....Definitely it will be espresso tested after build.
Question 1: Should I obfuscate above libraries?
Yes. If you add -keep <library> rules then the entire library will be included in your APK, which bloats it and might cause problems such as making your app exceed the 64k method limit and require Multidex. It's always a good idea to apply the ProGuard rules provided by the library. You can usually find .pro files in the libraries source code or in websites such as https://github.com/krschultz/android-proguard-snippets.
Question 2: Is it ok to keep the class names which are mentioned in AndroidManifest.xml and specifically their public members, and let obfuscate rest of the code.
The Android plugin already does that for you. The plugin scans all classes whose names need to be preserved (e.g. Activities, Services, BroadcastReceivers, Views, etc) and doesn't obfuscate them. This includes everything that you declare in AndroidManifest.xml.
Would any of you be so kind as to rephrase (in your own words) the explanations for some of the proguard keywords that are written in their manual? I have hard time understanding in full what some of them mean, and what changes if they are not there in the .cfg file.
The keywords I'm interested are:
1) -dontskipnonpubliclibraryclasses and -dontskipnonpubliclibraryclassmembers
The second is being explained as:
Specifies not to ignore package visible library class members (fields and methods). By default, ProGuard skips these class members while parsing library classes, as program classes will generally not refer to them. Sometimes however, program classes reside in the same packages as library classes, and they do refer to their package visible class members. In those cases, it can be useful to actually read the class members, in order to make sure the processed code remains consistent.
First of all, does it refere only in the context of external jars? Second, what is the difference between those flags reside in the .cfg file vs not being there?
2) -libraryjars, I'm lost for that one. What is the purpose of this keyword? On proguard manual page it reads:
Specifies the library jars (or aars, wars, ears, zips, apks, or directories) of the application to be processed.
So does it mean, that if I don't use this flag, then those jars are not put under the whole obfuscation process? But if that's the case, then why when I don't use this keyword, there are a lot of warnings for classes in those jars in the proguard output?
Next it says:
The files in these jars will not be included in the output jars.
What does it mean exactly? It means, that if this flag is set, then all other files aside .class files will not be included in the parent's application jar?
After hours of reading I think I got my answers. Especialy what helped me was reading many of the creator of ProGuard answers here at StackOverflow.
Let me start with the jars topic. Libraryjars is usually the platfrom jar, the application is build against, so android.jar is a good example here. This jar will not be processed, it's classes will not reside in the output apk, because they will be all on the clients device. They will not be obfuscated or shrunk, because a) even if they were they would not be coppied into the output apk anyway, and b) if they were obfuscated then it would crash application due to the fact that say Activity during obfuscation would have the name changed to "a", but on the clients device the android API is not changed.
So libraryjars is used for all the jars that proguard needs when processing our app, but which jars will not be included (or it's class files) in the final apk.
Injars on the other hand are all the jars that we want to be shrunk/obfuscated etc (unless we use keep* keywords).
Now the reason that I had so much difficulty was because there were conflicting information about those keywords all over the place. Some people said to use -injars, some said to use -libraryjars, some said neighter. What I found out later on, is that the last answer is correct. No -libraryjars or -injars keyword is needed because ADT does all this for the developer, and it uses the -injars keyword with all the jars residing in the /libs folder.
That is also the reason why I found many people using the "keep" keywords with the packages of one of the jars to ignore it's obfuscation/shrinking. The reason for it is that because ADT uses -injars keyword for those jars by default (and not libraryjars which would essentialy do the same in this context) then those jars are marked to be processed (obfuscated/shrunk). To negate this effect, people use -keep keywords for the packages of those jars.
As for the #1 question:
First of all, does it refere only in the context of external jars? The answer is no. It reffers to all the libraries even referenced inside the attached jars
Second, what is the difference between those flags reside in the .cfg file vs not being there? From what I found out it's for helping the ProGuard with processing of those libraries.
I have a library project which refers two other library projects (Google Play Services and Appcompat). The referencing project has no code just resources. All the code is in this library project. I added proguard configuration for my library project hoping to reduce the size of my binary. It compiles and generates the signed apk fine using ant build. But I see no reduction in binary size. Its exactly the same size as it was without proguard. Also obfuscation occurs only for few of the classes , not all.
What am I missing? Any help is appreciated.
Figured out myself. I configured proguard for the referencing project instead of configuring it in the library. All referenced libraries were automatically taken care of and i was able to shrink the size of final apk by about 30%.
obfuscation does not occur for all classes, some classes are skipped as they need to remain (normal) mainly, the views, and other classes that need to be accessed by external components
also check Proguard config file,
you some classes might be set as skipped by mistake.
For the moment I am developing small Android projects to practice with the Android prorgramming. However, once on the market, I would like to obfuscate / optimise the APK thanks to ProGuard. But this tool renames classes to obfuscate the code, so:
Is it safe to use tools like Android Query to write the code?
If it is not safe, what are some framework examples that can be used safely with Pro Guard?
What could be a solution to the problem? Or should I write everything using the good old Android style and forget about a "write less, do more" approach?
How do I identify the tools that are ProGuard-safe from the ones that are not?
I assume you want to use third party libraries (jar files). You could use a 3 step approach:
If the third party jar explicitly supports Android, it will have a proguard configuration. Usually this is a snippet that you merge into your proguard-project.txt.
If there is no such explicit support, you may still try to use the jar, obfuscate and test your app. If errors occur, gradually exclude classes from obfuscation until it works. A common problem is that libraries use reflection to instantiate classes and call methods which breaks after obfuscation.
Exclude the whole library from obfuscation. This will work in any case and proguard will not touch the library at all. (The Android toolchain will still repackage the contents of the jar into your apk which might cause problems.) This will also produce the least obfuscated result and should really be your last resort.
In any case, obfuscation is not a switch that you simply toggle. You'll need to get familiar with proguard config files which involves a learning curve.
Suppose i am developing an application using android api 16, my app will include android.jar. I would be importing few classes from the jar file.
I would enable proguard in release mode by configuring proguard. Does proguard remove unused classes in android.jar also?
Edit:
properties file for my project
android.library.reference.1=../actionbarsherlock
So does proguard remove unused classes from my library project included when packaging everything to .apk ?
Proguard does NOT remove anything from libraries. See the diagram and quote from the Proguard website.
ProGuard requires the library jars (or wars, ears, zips, or
directories) of the input jars to be specified. These are essentially
the libraries that you would need for compiling the code. ProGuard
uses them to reconstruct the class dependencies that are necessary for
proper processing. The library jars themselves always remain
unchanged. You should still put them in the class path of your final
application.
Android.jar would be referenced as a library jar (-libraryjars, see Proguard documentation) as opposed to an input jar. That means it would not be included in the output APK anyway. After all you don't want to redistribute the Android system libraries along with your app.