Android icon indicating copy to clipboard operation
Android copied to clipboard

Widget: support card images below Android 12L (API 32)

Open TheLastProject opened this issue 4 months ago • 17 comments

Thanks for the new widget! Great! But there is a problem: if the cards have no pictures, everything works. If you add a picture to at least one card, the application closes with an error and the widget becomes invisible. If you delete the widget, the application works again. Android 7.1.2 LOS 14 The widget for one card works without problems.

Originally posted by @midnightler in #2351

TheLastProject avatar Sep 04 '25 16:09 TheLastProject

Hi @midnightler,

Thanks for the report. I can't reproduce this though, I do have a card with an image and it works fine.

Do you have more info on "closes with an error"? A stack trace perhaps? Perhaps you can create an export file that does crash the widget so I can reproduce it locally?

TheLastProject avatar Sep 04 '25 16:09 TheLastProject

Tell me how to do this? I can provide logcat.

log.zip

midnightler avatar Sep 05 '25 03:09 midnightler

Thanks for the logcat!

I'm seeing 2 exceptions in here.

One seems to be some weird image decoding thing that I've never seen before, not sure how relevant (minimized because probably not it):

Probably irrelevant exception
09-05 09:30:39.243  1261  2215 I ActivityManager: Start proc 3818:me.hackerchick.catima/u0a288 for activity me.hackerchick.catima/protect.card_locker.MainActivity
09-05 09:30:39.315  3818  3818 W System  : ClassLoader referenced unknown path: /data/app/me.hackerchick.catima-1/lib/arm64
09-05 09:30:39.422  3818  3818 I art     : Rejecting re-init on previously-failed class java.lang.Class<protect.card_locker.Utils$$ExternalSyntheticLambda6>: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/graphics/ImageDecoder$OnHeaderDecodedListener;
09-05 09:30:39.422  3818  3818 I art     :   at android.content.Context protect.card_locker.Utils.updateBaseContextLocale(android.content.Context) (Utils.java:747)
09-05 09:30:39.422  3818  3818 I art     :   at void protect.card_locker.CatimaAppCompatActivity.attachBaseContext(android.content.Context) (CatimaAppCompatActivity.java:23)
09-05 09:30:39.422  3818  3818 I art     :   at void android.app.Activity.attach(android.content.Context, android.app.ActivityThread, android.app.Instrumentation, android.os.IBinder, int, android.app.Application, android.content.Intent, android.content.pm.ActivityInfo, java.lang.CharSequence, android.app.Activity, java.lang.String, android.app.Activity$NonConfigurationInstances, android.content.res.Configuration, java.lang.String, com.android.internal.app.IVoiceInteractor, android.view.Window) (Activity.java:6620)
09-05 09:30:39.422  3818  3818 I art     :   at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2618)
09-05 09:30:39.422  3818  3818 I art     :   at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:2751)
09-05 09:30:39.422  3818  3818 I art     :   at void android.app.ActivityThread.-wrap12(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1)
09-05 09:30:39.422  3818  3818 I art     :   at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1496)
09-05 09:30:39.422  3818  3818 I art     :   at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:102)
09-05 09:30:39.422  3818  3818 I art     :   at void android.os.Looper.loop() (Looper.java:154)
09-05 09:30:39.422  3818  3818 I art     :   at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6186)
09-05 09:30:39.422  3818  3818 I art     :   at java.lang.Object java.lang.reflect.Method.invoke!(java.lang.Object, java.lang.Object[]) (Method.java:-2)
09-05 09:30:39.422  3818  3818 I art     :   at void com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run() (ZygoteInit.java:889)
09-05 09:30:39.422  3818  3818 I art     :   at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:779)
09-05 09:30:39.422  3818  3818 I art     : Caused by: java.lang.ClassNotFoundException: Didn't find class "android.graphics.ImageDecoder$OnHeaderDecodedListener" on path: DexPathList[[zip file "/data/app/me.hackerchick.catima-1/base.apk"],nativeLibraryDirectories=[/data/app/me.hackerchick.catima-1/lib/arm64, /system/lib64, /vendor/lib64]]
09-05 09:30:39.422  3818  3818 I art     :   at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:56)
09-05 09:30:39.422  3818  3818 I art     :   at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:380)
09-05 09:30:39.422  3818  3818 I art     :   at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312)
09-05 09:30:39.422  3818  3818 I art     :   at android.content.Context protect.card_locker.Utils.updateBaseContextLocale(android.content.Context) (Utils.java:747)
09-05 09:30:39.422  3818  3818 I art     :   at void protect.card_locker.CatimaAppCompatActivity.attachBaseContext(android.content.Context) (CatimaAppCompatActivity.java:23)
09-05 09:30:39.422  3818  3818 I art     :   at void android.app.Activity.attach(android.content.Context, android.app.ActivityThread, android.app.Instrumentation, android.os.IBinder, int, android.app.Application, android.content.Intent, android.content.pm.ActivityInfo, java.lang.CharSequence, android.app.Activity, java.lang.String, android.app.Activity$NonConfigurationInstances, android.content.res.Configuration, java.lang.String, com.android.internal.app.IVoiceInteractor, android.view.Window) (Activity.java:6620)
09-05 09:30:39.422  3818  3818 I art     :   at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2618)
09-05 09:30:39.422  3818  3818 I art     :   at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:2751)
09-05 09:30:39.422  3818  3818 I art     :   at void android.app.ActivityThread.-wrap12(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1)
09-05 09:30:39.422  3818  3818 I art     :   at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1496)
09-05 09:30:39.422  3818  3818 I art     :   at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:102)
09-05 09:30:39.422  3818  3818 I art     :   at void android.os.Looper.loop() (Looper.java:154)
09-05 09:30:39.422  3818  3818 I art     :   at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6186)
09-05 09:30:39.422  3818  3818 I art     :   at java.lang.Object java.lang.reflect.Method.invoke!(java.lang.Object, java.lang.Object[]) (Method.java:-2)
09-05 09:30:39.422  3818  3818 I art     :   at void com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run() (ZygoteInit.java:889)
09-05 09:30:39.422  3818  3818 I art     :   at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:779)

One seems to actually directly relate to the widget:

09-05 09:30:52.169  3818  3818 E AndroidRuntime: FATAL EXCEPTION: main
09-05 09:30:52.169  3818  3818 E AndroidRuntime: Process: me.hackerchick.catima, PID: 3818
09-05 09:30:52.169  3818  3818 E AndroidRuntime: java.lang.RuntimeException: Unable to start receiver protect.card_locker.ListWidget: java.lang.RuntimeException: Tried to marshall a Parcel that contained Binder objects.
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at android.app.ActivityThread.handleReceiver(ActivityThread.java:3072)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at android.app.ActivityThread.-wrap18(ActivityThread.java)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1580)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:102)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:154)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:6186)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: Caused by: java.lang.RuntimeException: Tried to marshall a Parcel that contained Binder objects.
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at android.os.Parcel.nativeMarshall(Native Method)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at android.os.Parcel.marshall(Parcel.java:452)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at androidx.core.widget.RemoteViewsCompatService$RemoteViewsCompatServiceData$Companion.serializeToBytes$core_remoteviews_release(RemoteViewsCompatService.kt:254)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at androidx.core.widget.RemoteViewsCompatService$RemoteViewsCompatServiceData$Companion.create(RemoteViewsCompatService.kt:174)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at androidx.core.widget.RemoteViewsCompatService$Companion.saveItems(RemoteViewsCompatService.kt:315)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at androidx.core.widget.RemoteViewsCompat.setRemoteAdapter(RemoteViewsCompat.kt:87)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at protect.card_locker.ListWidget.onUpdate(ListWidget.kt:81)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at android.appwidget.AppWidgetProvider.onReceive(AppWidgetProvider.java:66)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	at android.app.ActivityThread.handleReceiver(ActivityThread.java:3065)
09-05 09:30:52.169  3818  3818 E AndroidRuntime: 	... 8 more

Caused by: java.lang.RuntimeException: Tried to marshall a Parcel that contained Binder objects. sounds interesting and probably the case. I wonder why:

  1. It doesn't happen on my devices
  2. It doesn't seem to happen for most people

The Google Play Console seems to have also logged this crash twice: once on an Android 9 device (Rakuten C330) and once on an Android 10 device (HONOR HWHRY-HF).

The two crashes on Google Play point to the same line: https://github.com/CatimaLoyalty/Android/blob/d936209b0e96ed2d03a7f0cd9792c2db52dfacd3/app/src/main/java/protect/card_locker/ListWidget.kt#L81-L87

I don't know yet what is going on, but seeing the crash info is useful. Still, it will be hard to test possible fixes if it doesn't happen on any of my devices.

Is there any chance you could create a minimal export file that triggers the crash, so hopefully with that export file it'll start crashing on my device too? You'll want to first make an export of your actual data using the export menu, then delete/change everything you don't want to share but make sure it still crashes and then export and share that. I know that's a lot of work but if we have an example export that actually crashes it would make reproducing and debugging this easier :)

TheLastProject avatar Sep 06 '25 10:09 TheLastProject

data.zip

midnightler avatar Sep 06 '25 13:09 midnightler

I'm probably the only one using such an old android. :-D

If it's hard, it's not worth doing for one user.

midnightler avatar Sep 06 '25 13:09 midnightler

Sadly the export doesn't cause a crash to me. Just to make sure that importing/exporting it doesn't cause a change that "fixes" the crash (like resizing the images), could you delete your data and import the export you sent me and see if it still crashes?

TheLastProject avatar Sep 06 '25 17:09 TheLastProject

The problem is not in import or export. Export and import themselves are without problems. I think the problem is that the widget cannot load (or display) the image assigned to the card. For example: I import a database of cards that have images assigned. After importing, I immediately delete the images for all cards. Now I make a widget with all card. The widget works, the application works. But if I now assign an image to any card, the application closes with an error. To make it work again, I need to delete the widget.

midnightler avatar Sep 07 '25 11:09 midnightler

Vid.zip

midnightler avatar Sep 07 '25 11:09 midnightler

I understand what you mean! I'm not saying the issue is in the importer, I'm just asking if you can please try if it is still broken when you import the export you shared because I tried importing your export on my phone and it isn't crashing for me. So I want to know for sure that Catima didn't do anything to the import/export file (like resizing the images) that "fixes" the crash.

I know it can sound a bit weird, but I'm just trying to figure out why it crashes for you but not for me :)

TheLastProject avatar Sep 07 '25 17:09 TheLastProject

Just adding a me to, to this one, exception is basically the same. Device is a phone running Android 11. I only get the below crash, I don't get the 'probably irrelevant' ImageDecoder exception that @midnightler's logcat showed. I have a mix of cards with,without images. Interestingly the widget is created but due to the crash appears invisible. I can resize the empty widget and remove it but no content from Catima ever appears.

09-10 18:20:48.722 31245-31245/? W/System: ClassLoader referenced unknown path: 
09-10 18:20:49.077 24217-24230/? W/kerchick.catim: Reducing the number of considered missed Gc histogram windows from 832 to 100
09-10 18:20:49.082 24217-24232/? W/System: A resource failed to call close. 
09-10 18:20:49.083 24217-24232/? W/System: A resource failed to call close. 
09-10 18:20:49.317 24217-24232/? W/System: A resource failed to call close. 
09-10 18:20:49.317 24217-24232/? W/System: A resource failed to call close. 
09-10 18:20:49.368 24217-24217/? E/AndroidRuntime: [ERB] CRASH: main in me.hackerchick.catima(24217)
09-06 08:19:31.510 567-567/? A/libc: crash_dump helper failed to exec
09-10 18:20:49.373 24217-24217/? E/AndroidRuntime: FATAL EXCEPTION: main
                                                   Process: me.hackerchick.catima, PID: 24217
                                                   java.lang.RuntimeException: Unable to start receiver protect.card_locker.ListWidget: java.lang.RuntimeException: Tried to marshall a Parcel that contained Binder objects.
                                                       at android.app.ActivityThread.handleReceiver(ActivityThread.java:4036)
                                                       at android.app.ActivityThread.access$1400(ActivityThread.java:238)
                                                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1925)
                                                       at android.os.Handler.dispatchMessage(Handler.java:106)
                                                       at android.os.Looper.loop(Looper.java:223)
                                                       at android.app.ActivityThread.main(ActivityThread.java:7701)
                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:610)
                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:952)
                                                    Caused by: java.lang.RuntimeException: Tried to marshall a Parcel that contained Binder objects.
                                                       at android.os.Parcel.nativeMarshall(Native Method)
                                                       at android.os.Parcel.marshall(Parcel.java:580)
                                                       at androidx.core.widget.RemoteViewsCompatService$RemoteViewsCompatServiceData$Companion.serializeToBytes$core_remoteviews_release(RemoteViewsCompatService.kt:254)
                                                       at androidx.core.widget.RemoteViewsCompatService$RemoteViewsCompatServiceData$Companion.create(RemoteViewsCompatService.kt:174)
                                                       at androidx.core.widget.RemoteViewsCompatService$Companion.saveItems(RemoteViewsCompatService.kt:315)
                                                       at androidx.core.widget.RemoteViewsCompat.setRemoteAdapter(RemoteViewsCompat.kt:87)
                                                       at protect.card_locker.ListWidget.onUpdate(ListWidget.kt:81)
                                                       at android.appwidget.AppWidgetProvider.onReceive(AppWidgetProvider.java:66)
                                                       at android.app.ActivityThread.handleReceiver(ActivityThread.java:4027)
                                                       at android.app.ActivityThread.access$1400(ActivityThread.java:238) 
                                                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1925) 
                                                       at android.os.Handler.dispatchMessage(Handler.java:106) 
                                                       at android.os.Looper.loop(Looper.java:223) 
                                                       at android.app.ActivityThread.main(ActivityThread.java:7701) 
                                                       at java.lang.reflect.Method.invoke(Native Method) 
                                                       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:610) 
                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:952) 
09-10 18:20:49.389 1242-3989/? W/ActivityTaskManager:   Force finishing activity me.hackerchick.catima/protect.card_locker.LoyaltyCardViewActivity
09-10 18:20:49.563 1242-2570/? W/InputDispatcher: Attempted to unregister already unregistered input channel 'd40565c me.hackerchick.catima/protect.card_locker.LoyaltyCardViewActivity (server)'

benjsc avatar Sep 10 '25 09:09 benjsc

So did a little more testing to help with debugging.

Catima version 2.37.0

  1. Single card, no image, card list widget works
  2. Two cards, no image, card list widget works
  3. Two cards, 1 front image, not set as card display, card list widget works
  4. Two cards, 1 front image, set as card display, card list widget displays blank, catima app crashes.

I tried the data.zip file posted in this issue thread but it didn't import any cards.

The attached broken.zip shows 2 cards, 1 with an image, 1 without, image is set as card display. If I display the widget it shows as empty. Starting catima immediately has it crash. I had to delete the empty widget to do the export of the file.

The same image shows fine in a card shortcut widget.

Granted the images is large (just a photo of my car's windscreen I grabbed for testing), but hopefully helps with a test case for debugging.

benjsc avatar Sep 10 '25 09:09 benjsc

Android 7, 9, 10 and 11 reports. Interesting. That's a wide range.

I was thinking: maybe it's a memory issue and this happens only in low memory situations (given the older Android versions) so I tried it on my old Fairphone 3 (still Android 15) but... no issue, not even with the broken.zip file.

So, assuming the broken.zip is really broken (same question I asked @midnightler: please make sure importing the export yourself still causes the crash, to make sure the import/export doesn't fix it by resizing images or anything), it seems to be specific to those Android versions? Maybe an Android bug?

Hard to track this one down, might need messing around in an emulator. I'm very hesitant to make code changes which I can't test, so without being able to reproduce it it's quite a pain for me.

TheLastProject avatar Sep 10 '25 11:09 TheLastProject

@benjsc The data.zip file contains other files inside. It needs to be unzipped.

midnightler avatar Sep 10 '25 13:09 midnightler

Tested the import one more time. There is no difference - if I import a file with a picture or just add pictures. The result is the same.

midnightler avatar Sep 10 '25 13:09 midnightler

Vid2.zip

midnightler avatar Sep 10 '25 13:09 midnightler

For statistics: On miui 14 android 13 it works without problems. And if you just add pictures to the maps, and if you import a file with pictures.

midnightler avatar Sep 10 '25 13:09 midnightler

Testing in emulators, it seems to crash all the way up to Android 12 (API 31) but not Android 12L (API 32).

It starts crashing already from the lowest version supporting icons (Android 6: API 23).

I've made https://github.com/CatimaLoyalty/Android/pull/2670 as a test, from my emulator testing that seems to be a workaround for the crash. But how to properly fix it is not yet clear to me.

TheLastProject avatar Sep 10 '25 21:09 TheLastProject