只需将此答案添加为替代方案并更新到现有答案即可。
最近将三星的 Accessory SDK 集成到 Android 的“配套”应用程序中以支持 Galaxy Gear S2 上的 Tizen 应用程序,我在编译配套应用程序的(缩小的)发布版本时遇到了同样的问题。
@while 的回答已经解释了NoSuchMethodException
抛出的原因和补救措施。但是,我发现概述的 Proguard 规则相当宽松且数量众多。这对于旧版本的 Accessory SDK 可能是必需的,但现在您可以使用更少的排除项来实现。
假设您使用的是较新的 Accessory SDK 版本之一(我测试了 2.2.2 和 2.3.0),您仍然需要从以下内容开始:
-keepattributes InnerClasses
您无法解决这个问题,因为SAAgent
使用反射来实例化SASocket
您在自己代码中某处实现的实例。此规则确保内部和外部类之间的关系(和命名)不会改变。
现在,您可能会想SASocket
通过添加排除来编写规则以保留实现的默认构造函数<init>()
。不幸的是,这不起作用,因为作为代码优化的一部分,Proguard 实际上会在内部类中创建一个参数化构造函数,该构造函数接受外部类的实例。结果,该构造函数没有被保留和剥离,因为 Proguard 认为没有人在调用它。
因此,长话短说,要同时保留您的SASocket
实现及其构造函数,请添加一条规则:
-keep class * extends com.samsung.android.sdk.accessory.SASocket { <init>(...); }
到目前为止,如果没有上述规则,您的应用程序可能会在运行时崩溃。添加它们后,情况将不再如此。但是,您会注意到 Accessory SDK 仍会记录各种错误,并且您的应用程序尚未按预期运行。检查 Logcat,您应该会看到错误,表明 SDK 无法绑定到您的服务。
造成这种情况的原因可能并不明显,但是如果您深入研究 Accessory SDK,您会注意到一些IInterface
和Binder
扩展(即在IDeathCallback
and ISAFrameworkManager
(2.2.2) 或ISAFrameworkManagerV2
(2.3.0) 中)。由于 Proguard 找不到对它们的任何显式调用,并且不知道这些实际上是由 Android 框架在运行时调用的,因此它会将它们剥离。所以,让我们添加一个规则来阻止 Proguard 这样做:
-keep class com.samsung.accessory.api.* extends android.os.Binder { *; }
在此之后,是时候恭喜了:您的服务现在应该可以再次绑定了。根据您的实现,您可能需要进一步的例外,但对于基本设置,上面应该可以解决问题。
加起来,你的配置中应该有以下规则:
#
# 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。