androidinstant-run

BootstrapApplication cannot be cast to ApplicationClass


I'm running the new stable release of Android Studio ver 2.0. When I disable instant run my app runs fine, but when I turn it on it gives me this error:

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

CustomApplication is an Application class that I get through a context. But I can't seem to get it. When instant run is on, my class is cast as BootstrapApplication then fails.

My app is a floating service like FB chatheads.

I have the latest gradle build:

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

Other answers here say that instant Run tries to do hot swapping of code; this causes the application class to be moved.

So how can I get around this?


Solution

  • Solution #1 - Disable Instant run in Settings

    Solution #2 - Get real application from BootstrapApplication using reflection

    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;
    }
    

    Using somewhere:

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

    Example of use:

    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();
        }
    
       ...
    
    }