-1

Recently I have observed a large number of crashes for an app that I maintain when the Android P developer preview is used.

Diving (deep) into the project's code, I have found the problem method to be the following:

public static <T> T get(MatrixCursor cursor, int column) {
    try {
        cursor.moveToFirst();
        Method get = MatrixCursor.class.getDeclaredMethod("get", int.class);
        get.setAccessible(true);
        return (T) get.invoke(cursor, column);
    } catch (Exception e) {
        throw new IllegalArgumentException("Android has changed the implementation of MatrixCursor?!");
    }
}

From what I understand, this code is used to retrieve a custom object from the MatrixCursor directly, rather than a primitive type, byte array or String. There has previously been a private method within MatrixCursor that performs this internally, and it is this method that we access through reflection.

Needless to say, there's a number of issues with this approach. As far as I am aware, reflection to access private APIs is a feature that Android advises heavily against. Nevertheless, until the Android P preview, this seems to have been working as expected.

This leads me to raise the following questions:

Has MatrixCursor's implementation changed or is reflection totally deprecated as of Android P?

Sadly, I am not 100% clued up on what alternatives I have to avoid this issue. Any suggestions for that are greatly appreciated, is there a Cursor that can be used to store custom objects?

Ed Holloway-George
  • 5,092
  • 2
  • 37
  • 66
  • "Has MatrixCursor's implementation changed" -- possibly. Without a Java stack trace, we can't tell you where and how you are crashing. "is there a Cursor that can be used to store custom objects?" -- `Cursor` is an interface. Write your own implementation. – CommonsWare Jun 01 '18 at 10:50

1 Answers1

1

Yes, something has changed.

No, the underlying implementation of MatrixCursor has likely not changed.

What has changed is that Android P is introducing restrictions on non-public members of SDK classes. Attempting to use private fields or methods on SDK classes (whether by direct invocation, reflection, or JNI) will result in a crash.

If you run the code in question on a device running P and look at the logcat output, you should see a message similar to this:

Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI)

I highly encourage you to fully read the linked documentation on these restrictions for the full context and for more information on how you can handle it.

One option (which you should do ASAP if needed!) is to file a bug so the Android team knows that this is a method you use and does not have a public alternative. If you do this before the release of Android P, there is a much better likelihood that the team will either create a public alternative for this method or allow you to continue to access that method in P.

Bryan Herbst
  • 66,602
  • 10
  • 133
  • 120
  • Thank you for that clear explanation - I will raise a bug and pray the Android team takes pity on me – Ed Holloway-George May 31 '18 at 15:08
  • Good luck! From what I've been hearing, they are very receptive to working with developers on this change, and this is a huge reason they are encouraging everyone to try out the P preview- they want to know about these problems before the final release. – Bryan Herbst May 31 '18 at 15:10
  • However, this would not result in crashes. The messages appear, but do not crash the code, as of P DP2. – CommonsWare Jun 01 '18 at 10:49