Description
When submitting an Android JME app in the Google Play Store, for target API level 30 and higher, the Play Store Console reports multiple errors. These are due to AndroidBufferAllocator accessing fields of java.nio.ByteBufferAsFloat and similar (ByteBufferAsChar, ByteBufferAsInt, etc). These classes are not part of the SDK-approved Android API, and as such their use is not allowed for API levels 30 and higher.
This is the stack trace:
StrictMode policy violation: android.os.strictmode.NonSdkApiUsedViolation: Ljava/nio/ByteBufferAsCharBuffer;->bb:Ljava/nio/ByteBuffer;
at android.os.StrictMode.lambda$static$1(StrictMode.java:407)
at android.os.-$$Lambda$StrictMode$lu9ekkHJ2HMz0jd3F8K8MnhenxQ.accept(Unknown Source:2)
at java.lang.Class.getDeclaredField(Native Method)
at com.jme3.util.AndroidBufferAllocator.<clinit>(AndroidBufferAllocator.java:70)
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:454)
at java.lang.Class.forName(Class.java:379)
at com.jme3.util.BufferAllocatorFactory.create(BufferAllocatorFactory.java:25)
at com.jme3.util.BufferUtils.<clinit>(BufferUtils.java:66)
at com.jme3.util.BufferUtils.createIntBuffer(BufferUtils.java:926)
at com.jme3.renderer.android.AndroidGL.<init>(AndroidGL.java:47)
at com.jme3.system.android.OGLESContext.initInThread(OGLESContext.java:205)
at com.jme3.system.android.OGLESContext.onSurfaceCreated(OGLESContext.java:184)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1560)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1285)
This is the static initializer of AndroidBufferAllocator where the error occurs:
static {
for (String className : wrapperClassNames) {
try {
Class clazz = Class.forName(className);
// loop for all possible field names in android
for (String fieldName : possibleBufferFieldNames) {
try {
Field field = clazz.getDeclaredField(fieldName); // <-- Problem is here
field.setAccessible(true);
fieldIndex.put(clazz, field);
break;
} catch (NoSuchFieldException e) {
}
}
} catch (ClassNotFoundException ex) {
}
}
}
Workaround: Replace AndroidBufferAllocator by an implementation which does nothing on destroyDirectBuffer(Buffer), such as PrimitiveAllocator. This can be done by setting the system property com.jme3.BufferAllocatorImplementation to the full class name of the replacing Allocator during startup / initialization.
Up until API level 29 this was not a problem, as the affected classes where gray-listed. However, recently Google made API level 30 the mandatory target level for releases on the play store.
See also forum entry AndroidBufferAllocator and NonSdkApiUsedViolation.