Thursday, May 17, 2012

Configuring ProGuard for an Android project

I've done a few Android projects and I find that when I start pushing out obfuscated binaries often I have to spend quite a bit of time debugging my proguard.conf file to get rid of all the new crashes :)
For this reason I've created this Android proguard.conf generic starting point template. If you've know any other common config lines let's have them and I'll update this post accordingly.

-dontpreverify
-optimizations !code/simplification/arithmetic
-keepattributes *Annotation*
-printmapping AppClassMap.map

-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider

-keep class android.support.v4.** { *; }

-keep public class * extends android.app.Fragment
-keep public class * extends android.support.v4.app.Fragment
-keep public class * implements de.akquinet.android.androlog.reporter.Reporter
-keep class com.google.android.apps.analytics.PipelinedRequester$Callbacks

-keep public class * extends android.view.View {
    public (android.content.Context);
    public (android.content.Context, android.util.AttributeSet);
    public (android.content.Context, android.util.AttributeSet, int);
    public void set*(...);
}

# Keep serializable classes and necessary members for serializable classes
# Copied from the ProGuard manual at http://proguard.sourceforge.net.
-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient ;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

-keepclasseswithmembers class * {
    public (android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
    public (android.content.Context, android.util.AttributeSet, int);
}

-keepclassmembers class * implements android.os.Parcelable {
    static android.os.Parcelable$Creator CREATOR;
}

-keepclassmembers class **.R$* {
    public static ;
}

-keep public interface com.android.vending.licensing.ILicensingService

-keepclasseswithmembernames class * {
    native ;
}

-keepclassmembers class * extends java.lang.Enum {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# Removes all calls to Log. Delete the methods you want to keep.
-assumenosideeffects class android.util.Log {
    public static int v(...);
    public static int d(...);
    public static int i(...);
    public static int w(...);
    public static int e(...);
    public static int wtf(...);
}

# Removes all calls to Log. Delete the methods you want to keep.
-assumenosideeffects class de.akquinet.android.androlog.Log {
    public static int v(...);
    public static int d(...);
    public static int i(...);
    public static int w(...);
    public static int e(...);
    public static int wtf(...);
}


-dontwarn **CompatHoneycomb
-dontwarn android.support.v4.**
-dontskipnonpubliclibraryclasses
-dontusemixedcaseclassnames

Monday, April 02, 2012

Setting it free

After making my first million :) I've decided that my Slashdot Reader Widget should be free. There are no annoying adds or anything else to lessen your experience - just the fully functional version for you to enjoy at no cost.

Saturday, January 21, 2012

Slashdot Reader Widget for Android - Maintenance

As soon as I released the original version of the Slashdot widget, I realized  that Android 3.0+ (honeycomb and ice cream sandwich) allows natively scrollable widgets (at least in the vertical direction) and this is much nicer on bigger screens, no such luck for Android 2.3 (Gingerbread) or prior versions of course.

The nice thing about Android and the Market Place is that it's relatively easy to work around this using the android:minsdkversion and android:maxSdkVersion elements of AndroidManifest.xml.

At this point I've developed 2 versions of the widget.

Version A:
- Targets Android 2.2 & 2.3 AndroidManifest.xml contains:
<uses-sdk android:minsdkversion="8" android:maxsdkversion="10"/>
- Uses custom arrow buttons for scrolling and switching between stories

Version B:
- Targets Android 3.0+ AndroidManifest.xml contains:
<uses-sdk android:minsdkversion="11"/>
- Uses ListView backed by a Collection

I did a build of both and publish them both concurrently in the Market Place - no problem :)