Fixing the Gear Fit SDK for Android 5.0 Lollipop

With Version 5.0 of Android the usage of implicit intents is changed. It is no longer possible to bind to a service using an implicit intent. Trying to do so results in a "InvalidArgumentException". 

Unfortunately this also affects applications written using the CUP SDK for the Gear Fit. The SDK uses a communicator class that binds to some Samsung framework providing the communication to the Gear Fit. This binding relies on a implicit intent. As a consequence your own apps won't work any longer once you upgraded to Android Version 5 on the host device. 

Below I wrote up how I fixed the problem. It would be best, if Samsung would "just" make the current fixed SDK available. As the copyright situation is kind of unclear, I'm not posting the SDK (cup-v1.0.0.jar).

The following five steps assume that you work in a Mac OS or Linux environment including a JDK.

Before we start a short explanation about the fix:

The connect() method is used when the first dialog is created. This explains why apps may properly initialize and then fail:

public boolean connect(Object paramObject) {
  int i = 1;
  Intent localIntent = new Intent("com.samsung.android.sdk.cup.ScupService");
  if (!(this.mContext.getApplicationContext().bindService(localIntent, this.mConnection,  i)))
  i = 0;
  return i;
}

In order to fix the method we need to add one line of code:

public boolean connect(Object paramObject) {
  int i = 1;
  Intent localIntent = new Intent("com.samsung.android.sdk.cup.ScupService");
   // FIX FOR LOLLIPOP
   localIntent.setPackage("com.samsung.android.wms");
   // END FIX FOR LOLLIPOP
  if (!(this.mContext.getApplicationContext().bindService(localIntent, this.mConnection,  i)))
  i = 0;
  return i;
}

The proper way for fixing this would be to query the package manager and to hope that we only find one service implementation:

// FIX FOR LOLLIPOP
        Iterator iter =mContext.getPackageManager().queryIntentServices(localIntent,0).iterator();
        if(iter.hasNext()) {
        ResolveInfo rI=(ResolveInfo)iter.next();
        localIntent.setPackage(rI.serviceInfo.applicationInfo.packageName);
        }
        // END FIX FOR LOLLIPOP

With the proper solution and patching approach described below, a dalvik format error occurred. Since the byte code editor seems to be not up to date with current Java Byte Code, there may be situations where this does not work. 

Also, It may be possible that an update of the Samsung Software on the phone may result in a different package name for the service, causing this patch to fail. 



Step 1:

You need the following files:
  1. the SDK itself: cup-v1.0.0.jar (find it under xda forum: http://forum.xda-developers.com/gear-fit/development/samsung-gear-fit-sdk-available-t2872803)
  2. a java byte code editor: http://set.ee/jbe/

Step 2:

Extract the SDK jar:

jar xvf cup-v1.0.0.jar

Step 3:

Run JBE:

unzip the downloaded be file into a directory
cd <unzip dir>
export CLASSPATH=./bin
./jbe.sh


The editor window should appear.

Step 4:

Navigate to the directory with the extracted files and open the ScupServiceCommunicator.class. Locate the "connect()" method and open the code. It should appear in the right hand window. Select the "Code Editor". Select the content with Ctrl-A and paste the following byte-code into the window:

iconst_1
istore_2
new android/content/Intent
dup
ldc "com.samsung.android.sdk.cup.ScupService"
invokespecial android/content/Intent/<init>(Ljava/lang/String;)V
astore_3
aload_3
ldc "com.samsung.android.wms"
invokevirtual android/content/Intent/setPackage(Ljava/lang/String;)Landroid/content/Intent;
pop
aload_0
getfield com/samsung/android/sdk/cup/ScupServiceCommunicator/mContext Landroid/content/Context;
invokevirtual android/content/Context/getApplicationContext()Landroid/content/Context;
aload_3
aload_0
getfield com/samsung/android/sdk/cup/ScupServiceCommunicator/mConnection Landroid/content/ServiceConnection;
iload_2
invokevirtual android/content/Context/bindService(Landroid/content/Intent;Landroid/content/ServiceConnection;I)Z
ifne 23
iconst_0
istore_2
iload_2
ireturn


It should count 24 lines. Save the file.

Step 5:

Go back the terminal and pack the jar:

jar cvf cup-v1.0.0-lollipop.jar com


You are done! When you put the jar into your app project, make sure that you clean out the bin directory and refresh the IDE (e.g. Eclipse).