Skip to content

Latest commit

 

History

History
108 lines (88 loc) · 3.55 KB

File metadata and controls

108 lines (88 loc) · 3.55 KB

Accessing private fields or methods using Reflection

This part of the guide should be used when a field or method you want to use/access is not public. There are two ways to get around non-public fields/methods.

Access methods

Sometimes, the method or field will have a static "access method" that allows you to access the private method or field from outside of the class. They are usually named something along the lines of access$_______, with the blank being the field or method name. They take in an instance of the class as the first argument, and any other method arguments should you be "accessing" a method.

Note: The examples below were taken from decompiled discord code at the time of writing this guide.

Field example
public static final int access$getToolbarHeight$p(WidgetMedia widgetMedia) {
  return widgetMedia.toolbarHeight;
}

This example method allows you to get the toolbarHeight field of WidgetMedia. It takes in a WidgetMedia instance and returns the toolbarHight.

Method example
public static final void access$handlePlayerEvent(WidgetMedia widgetMedia, AppMediaPlayer.Event event) {
    widgetMedia.handlePlayerEvent(event);
}

This example allows you to call the handlePlayerEvent of WidgetMedia, which is normally private. It simply takes

  1. The instance of WidgetMedia
  2. The argument to pass to handlePlayerEvent

To use these, simply call the method. If you are using kotlin, you have to wrap the function name in backticks, like so:

WidgetMedia.`access$handlePlayerEvent`(widgetMedia, event)

These sort of methods should be used before trying reflection, as reflection is slow and should only be used when absolutely needed.

Reflection

If the above is not possible, you can use reflection to access non-public methods/fields. Examples for both java and kotlin are shown below.

Java (method)
// Get the method
var method = ClassName.class.getDeclaredMethod("methodName");
// Make it "accessible"
method.setAccessible(true);
// Invoke it
// Note: if the method takes any arguments then add them after the classInstance argument.
// Additionally, if the method is static then just pass null for the classInstance.
var result = method.invoke(classInstance);
Java (field)
// Get the field
var field = ClassName.class.getDeclaredField("fieldName");
// Make it "accessible"
field.setAccessible(true);
// Get value
// Note: if the field is static then just pass null for the classInstance.
var value = field.get(classInstance);
Kotlin (method)
// Get the method
val method = ClassName::class.java.getDeclaredMethod("methodName").apply { 
  isAccessible = true // Make it "accessible"
}
// Invoke it
// Note: if the method takes any arguments then add them after the classInstance argument.
// Additionally, if the method is static then just pass null for the classInstance.
val result = method.invoke(classInstance)
Kotlin (field)
// Get the field
val field = ClassName::class.java.getDeclaredField("fieldName").apply { 
  isAccessible = true // Make it "accessible"
}
// Get value
// Note: if the field is static then just pass null for the classInstance.
val value = field.get(classInstance)