UdaraWanasinghe / webp-android

libwebp JNI bindings to encode a series of Android bitmap images to an animated WebP image.
MIT License
14 stars 0 forks source link

Crash on release build. #4

Closed AradiPatrik closed 1 year ago

AradiPatrik commented 1 year ago

My stacktrace

java_vm_ext.cc:594] JNI DETECTED ERROR IN APPLICATION: java_class == null
java_vm_ext.cc:594]     in call to GetStaticMethodID
java_vm_ext.cc:594]     from void com.aureusapps.android.webpandroid.decoder.WebPDecoder.nativeDecodeFrames(android.content.Context, android.net.Uri, android.net.Uri)

Also

failed to add asset path '/data/app/~~vhlm4eDw8sy8A_FHF1smtA==/my.package.name-OA6BY74EwD9N0TRiWvpPQA==/base.apk' (Ask Studio Bot)
                                                                                                    java.io.IOException: Failed to load asset path /data/app/~~vhlm4eDw8sy8A_FHF1smtA==/my.package.name-OA6BY74EwD9N0TRiWvpPQA==/base.apk
                                                                                                        at android.content.res.ApkAssets.nativeLoad(Native Method)
                                                                                                        at android.content.res.ApkAssets.<init>(ApkAssets.java:296)
                                                                                                        at android.content.res.ApkAssets.loadFromPath(ApkAssets.java:145)
                                                                                                        at android.app.ResourcesManager.loadApkAssets(ResourcesManager.java:472)
                                                                                                        at android.app.ResourcesManager.-$$Nest$mloadApkAssets(Unknown Source:0)
                                                                                                        at android.app.ResourcesManager$ApkAssetsSupplier.load(ResourcesManager.java:167)
                                                                                                        at android.app.ResourcesManager.createAssetManager(ResourcesManager.java:548)
                                                                                                        at android.app.ResourcesManager.createResourcesImpl(ResourcesManager.java:630)
                                                                                                        at android.app.ResourcesManager.findOrCreateResourcesImplForKeyLocked(ResourcesManager.java:682)
                                                                                                        at android.app.ResourcesManager.createResources(ResourcesManager.java:1028)
                                                                                                        at android.app.ResourcesManager.getResources(ResourcesManager.java:1131)
                                                                                                        at android.app.ActivityThread.getTopLevelResources(ActivityThread.java:2467)
                                                                                                        at android.app.ApplicationPackageManager.getResourcesForApplication(ApplicationPackageManager.java:2032)
                                                                                                        at android.app.ApplicationPackageManager.getResourcesForApplication(ApplicationPackageManager.java:2018)
                                                                                                        at android.app.ApplicationPackageManager.getText(ApplicationPackageManager.java:2335)
                                                                                                        at android.content.pm.PackageItemInfo.loadUnsafeLabel(PackageItemInfo.java:222)
                                                                                                        at android.content.pm.PackageItemInfo.loadLabel(PackageItemInfo.java:212)
                                                                                                        at android.app.ApplicationPackageManager.getApplicationLabel(ApplicationPackageManager.java:2380)

I added these lines to my proguard file:

-keep class com.aureusapps.android.webpandroid.decoder.** {*;}
-keep class com.aureusapps.android.webpandroid.decoder.**
-keep class com.aureusapps.android.webpandroid.encoder.** {*;}
-keep class com.aureusapps.android.webpandroid.encoder.**
-keep class com.aureusapps.android.webpandroid.decoder.WebPDecoder {*;}
-keep class com.aureusapps.android.webpandroid.decoder.WebPDecoder
-keep class com.aureusapps.android.webpandroid.decoder.WebPInfo {*;}
-keep class com.aureusapps.android.webpandroid.decoder.WebPInfo
-keep class com.aureusapps.android.webpandroid.decoder.WebPDecodeListener {*;}
-keep class com.aureusapps.android.webpandroid.decoder.WebPDecodeListener

This is how I use it (although I don't think it's relevant to my problem)

val decoder = WebPDecoder()
                val encoder = AnimatedGifEncoder()
                encoder.setRepeat(0)
                encoder.start(outputStream)
                suspendCancellableCoroutine { continuation ->
                    decoder.addDecodeListener(object : WebPDecodeListener {
                        var frameCount = AtomicInteger(0)
                        var lastFrameTimestamp = AtomicInteger(0)

                        override fun onFrameDecoded(
                            index: Int,
                            timestamp: Long,
                            bitmap: Bitmap,
                            uri: Uri?
                        ) {
                            encoder.setDelay(timestamp.toInt() - lastFrameTimestamp.get())
                            lastFrameTimestamp.set(timestamp.toInt())
                            encoder.addFrame(transform(bitmap))
                            if (index == frameCount.get() - 1) {
                                encoder.finish()
                                continuation.resume(Unit)
                            }
                        }

                        override fun onInfoDecoded(info: WebPInfo) {
                            frameCount.set(info.frameCount)
                            logcat { info.toString() }
                        }
                    })
                    decoder.decodeFrames(context, currentFile.toUri(), null)
                }

How should I modify my proguard file, or how should I configure the build.gradle to avoid the crash?

UdaraWanasinghe commented 1 year ago

Add these two lines to proguard rules

-keep class com.aureusapps.android.extensions.UriExtensionsKt {*;}
-keep class com.aureusapps.android.extensions.BitmapUtils {*;}

I used some extension functions in com.aureusapps.android.extensions package.

AradiPatrik commented 1 year ago

It didn't work. Same error. Actually I can't even find these classes in my external libraries.

image

These are the classes included in the library

AradiPatrik commented 1 year ago

My current proguard file:

-keep class com.aureusapps.android.webpandroid.decoder.** {*;}
-keep class com.aureusapps.android.webpandroid.decoder.**
-keep class com.aureusapps.android.webpandroid.encoder.** {*;}
-keep class com.aureusapps.android.webpandroid.encoder.**
-keep class com.aureusapps.android.webpandroid.decoder.WebPDecoder {*;}
-keep class com.aureusapps.android.webpandroid.decoder.WebPDecoder
-keep class com.aureusapps.android.webpandroid.decoder.WebPInfo {*;}
-keep class com.aureusapps.android.webpandroid.decoder.WebPInfo
-keep class com.aureusapps.android.webpandroid.decoder.WebPDecodeListener {*;}
-keep class com.aureusapps.android.webpandroid.decoder.WebPDecodeListener
-keep class com.aureusapps.android.extensions.UriExtensionsKt {*;}
-keep class com.aureusapps.android.extensions.BitmapUtils {*;}
AradiPatrik commented 1 year ago

https://github.com/UdaraWanasinghe/webp-android/blob/15b98312fc97c506fa64cb69731953c526f7e976/webp-android/src/main/cpp/bitmap_utils.cpp#L74

can it be that we will have to add these methods to proguard too?

AradiPatrik commented 1 year ago

I added this line to my build.gradle

    implementation("com.aureusapps.android:extensions:1.0.3")

also my proguard looks like this now:

-keep class com.aureusapps.android.webpandroid.decoder.** {*;}
-keep class com.aureusapps.android.webpandroid.decoder.**
-keep class com.aureusapps.android.webpandroid.encoder.** {*;}
-keep class com.aureusapps.android.webpandroid.encoder.**
-keep class com.aureusapps.android.webpandroid.decoder.WebPDecoder {*;}
-keep class com.aureusapps.android.webpandroid.decoder.WebPDecoder
-keep class com.aureusapps.android.webpandroid.decoder.WebPInfo {*;}
-keep class com.aureusapps.android.webpandroid.decoder.WebPInfo
-keep class com.aureusapps.android.webpandroid.decoder.WebPDecodeListener {*;}
-keep class com.aureusapps.android.webpandroid.decoder.WebPDecodeListener
-keep class com.aureusapps.android.extensions.UriExtensionsKt {*;}
-keep class com.aureusapps.android.extensions.BitmapUtils
-keep class com.aureusapps.android.extensions.BitmapUtils {*;}
-keep class android.graphics.Bitmap
-keep class android.graphics.Bitmap {*;}

still the same error

AradiPatrik commented 1 year ago

It worked finally! I added the proguard rules to my main app module and somehow it works now. Maybe my module specific proguard rule wasn't discovered.

Thanks for the help. Also maybe for future releases adding checks after every method like GetStaticMethodId in C++ and providing descriptive error messages will help future integrations.

Thanks again!