I am trying to use proguard to obfuscate the code of my Android app.
My problem is that some screen of my app work fine, some others show a blank screen (not entirely blank though, for example my top title bar display correctly, but the rest of the content is blank).
I have started with the basic settings:
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
Then, in proguard-project.txt, I have tried to add:
-keep class {my.package.name}.** { *; }
No change
Then
-dontskipnonpubliclibraryclassmembers
No change
Then
-dontobfuscate
which obviously solved the problem but then there is no point since I want to obfuscate my code.
Any idea?
Look at the output ProGuard creates; it will tell you what classes got renamed and what classes got deleted (because they appear to be unused). You will need to modify your config to nether rename nor delete these classes of course. Typically, you can find an interaction between your AndroidManifest.xml and the pieces that are missing after obfuscation (and your logcat might even tell you what is missing). Less likely is that use of reflection led ProGuard to not realize the importance of keeping these things in tact.
If you decide you need full obfuscation for the things that are being altered yet are necessary, you'll need to create thin object proxys that are safe from obfuscation and know how to get to the real classes.
Related
Whats the difference between
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt
and
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
when I'm using 1st one its crashing with facebook login, but not when i use second, it'll not crash (in release build).
but size get increase from 4 to 5 MB in second.
I'm using API 21.
Facebook sdk 3.0
Without seeing the contents of the proguard files, I can only guess, but I think it's fair to assume that proguard-project.txt contains definitions to keep class names / methods / members / etc relating to the Facebook SDK.
The reason it's crashing in the 1st setting is because it doesn't include your project's proguard settings, meaning it minifies more than the 2nd setting (including the Facebook SDK). Then, in release, the Facebook SDK is possibly loading a class / invoking a method via reflection or something similar, and crashing because it can't find a method / class name which has been minified.
This is also why the 2nd setting results in a larger binary - minifcation means smaller binary, since every class is being reduced from "SomeLongClassName" to "a". The more you minify, the smaller (and more efficient) the resulting binary is.
Minification is an optimization, and shouldnt (IMO) have a higher priority than code coherence and architecture. If you need to exclude several items from minification (which your ProGuard probably does with the Facebook SDK), then you should, and you shouldn't worry about the resulting APK size.
I just found that ProGuard removed a .wait() call which I used to synchronize threads, which lead to a race condition which lead to a day of happy debugging :) Anyway...
I tracked it down to following piece of proguard configuration:
-assumenosideeffects public class android.util.Log {
<methods>;
}
I want to understand WHY this happened. I am not sure why assuming that removal of Log class has no side effects leads to removal of .wait() on different class/object.
I saw ProGuard optimization also remove #wait() calls where Eric explains that such things may happen. However, he doesn't explain why.
Also, I found example how to remove Logs here (http://proguard.sourceforge.net/index.html#manual/examples.html). So, I can replace this piece of proguard of configuration (but it's not the point of this question).
Your original configuration matches all methods of Log (explicit or inherited), including Object#wait(). It tells ProGuard that the wait() method has no side-effects and that it can be removed without harming the program. This is obviously not true, as you have noticed. With -assumenosideeffects, you should always explicitly list the methods that are safe to remove.
It is very very hard to use the crash reports without knowing the line numbers. Also you cannot debug the code without line numbers as well.
Is there a specific reason to disable the line numbers when using ProGuard?
Thank you.
By default, ProGuard strives for the leanest possible application. It removes all elements from your code that are not strictly necessary for running it. You can preserve line numbers if you expect you'll need them, at the price of a very small increase in application size.
As the answers to this question ( A URL specified in a separate line in Java doesn't issue compile-time errors. Why? ) states you can add code labels on the code without having compilation errors.
Even more, using http:// will work as it will be considered a code label, and a comment.
So I was thinking...
Can I add a number of random code labels (including urls) to the code with proguard to make it even less readable?
Of course I could add them by hand, but that would be a good solution, as it would polute the original code, and what I want it just on release compiled code.
I wanted to do this on Android apps, that's why I'm focusing on proguard (an out of the box solution for Android obfuscation).
You could check AspectJ which allows to create custom modifications of the byte code during build.
However I would not do that. Have you checked if java decompilers show your URLs?
You better optimize your obfuscation such that there is as little as possible in clear text.
No, such labels won't affect the compiled code at all.
A label (be it "http:" or "somelabel:") doesn't show up in the compiled code, not even as debug information. It is only useful in combination with break statements.
A comment (be it "//www.example.com/path" or "//somecomment") doesn't get compiled in either. It is only useful to clarify the source code.
Since java bytecode doesn't represent labels or comments, ProGuard can't add them either. ProGuard also doesn't add unnecessary goto statements
Android app submission says, remove any logging before submission. Have a few question on this one
Is System.out.println considered as logging? How can I disable it across the app without having to remove it on by one
Tried android:debuggable="false" inside manifest, but eclipse says "Avoid hardcoding the debug mode; leaving it out allows debug and release builds to automatically assign one"
I have some third party jar files that shows Log statement when I test my app. How can I remove them, considering I don't have the source.
Suggestions are highly appreciated.
I'm sure you've come across the fact that you can do the if(GLOBAL_VALUE) trick, because your logs are already there!
Therefore, my suggestions is to use Proguard; http://developer.android.com/tools/help/proguard.html
The following proguard.cfg chunk instructs to remove Log.d calls.
-assumenosideeffects class android.util.Log {
public static *** d(...);
}
You can do it for other calls like Log.i, Log.e, etc based on the value you put there!
As for your Jar, if it is referencing the Android Log system, ProGuard should take care of that.