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
Ответы
Ответ 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
больше.