AsyncTask.doInBackground - Android Scala项目中未实现抽象方法的错误

时间:2014-07-24 12:43:32

标签: android scala proguard

任何人都可以给我任何关于如何调试以下内容的线索。

我有一个混合的java / scala android项目,我正在Intellij中工作,我通过Proguard处理它作为run config的一部分。

当我运行应用程序时,我收到错误:

07-24 12:36:35.879  21731-21779/com.ovaphone E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
java.lang.RuntimeException: An error occured while executing doInBackground()
        at android.os.AsyncTask$3.done(AsyncTask.java:299)
        at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
        at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
        at java.util.concurrent.FutureTask.run(FutureTask.java:137)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
        at java.lang.Thread.run(Thread.java:856)
 Caused by: java.lang.AbstractMethodError: abstract method not implemented
        at android.os.AsyncTask.doInBackground(AsyncTask.java)
        at android.os.AsyncTask$2.call(AsyncTask.java:287)
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)

我猜这是由于Proguard剥离太多造成的。

我确实有一个扩展AsyncTask的类,我知道这个类肯定是罪魁祸首,因为当我注释掉它的使用时,问题就消失了。

我的AsyncTask是:

object CheckNetworkStatusOnStartup {
  class Payload(var mainActivity: MainActivity) {
    var isConnected: java.lang.Boolean = false
  }

}

类CheckNetworkStatusOnStartup扩展了AsyncTask [CheckNetworkStatusOnStartup.Payload,Void,CheckNetworkStatusOnStartup.Payload] {

 override def doInBackground(params: Payload*): Payload = {
      val payload = params(0)
      <checks the network status and sets Payload.isConnected>
      payload
  }

 override def onPostExecute(payload: Payload) {
      <updates network status on screen of MainActivity>
  }

}

它在MainActivity中被调用:

 new CheckNetworkStatusOnStartup().execute(new CheckNetworkStatusOnStartup.Payload(this))

我尝试过添加两者:

-keep class * extends android.os.AsyncTask {
  *;
}

-keep public class com.mypackage.MyClass extends android.os.AsyncTask

到proguard配置文件但是没有区别。

那些“保证”的陈述应该足够吗?

任何人都可以给我任何关于如何进行的指示吗?

修改

根据Eric的建议,在编译的类上运行javap会得到以下输出:

public class com.ovaphone.CheckNetworkStatusOnStartup extends android.os.AsyncTask<com.ovaphone.Payload, java.lang.Void, com.ovaphone.Payload> {
  public com.ovaphone.Payload doInBackground(scala.collection.Seq<com.ovaphone.Payload>);
  public void onPostExecute(com.ovaphone.Payload);
  public com.ovaphone.Payload doInBackground(com.ovaphone.Payload[]);
  public void onPostExecute(java.lang.Object);
  public com.ovaphone.CheckNetworkStatusOnStartup();

}

在进程apk上运行dexdump表明缺少doInBackground(但是onPastExecute没有)。

为了调查问题是由Proguard和Scala之间的交互引起的,我编写了java版本的代码(我刚刚注意到它略有不同,因为Payload是CheckNetworkStatusOnStartup的内部类,但我没有认为这很重要)。 java版工作正常!这是javap输出:

class com.mysimplet.CheckNetworkStatusOnStartup extends android.os.AsyncTask<com.mysimplet.CheckNetworkStatusOnStartup$Payload, java.lang.Void, com.mysimplet.CheckNetworkStatusOnStartup$Payload> {
  com.mysimplet.CheckNetworkStatusOnStartup();
  protected com.mysimplet.CheckNetworkStatusOnStartup$Payload doInBackground(com.mysimplet.CheckNetworkStatusOnStartup$Payload...);
  protected void onPostExecute(com.mysimplet.CheckNetworkStatusOnStartup$Payload);
  protected void onPostExecute(java.lang.Object);
  protected java.lang.Object doInBackground(java.lang.Object...);
}

注意doInBackground的方法定义之间的区别:

Scala: public com.ovaphone.Payload doInBackground(scala.collection.Seq<com.ovaphone.Payload>);

VS

Java: protected com.ovpahone.Payload doInBackground(com.ovaphone.Payload...);

因此,Scala已将varargs转变为Seq。也许那令人困惑的Proguard?任何想法?

作为一种解决方法,我已经在我的项目中包含了该类的java版本,但是很快就能让Scala版本正常工作。

2 个答案:

答案 0 :(得分:2)

这可能有所帮助。

http://piotrbuda.eu/2012/12/scala-and-android-asynctask-implementation-problem.html

签名问题我猜错了。

我自己也遇到了同样的问题,更改签名解决了我的问题。

答案 1 :(得分:1)

您应确保ProGuard获得合适的Android运行时(android.jar)。根据您的构建过程,它会自动添加(例如Android Ant,Gradle,Eclipse),或者您必须使用选项-libraryjars自行添加(例如自定义构建)。

请注意,您可以查看ProGuard正在应用的配置

-printconfiguration config.txt

然后,您应该检查-injars-libraryjars选项。

如果没有正确的运行时jar,ProGuard通常会打印出许多警告,默认情况下拒绝继续。它需要运行时类来分析应用程序的结构。例如,在这种情况下,它需要知道运行时接口方法,因此它不会从实现中删除它们。