最近,我观察到我使用Android P开发人员预览时维护的应用程序的大量崩溃。
深入到项目代码中,我发现问题方法如下:
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?!"); } }据我所知,这段代码用于直接从MatrixCursor中检索自定义对象,而不是原始类型,字节数组或字符串。 之前在MatrixCursor中有一个私有方法 ,它在内部执行此操作,并且这是我们通过反射访问的方法。
不用说,这种方法存在很多问题。 据我所知,访问私有API的反思是Android 强烈反对的一个功能。 不过,在Android P预览之前,这似乎一直按预期工作。
这导致我提出以下问题:
从Android P开始, MatrixCursor的实现是否已更改或完全弃用?
可悲的是,我并不是100%提供了我必须避免这个问题的替代方案。 任何建议都不胜感激,有没有可用于存储自定义对象的光标?
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?
最满意答案
是的,事情已经改变了。
不, MatrixCursor的底层实现可能没有改变。
改变之处在于Android P正在对SDK类的非公共成员实施限制 。 试图在SDK类上使用专用字段或方法(无论是通过直接调用,反射还是JNI)都会导致崩溃。
如果您在运行P的设备上运行代码并查看logcat输出,则应该看到类似如下的消息:
Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI)
我强烈建议您完整阅读关于这些限制条件的链接文档以了解完整的上下文以及有关如何处理它的更多信息。
一个选项(如果需要的话,你应该尽快做出)是提交一个bug,以便Android团队知道这是一种你使用的方法,没有公共选择。 如果您在Android P发布之前执行此操作,则团队可能会为该方法创建公共替代方案或允许您在P中继续访问该方法的可能性更大。
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.
更多推荐
发布评论