安卓7.0和7.1出现getApplication()类型转换异常

26
在开发者控制台中,我看到了很多像这样的堆栈跟踪崩溃信息。
java.lang.RuntimeException: 
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2984)
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3045)
  at android.app.ActivityThread.-wrap14(ActivityThread.java:0)
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1642)
  at android.os.Handler.dispatchMessage(Handler.java:102)
  at android.os.Looper.loop(Looper.java:154)
  at android.app.ActivityThread.main(ActivityThread.java:6776)
  at java.lang.reflect.Method.invoke(Native Method:0)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
Caused by: java.lang.ClassCastException: 
  at com.myapp.ui.BaseActivity.getApp(BaseActivity.java:193)
  at com.myapp.ui.BaseActivity.onCreate(BaseActivity.java:275)
  at com.myapp.ui.CastActivity.onCreate(CastActivity.java:39)
  at com.myapp.ui.MainActivity.onCreate(MainActivity.java:268)
  at android.app.Activity.performCreate(Activity.java:6955)
  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1126)
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2927)

BaseActivity的getApp方法是:

public App getApp() {
        return (App) getApplication();
    }

App 类是

public class App extends MultiDexApplication { ...

在清单应用程序标签中包含对该类的引用。

 <application
        android:name="com.myapp.App"

98%的崩溃发生在Android 7.0,其余2%发生在7.1。其他版本的Android不受影响。

编辑:我使用proguard,所以这可能与此有关,但保留类。

-keep class com.myapp.** { *;}
-keep interface com.myapp.** { *;}

注意:可能与此相关,但在某些Android版本中,似乎不会调用App的onCreate方法。我观察到这一点是因为从Service(由AlarmManager启动)或BroadcastReceiver访问时,在onCreate中创建的某些对象为空。

有人知道是什么原因导致这种情况,如何解决或绕过?谢谢

编辑2: 最终我得到了以下解决方案:

   public App getApp() {

    Application application = getApplication();
    App app = null;

    try {
        app = (App) application;
    } catch (Exception e) {
        if (application != null) {
            Log.e(TAG, "getApp Exception: application class: " + application.getClass().getName());
        } else {
            Log.e(TAG, "getApp Exception: application object is null");
        }
    }

    return app;
}

至少它不会崩溃,我可以检查getApp() == null


嗨,你找到解决方案了吗? - Siarhei
@user5599807,很遗憾不行。 - Martin Vandzura
这种崩溃有多常见?总会有一些奇怪的罕见崩溃是特定于供应商/ROM的。 - meh
1
我也在Android 8.0和8.1上遇到了这个问题。 - Highriser
5个回答

13

转换失败是因为getApplication()返回一个Application而不是所需的子类。

我曾经成功捕获了错误并要求用户重新启动设备或重新安装应用程序。

不幸的是,这种罕见崩溃没有真正的解决方法。Google不会修复与生命周期相关的问题,但称其在Android 7.1+中有所减少。来源:https://issuetracker.google.com/issues/37137009


这并没有回答问题。一旦你有足够的声望,你就可以评论任何帖子;相反,提供不需要询问者澄清的答案。- 来自审查 - lebelinoz
1
{btsdaf} - Jsyntax
Agreed. +1 from me. - lebelinoz

1

我认为你应该将getApplicationContext()转换为App


你能解释一下为什么它会有帮助吗? - Martin Vandzura
这是一种替代方案,有时在为Android编程时,我发现像这样的小改变可以消除异常。 - Tuby
问题在于某些情况下它可能无法返回应用程序对象(即 Android 的供应商实现)。 - Martin Vandzura

1
虽然我不能确定这个解决方案是否有效。我认为静态应用实例应该能够解决问题。
class MyApp extends Application {
  private static final sInstance;

  public void onCreate() {
    sInstance = this;
  }

  public static MyApp getInstance() {
    return sInstance;
  }
}

如果你调用MyApp.getInstance()而不是调用getActivity(),那么你就不需要进行强制类型转换了。这样就不会再出现ClassCastException的错误了。


0

我不需要这样做,因为MultiDexApplication已经完成了。在你分享的链接中,它说你可以扩展MultiDexApplication或覆盖attachBaseContext方法。 - Martin Vandzura
@vandzi,你能发布一下你的应用程序类onCreate吗? - Vincent
那里没有什么有用的东西,只有super.onCreate();分析初始化。我认为问题出在其他地方。 - Martin Vandzura
我重新创建了你的实现,它在我的 Android 7.0 上运行良好,我认为问题出在其他地方。 - Vincent
是的,我在报告中看到三星S7是顶级设备,但其他设备也是如此。共同点是Android 7.0。 - Martin Vandzura
显示剩余2条评论

0

这可能会有所帮助

public class App extends MultiDexApplication { 

        public static App app = null;

        public static App getInstance() {
            return app;
        }

        @Override
        public void onCreate() {
            super.onCreate();
            app = this;
        }
}

你不需要强制转换 getApplication(),因为你已经在 Application 类中了,所以只需使用 this 关键字来获取应用程序实例即可。希望你会发现这很有用。


getApp在activity中,所以我必须进行强制转换。 - Martin Vandzura
尽管在您的活动中不需要强制转换使用getApplicationContext()函数。 - Piyush Patel
获取应用程序当前进程的单个全局Application对象的上下文。 - Piyush Patel
我不想获取上下文,我想获取应用程序实例。 - Martin Vandzura
我已经回答过了,请阅读上面的陈述。全局应用程序对象(也就是App实例)。 - Piyush Patel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接