BootstrapApplication не может быть приведено к ApplicationClass

Я использую новую стабильную версию Android Studio версии 2.0. Когда я отключаю мгновенный запуск, мое приложение работает нормально, но когда я его включаю, оно выдает мне эту ошибку:

Caused by: java.lang.ClassCastException: com.android.tools.fd.runtime.BootstrapApplication cannot be cast to com.my.app.CustomApplication

CustomApplication - это класс Application, который я получаю через контекст. Но я не могу этого понять. Когда мгновенный запуск включен, мой класс преобразуется в BootstrapApplication, а затем не выполняется.

Мое приложение - это плавающий сервис, такой как FB chatheads.

У меня последняя версия Gradle:

classpath 'com.android.tools.build:gradle:2.0.0'

Другие ответы здесь говорят, что мгновенный Run пытается выполнить горячую замену кода; это вызывает перемещение класса приложения.

Так как я могу обойти это?

2 ответа

Решение

Решение № 1 - отключить мгновенный запуск в настройках

Решение № 2 - Получить реальное приложение из BootstrapApplication, используя отражение

public static CustomApplication getRealApplication (Context applicationContext)
{
    CustomApplication application = null;

    if (applicationContext instanceof CustomApplication)
    {
        application = (CustomApplication) applicationContext;
    }
    else
    {
        Application realApplication = null;
        Field magicField = null;
        try
        {
            magicField = applicationContext.getClass().getDeclaredField("realApplication");
            magicField.setAccessible(true);
            realApplication = (Application) magicField.get(applicationContext);
        }
        catch (NoSuchFieldException e)
        {
            Log.e(TAG, e.getMessage());
        }
        catch (IllegalAccessException e)
        {
            Log.e(TAG, e.getMessage());
        }

        application = (CustomApplication) realApplication;
    }

    return application;
}

Используя где-то:

    Context applicationContext = getContext().getApplicationContext();
    CustomApplication application = getRealApplication(applicationContext);

Пример использования:

public class MyProvider extends OrmLiteProvider<OrmLiteSqliteOpenHelper, OrmLiteUriMatcher<OrmLiteMatcherEntry>>
{
    @Override
    protected OrmLiteSqliteOpenHelper createHelper ()
    {
        Context applicationContext = getContext().getApplicationContext();
        CustomApplication application = CustomApplication.getRealApplication(applicationContext);
        return application.getComponent().databaseHelper();
    }

   ...

}

public static CustomApplication getRealApplication (Context applicationContext)
{
    CustomApplication application = null;

    if (applicationContext instanceof CustomApplication)
    {
        application = (CustomApplication) applicationContext;
    } else if (applicationContext.getApplicationContext() instanceof CustomApplication) {
        application = (CustomApplication) applicationContext.getApplicationContext() ;
    }
    else
    {
        Application realApplication = null;
        Field magicField = null;
        try
        {
            magicField = applicationContext.getClass().getDeclaredField("realApplication");
            magicField.setAccessible(true);
            realApplication = (Application) magicField.get(applicationContext);
        }
        catch (NoSuchFieldException e)
        {
            Log.e(TAG, e.getMessage());
        }
        catch (IllegalAccessException e)
        {
            Log.e(TAG, e.getMessage());
        }

        application = (CustomApplication) realApplication;
    }

    return application;
}

в решении № 2 я добавляю один случай

Другие вопросы по тегам