Just adding this answer as an alternative and update to the already existing answer.
Having recently integrated Samsung's Accessory SDK into an Android 'companion' app to support a Tizen app on the Galaxy Gear S2, I ran into the same problem when compiling a (minified) release build of the companion app.
@while's answer already explains the cause and remedy of the NoSuchMethodException
thrown. However, I found the outlined Proguard rules to be rather relaxed and numerous. This may have necessary for older versions of the Accessory SDK, but these days you can probably do with far less exclusions.
Assuming you're using one of the more recent Accessory SDK versions (I tested both 2.2.2 and 2.3.0), you'll still want to start with:
-keepattributes InnerClasses
You can't get around this one, because the SAAgent
uses reflection to instantiate an instance of the SASocket
you implement somewhere in your own code. This rule ensures that the relationship between (and naming of) the inner and outer classes doesn't change.
Now, you may be tempted to write a rule to keep the default constructor of your SASocket
implementation by adding an exclusion for <init>()
. Unfortunately, that won't work, because as part of the code optimisation Proguard will actually create a parameterised constructor in the inner class that accepts an instance of the outer class. As a result, that constructor isn't kept and stripped away because Proguard thinks no one is calling it.
So, long story short, to keep both your SASocket
implementation and its constructor(s), add a rule:
-keep class * extends com.samsung.android.sdk.accessory.SASocket { <init>(...); }
Up until this far, your app was probably crashing at runtime without the above rules. Having added them, this should no longer be the case. However, you'll notice that the Accessory SDK still logs various errors and that your app isn't yet working as intended. Inspecting Logcat, you should see errors indicating that the SDK failed to bind to your service.
The cause for this may not be obvious, but if you dig around the Accessory SDK, you'll notice some IInterface
and Binder
extensions (i.e. in IDeathCallback
and ISAFrameworkManager
(2.2.2) or ISAFrameworkManagerV2
(2.3.0)). Since Proguard can't find any explicit calls to them and doesn't know these are in fact invoked at runtime by the Android framework, it'll strip them away. So, let's add a rule to stop Proguard from doing that:
-keep class com.samsung.accessory.api.* extends android.os.Binder { *; }
After this, it's time for congratulations: your service should now be bindable again. Depending on your implementation you may require further exceptions, but for a basic setup, above should do the trick.
Adding it all up, you should have the following rules in your config:
#
# Samsung Accessory SDK Proguard Rules
#
# Keep relationship between inner and outer classes
-keepattributes InnerClasses
# Keep any SASocket implementation and its constructors
-keep class * extends com.samsung.android.sdk.accessory.SASocket { <init>(...); }
# Keep the Accessory SDK's IInterface and Binder classes
-keep class com.samsung.accessory.api.* extends android.os.Binder { *; }
YMMV.