Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Google Play Store Console pre-launch report shows errors due to usage of non-SDK API classes #1678

Closed
digitprop opened this issue Nov 23, 2021 · 3 comments · Fixed by #1821
Closed
Labels
Milestone

Comments

@digitprop
Copy link

digitprop commented Nov 23, 2021

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.

@pavly-gerges
Copy link
Contributor

As suggested by @Ali-RS , we will try to migrate AndroidBufferAllocator to a native binding, if we managed to make it, would you mind to test it ? I can ping you here when it's available for a public use....

@pavly-gerges
Copy link
Contributor

This has nothing to do with the fix...

I was testing some android apps today, and i noticed these in logcat :

W/ojmesurfacevie: Accessing hidden method Lsun/nio/ch/DirectBuffer;->attachment()Ljava/lang/Object; (blacklist, reflection, denied)
W/ojmesurfacevie: Accessing hidden field Ljava/nio/ByteBufferAsFloatBuffer;->bb:Ljava/nio/ByteBuffer; (blacklist, reflection, denied)
    Accessing hidden field Ljava/nio/ByteBufferAsIntBuffer;->bb:Ljava/nio/ByteBuffer; (blacklist, reflection, denied)
    Accessing hidden field Ljava/nio/ByteBufferAsDoubleBuffer;->bb:Ljava/nio/ByteBuffer; (blacklist, reflection, denied)
    Accessing hidden field Ljava/nio/ByteBufferAsShortBuffer;->bb:Ljava/nio/ByteBuffer; (blacklist, reflection, denied)
    Accessing hidden field Ljava/nio/ByteBufferAsLongBuffer;->bb:Ljava/nio/ByteBuffer; (blacklist, reflection, denied)
W/ojmesurfacevie: Accessing hidden field Ljava/nio/ByteBufferAsCharBuffer;->bb:Ljava/nio/ByteBuffer; (blacklist, reflection, denied)

They implies what @digitprop has stated, so they are considered blacklist and of denied access...

Off topic note :
Android internals use java reflection a lot, it appears through the logcat as well, but of greylist and allowed access (as they considered somehow sdk api calls) :
For example :

W/ojmesurfacevie: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
W/ojmesurfacevie: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)

I can also see some reflection api calls that are denied as well (but don't know why, still searching to get better understanding of logs).

@digitprop
Copy link
Author

@Scrappers-glitch Sorry for the late reply! I'd be happy to test the migration to a native binding. If you ping me I'll try it out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
4 participants