Подтвердить что ты не робот

Android 7.0 и 7.1 getApplication() ClassCastException

В консоли разработчика я вижу много сбоев с stacktrace, подобных этому

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)

Метод getApp для BaseActivity -

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

Класс приложения

public class App extends MultiDexApplication { ...

а в теге манифеста приложения содержится ссылка на этот класс

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

98% сбоев для Android 7.0, остальное - 7.1. Никаких других версий Android не влияет.

EDIT: я использую proguard, поэтому его можно каким-то образом связать, но сохраняя класс

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

Примечание. Возможно, это не так, но в тех же версиях Android это выглядит так, как иногда не вызывается метод App onCreate. Я наблюдал это, потому что некоторые объекты, созданные в onCreate, были пустыми, когда к ним обращались из Сервиса (запущенного AlarmManager) или BroadcastReceiver

Есть ли у кого-нибудь идея, что может вызвать его, как его исправить или обойти? Благодаря

ИЗМЕНИТЬ 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

4b9b3361

Ответ 1

Не удалось выполнить кастинг, потому что getApplication() возвращает Application и НЕ желаемый подкласс.

У меня был некоторый успех, когда я поймал ошибку и попросил пользователя перезагрузить свое устройство или переустановить приложение.

К сожалению, нет реального исправления этого редкого краха. Google не исправит проблему, связанную с жизненным циклом, но сказал, что она уменьшена в Android 7.1+. Источник: https://issuetracker.google.com/issues/37137009

Ответ 2

Я думаю, вы должны использовать getApplicationContext() в App вместо этого.

Ответ 3

Вы должны переопределить attachBaseContext в своем классе приложения следующим образом:

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
}

Посмотрите эту ссылку для получения дополнительной информации: https://developer.android.com/reference/android/support/multidex/MultiDexApplication.html

Ответ 4

Это может помочь

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, поэтому просто используйте это ключевое слово, чтобы получить экземпляр приложения. Надеюсь, что вы найдете полезные

Ответ 5

Пока я не могу сказать, работает ли это решение.

Я думаю, что статический экземпляр приложения должен решить проблему.

class MyApp extends Application {
  private static final sInstance;

  public void onCreate() {
    sInstance = this;
  }

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

Вместо вызова getActivity(), если вы вызываете MyApp.getInstance(), вам не нужно бросать. Поэтому не должно быть никаких ClassCastException больше.