woensdag 22 oktober 2014

Changing command line switches for Chrome on Android

While we were developing a web application, we ran into a little "snag" when a (Nexus 5 using a) Chrome browser tried to access our web application using a reversed proxy.  For some reason we received a Connection Closed after downloading the headers with some 8 kb of (corrupted) data.

When we narrowed it down that the data was compressed, we found out that Chrome enables SDCH by default, which is only supported by ... Google.  To narrow down the problem, we checked if we could access the server directly (worked via a VPN) and with different browsers (Opera and Firefox). When we used Firefox, it all worked perfectly (why? WebKit vs Gecko Engine...).

Because we actually wanted to point-out the problem, we wanted to be able to switch of the SDCH when using the Chrome browser (we used Chrome 38.0.2125.102 on Android 4.4.4). Here are the different steps we used:

Prerequisite:
  • You need to have root access on your Smartphone (we rooted a Samsung Galaxy Nexus with a Cyanogenmod);
  • You need developer access to your Smartphone;
  • You need to have adb (Android Debug Bridge) installed;
  • You need to have a good understanding of Linux/Terminal/VI;
As they say, with great power comes great responsibility. So please be careful on what you do with the root access!

Connect your device via a USB cable and start a Terminal. Connect to the device using:

$ ./adb shell

Change to root:

shell@maguro:/ $ su 


In your prompt VI a file called "/data/local/chrome-command-line" a

root@maguro:/ # vi /data/local/chrome-command-line 

Add this line (or whatever switches you may need) to this file:

 
--enable-sdch=0 --enable-sdch-over-https=0
~
~
~

Quite VI (:wq) and stop the Chrome instance running on your Android device. If you open the Chrome browser and navigate to "chrome://version", it should display the newly added switches  just below "User-Agent".








donderdag 16 oktober 2014

Robolectric + Google Play Service 5.x = java.lang.VerifyError

When I upgraded my application recently to include Play Services 5.x (for Wearable integration) I ran into the infamous VerifyError.

Thanks to this Google post, I could easily fix the issue.

In short, when you have this in your build file:
...
    //keep GMS play services at 4.4, 5.x only works with support-v4:21.+
    //compile 'com.google.android.gms:play-services:4.4.52'
    compile 'com.google.android.gms:play-services-wearable:5.0.77'

    compile 'org.bouncycastle:bcprov-jdk16:1.46'
...

Make sure to include:
tasks.whenTaskAdded { theTask ->
    def taskName = theTask.name.toString()
    //map "testLocalDebug" to your taskName!!
    if ("testLocalDebug".toString().equals(taskName)) {
        /**
         * Listen for when robolectric adds the 'testDebug' task and when it does, add the -noverify
         * option to that task's jvmArgs.  This allows us to turn off byte code verification when
         * running our unit tests.
         */
        theTask.jvmArgs('-noverify')
    }
}

To avoid:
java.lang.VerifyError: Expecting a stackmap frame at branch target 69
Exception Details:
  Location:
    com/google/android/gms/gcm/GoogleCloudMessaging.()V @31: goto
  Reason:
    Expected stackmap frame at this location.
  Bytecode:
    0000000: b801 b54c 2ab7 011d 2ab6 0120 1301 2203
    0000010: 1202 b801 284d 2cc7 000b 2b10 2c04 54a7
...