lundi 10 juin 2019

Use reflection to get private fields from hidden Android AOSP class

I am trying to use reflection to access a private final field from ActivityView class, which is hidden in Android AOSP. I created an ActivityView object using reflection, which has a SurfaceView inside, and i need to have a callback which tells me when the surface is created.

val activityViewClass = Class.forName("android.app.ActivityView")
val activityView = activityViewClass.getConstructor(Context::class.java).newInstance(this)

Then, there are two options to have access to that callback:

1. Access directly the private final callback field from the class.

So i try to access mSurfaceCallback field which throws java.lang.NoSuchFieldException.

val field = activityView::class.java.getDeclaredField("mSurfaceCallback")

If i try to access any other private field i get the same error.

If i call activityView::class.java.declaredFields i get an empty list.

I tried in Java, in Kotlin with kotlin-reflect library and no success.

I also tried https://github.com/ronmamo/reflections library for reflection, i get the same results.

2. Set a ActivityView.StateCallback to the activity view.

ActivityView has a StateCallback object which looks like this:

/** Callback that notifies when the container is ready or destroyed. */ public abstract static class StateCallback { /** * Called when the container is ready for launching activities. Calling * {@link #startActivity(Intent)} prior to this callback will result in an * {@link IllegalStateException}. * * @see #startActivity(Intent) */ public abstract void onActivityViewReady(ActivityView view); /** * Called when the container can no longer launch activities. Calling * {@link #startActivity(Intent)} after this callback will result in an * {@link IllegalStateException}. * * @see #startActivity(Intent) */ public abstract void onActivityViewDestroyed(ActivityView view); /** * Called when a task is moved to the front of the stack inside the container. * This is a filtered version of {@link TaskStackListener} */ public void onTaskMovedToFront(ActivityManager.StackInfo stackInfo) { } }

This is exactly what i need. But since it is an abstract class i cannot instantiate it. And i also cannot extend it because it is hidden.

Any ideas how to access that private field or how to extend a hidden abstract class using reflection?





Aucun commentaire:

Enregistrer un commentaire