mmin18 / LayoutCast

Cast android code and resource changes to the running application through ADB.
1.71k stars 173 forks source link

running on android M successfully #76

Open liqk2014 opened 8 years ago

liqk2014 commented 8 years ago

first time i run my project on android M using LyoutCast, i throws "unable to initialize application for BootInflater" exception .

so i try to trace the source code , finally i found that it is beacause the Class "android.app.ContextImpl$StaticServiceFetcher" had been moved to "android.app.SystemServiceRegistry$StaticServiceFetcher",

i fix the bugs using these code:

BootInflater.java:

public static void initApplication(Application app) {
    LayoutInflater inflater = (LayoutInflater) app
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    if (inflater instanceof BootInflater) {
        // already inited
        return;
    }
    systemInflater = inflater;

    Class<?> cCtxImpl = app.getBaseContext().getClass();
    if ("android.app.ContextImpl" .equals(cCtxImpl.getName())) {
        try {
            ClassLoader bootClassLoader = cCtxImpl.getClassLoader();

            Class<?> ClassSystemServiceRegistry = bootClassLoader.loadClass("android.app.SystemServiceRegistry");

            Class<?> cStaticFetcher = bootClassLoader
                    .loadClass("android.app.SystemServiceRegistry$StaticServiceFetcher");
            Class<?> cFetcherContainer = null;
            for (int i = 1; i < 50; i++) {
                String cn = "android.app.SystemServiceRegistry$" + i;
                try {
                    Class<?> c = bootClassLoader.loadClass(cn);
                    if (cStaticFetcher.isAssignableFrom(c)) {
                        cFetcherContainer = c;
                        break;
                    }
                } catch (Exception e) {
                }
            }
            Constructor<?> cFetcherConstructor = cFetcherContainer
                    .getDeclaredConstructor();
            cFetcherConstructor.setAccessible(true);
            Object fetcher = cFetcherConstructor.newInstance();
            Field f = cStaticFetcher.getDeclaredField("mCachedInstance");
            f.setAccessible(true);
            f.set(fetcher, new BootInflater(app));
            f = ClassSystemServiceRegistry.getDeclaredField("SYSTEM_SERVICE_FETCHERS");
            f.setAccessible(true);
            HashMap<String, Object> map = (HashMap<String, Object>) f
                    .get(null);
            map.put(Context.LAYOUT_INFLATER_SERVICE, fetcher);
        } catch (Exception e) {
            throw new RuntimeException(
                    "unable to initialize application for BootInflater");
        }
    } else {
        throw new RuntimeException("application base context class "
                + cCtxImpl.getName() + " is not expected");
    }

    if (!(app.getSystemService(Context.LAYOUT_INFLATER_SERVICE) instanceof BootInflater)) {
        throw new RuntimeException(
                "unable to initialize application for BootInflater");
    }
}

now i can run my project successfully.

ipcjs commented 8 years ago

+1

kaleai commented 8 years ago

+1

onolox commented 8 years ago

I have not reviewed your code, but, make it work with both Lollipop and Marshmallow and make a pull request in mmin18 project. Great work and continue participating.