Instance of abstract class with hidden constructor

2019-03-31 04:44发布

问题:

I need to create an instance of an abstract class with hidden constructor, the class looks like the following:

public abstract class TestClass {
    /**
    * @hide
    */
    public TestClass() {
    }
}

creating an concrete class does not work, because the constructor is not visible and calling the constructor via reflection API also doesn't work because the class is abstract.

I need to create an instance of android.print.PrintDocumentAdapter.LayoutResultCallback

回答1:

I ran into precisely the same problem (for precisely the same class even) and I have a better solution than replacing the android.jar with framework.jar as suggested in the other answer.

The solution uses the dexmaker library. (You will need dexmaker.1.4.jar and dexmaker-dx.1.4.jar). This is a library that generates bytecode at runtime for the Dalvik VM (the VM used in android).

This library has a class called ProxyBuilder that generates a proxy for an abstract class. The proxy is an object that extends the abstract class and implements the methods by dispatching them to an instance of java.lang.reflect.InvocationHandler that you specify.

ProxyBuilder is almost identical to java.lang.refect.Proxy, except that java.lang.refect.Proxy only works for interfaces, while dexmaker's ProxyBuilder works for abstract classes, which is what we need for our problem.

The code is all of:

public static PrintDocumentAdapter.LayoutResultCallback getLayoutResultCallback(InvocationHandler invocationHandler,
                                                                                File dexCacheDir) throws  IOException{
    return ProxyBuilder.forClass(PrintDocumentAdapter.LayoutResultCallback.class)
            .dexCache(dexCacheDir)
            .handler(invocationHandler)
            .build();
}

The callback logic is implemented in the invocationHandler that you provide. The cacheDir is some directory where dexmaker can store some files.



回答2:

This tutorial seems to address how to do what you are asking: https://devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-1-introduction/. I have never done this myself so I cannot vouch for it.

Be warned: there is a reason that methods in the API are hidden. The most important for developers is that there is no guarantee that the method will stick around for any length of time as the method in question is not part of any public API.