Monday, January 21, 2013

Tuesday, January 15, 2013

New Google Analytics Console

Huge fan of the new Google Analytics redesign.  It's nice to not have to switch over to tab sections to see real-time stats, shortcuts, dashboards and intelligence events.  Here's a snapshot of the new left navigation panel.


Sunday, January 13, 2013

Using Proguard with Android

Some reasons you might want to use it

Security

Proguard makes it easier to hide the implementation details and keys of the services you use.

Protect IP

The work involved in creating your project is often the primary reason you don't have competitors.  Proguard obfuscates your code so your competitors can't simply decompile copy/paste your work.

Reduce APK Size

Proguard removes unused code, reduces the length of variable names, and inlines code.  All this adds up to a smaller app size and less for your users to download.

Optimization

Proguard optimizes variable allocation, arithmetic, unnecessary code, etc.

Logging

Proguard can remove all your logging by removing the actual code that calls it.  This is much simpler and more efficient than any other method.

Syntax

Reflection

Reflection is easily the biggest gotcha when it comes to Proguard.  It works by analyzing which methods and classes actually get used.  Despite some safeguards, it's generally best to assume reflected code will get removed.  You need to specify which methods and classes to keep.  Generally, you should be as specific as possible because telling Proguard to keep large chunks of code drastically reduces it's efficacy.

Setting up your proguard.cfg

Initial Template

#Remove all the injar/outjar/libraryjar junk, the android ant script takes care of this

-dontpreverify
-repackageclasses ''
-allowaccessmodification
-optimizations !code/simplification/arithmetic
-keepattributes *Annotation*

-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 public class * extends android.view.View {
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
    public void set*(...);
}

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

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

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

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


First thing you should notice, is that we tell Proguard to keep all the classes (Activities, Services, etc) we declare in AndroidManifest.xml.  These are known as the entry points to the application.  These classes should not have their names changed because the Android won't be able to find them when needed.

Fragments

-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.app.Fragment

Fragments are generally created through reflection.  It's a good idea to keep them all.

3rd Party Libraries

-keep class android.** {*;}
-keep class com.millennialmedia.android.** {*;)
-keep class com.google.ads.** {*;}




It's generally a good idea to keep everything in a third-party library or jar, unless receiving a specific exclude list from the publisher.  You didn't write the code so it's hard to know what sort of issues it may have with Proguard.

Removing Logging

-assumenosideeffects class android.util.Log {
    public static *** e(...);
    public static *** w(...);
    public static *** wtf(...);
    public static *** d(...);
    public static *** v(...);
}

assumenosideeffects tells Proguard that method calls to these don't actually do anything and can be removed if the return value is not used.  android.util.Log does have a return value that's not particularly useful so keep this in mind.

Serializables

-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 <fields>;
    !private <fields>;
    !private <methods>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

I'm not entirely sure why this isn't just build into the platform.  These methods and fields from Serializable are discovered at runtime and won't be used in your code.

Click Methods

-keepclassmembers class * {

public void *ButtonClicked(android.view.View);

}

Methods that are called by android:onclick in your xml layouts are referenced by reflection at runtime.  My strategy is to suffix them all with ButtonClicked and save any method that ends with that.

Native Methods

-keepclasseswithmembernames class * {
    native <methods>;
}



Native methods should not be obfuscated because they reference JNI methods relating to their name.

Obfuscating debug builds

It may be useful to obfuscate debug builds in a continuous integration environment.  If so, you can modify your Android build.xml this way to accomplish it.
<target name="-debug-obfuscation-check">
        <!-- yes, we want to obfuscate in debug too!!!! -->
        <condition property="proguard.enabled" value="true" else="false">
            <and>
                <isset property="proguard.config" />
            </and>
        </condition>
        <if condition="${proguard.enabled}">
            <then>
                <!-- Secondary dx input (jar files) is empty since all the
                     jar files will be in the obfuscated jar -->
                <path id="out.dex.jar.input.ref" />
            </then>
        </if>
    </target>

Air Conditioning App

Published a new Android app today to help users find the perfect-sized window air conditioner for their home.  Branded for my friends' general contracting and remodeling company, The Chateau Group

Air Conditioner Calculator on Google Play


Friday, January 11, 2013

Chad Kouse Dot Com needs to stop ripping off my blogger theme.

Monday, January 7, 2013

Friday, January 4, 2013

O-H!

Lawrence, I love that you follow my blog.  However, it really bothers me that there's a Michigan logo in my sidebar.

Thursday, January 3, 2013

Using Campaign Tracking to Send a Message

I put campaign tracking on nearly every link I sent to the web.  It's not just about finding out where your traffic is coming from, but also leaving an impression on other developers that you're sending traffic too.

There's another useful method for this: sending messages to a site that have the potential to be very visible to someone that can make decisions.  When you send a message to customer support, it gets mixed in with the general opinion of the user-base and then transferred on to product and marketing.  Chances are, your opinion doesn't make it past the support team.  However, employees at the company looking at analytics are often employees trying to make practical product decisions based on this data.  You hit them directly this way.

Suppose you visit my website, and decide you'd love to tell me how wonderful it is.  You could send me a message with:

http://www.andymcsherry.com?utm_source=andy%20admirer&utm_medium=address%20bar&utm_campaign=letting%20people%20know%20they%20rock