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

Invalid resource ID crashes the app #413

Closed
TWiStErRob opened this issue Apr 14, 2015 · 3 comments
Closed

Invalid resource ID crashes the app #413

TWiStErRob opened this issue Apr 14, 2015 · 3 comments
Labels
Milestone

Comments

@TWiStErRob
Copy link
Collaborator

Glide Version/Integration library (if any): 3.6.0-SNAPSHOT
Device/Android Version: S4/4.4
Issue details/Repro steps: When Glide receives an invalid resource ID it leads to a crashing application. The expected behaviour would be to display the .error() image (if any) and call onException with the Resources$NotFoundException instance and the invalid resource ID as model.

Please note that all the other cases I could think of are gracefully (and most of the time correctly) handled. See other cases. below the stack trace.

Glide load line:

Glide.with(context)
     .fromResource()
     .load(0) // any non-existent resource ID, 123456789 too
     .listener(new RequestListener<Integer, GlideDrawable>() {
           @Override public boolean onException(...) { Log.d(...); return false; }
           @Override public boolean onResourceReady(...) { Log.d(...); return false; }
     })
     .into(imageView)
;

Stack trace:

27.797  10716-10716 W/ResourceType﹕ No known package when getting name for resource number 0x075bcd15
27.797  10716-10716 D/AndroidRuntime﹕ Shutting down VM
27.797  10716-10716 W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x418cbda0)
27.797  10716-10716 E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: net.twisterrob.app, PID: 10716
    java.lang.RuntimeException: Unable to start activity ComponentInfo{net.twisterrob.app/net.twisterrob.app.GlideActivity}: android.content.res.Resources$NotFoundException: Unable to find resource ID #0x75bcd15
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2305)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2363)
            at android.app.ActivityThread.access$900(ActivityThread.java:161)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1265)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:157)
            at android.app.ActivityThread.main(ActivityThread.java:5356)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: android.content.res.Resources$NotFoundException: Unable to find resource ID #0x75bcd15
            at android.content.res.Resources.getResourcePackageName(Resources.java:2708)
            at com.bumptech.glide.load.model.ResourceLoader.getResourceFetcher(ResourceLoader.java:32)
            at com.bumptech.glide.load.model.ResourceLoader.getResourceFetcher(ResourceLoader.java:16)
            at com.bumptech.glide.load.model.ImageVideoModelLoader.getResourceFetcher(ImageVideoModelLoader.java:39)
            at com.bumptech.glide.request.GenericRequest.onSizeReady(GenericRequest.java:417)
            at com.bumptech.glide.request.target.ViewTarget$SizeDeterminer.getSize(ViewTarget.java:166)
            at com.bumptech.glide.request.target.ViewTarget.getSize(ViewTarget.java:72)
            at com.bumptech.glide.request.GenericRequest.begin(GenericRequest.java:261)
            at com.bumptech.glide.manager.RequestTracker.runRequest(RequestTracker.java:36)
            at com.bumptech.glide.GenericRequestBuilder.into(GenericRequestBuilder.java:616)
            at com.bumptech.glide.GenericRequestBuilder.into(GenericRequestBuilder.java:652)
            at com.bumptech.glide.DrawableRequestBuilder.into(DrawableRequestBuilder.java:436)
            at net.twisterrob.app.GlideActivity.onCreate(GlideActivity.java:23)
            at android.app.Activity.performCreate(Activity.java:5426)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2269)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2363)
            at android.app.ActivityThread.access$900(ActivityThread.java:161)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1265)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:157)
            at android.app.ActivityThread.main(ActivityThread.java:5356)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
            at dalvik.system.NativeStart.main(Native Method)

Other Cases

Some parts of the log were cut for brevity.

R.drawable.image

Source: a valid png/jpg file.
Result: all is fine.

20.480    8830-8830 D/GLIDE﹕ onResourceReady(com.bumptech.glide.load.resource.bitmap.GlideBitmapDrawable@42b52840, 2130837560, Target for: android.widget.ImageView{42a9b690 V.ED.... ......ID 0,0-150,150 #7f090023 app:id/image}, false)
R.drawable.drawable

Source: A valid xml drawable, e.g. a <shape>.
Result: BitmapFactory returns null, see #350.

52.270  13649-13675 D/skia﹕ --- SkImageDecoder::Factory returned null
52.410  13649-13649 D/GLIDE﹕ onException(null, 2130837561, Target for: android.widget.ImageView{42a9ae40 V.ED.... ......ID 0,0-150,150 #7f090023 app:id/image}, true)
R.string.app_name

Source: any resource defined in values/*.xml so it doesn't have a full file associated to it.
Result: exception is expected and nicely forwarded.

50.358    9457-9457 D/GLIDE﹕ onException(java.io.FileNotFoundException: Resource does not exist: android.resource://net.twisterrob.app/string/app_name, 2131427328, Target for: android.widget.ImageView{42a9e6c0 V.ED.... ......ID 0,0-150,150 #7f090023 app:id/image}, true)
    java.io.FileNotFoundException: Resource does not exist: android.resource://net.twisterrob.app/string/app_name
            at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:900)
            at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:835)
            at com.bumptech.glide.load.data.FileDescriptorLocalUriFetcher.loadResource(FileDescriptorLocalUriFetcher.java:21)
            at com.bumptech.glide.load.data.FileDescriptorLocalUriFetcher.loadResource(FileDescriptorLocalUriFetcher.java:14)
            at com.bumptech.glide.load.data.LocalUriFetcher.loadData(LocalUriFetcher.java:44)
            at com.bumptech.glide.load.model.ImageVideoModelLoader$ImageVideoFetcher.loadData(ImageVideoModelLoader.java:83)
            at com.bumptech.glide.load.model.ImageVideoModelLoader$ImageVideoFetcher.loadData(ImageVideoModelLoader.java:53)
            at com.bumptech.glide.load.engine.DecodeJob.decodeSource(DecodeJob.java:170)
            at com.bumptech.glide.load.engine.DecodeJob.decodeFromSource(DecodeJob.java:128)
            at com.bumptech.glide.load.engine.EngineRunnable.decodeFromSource(EngineRunnable.java:122)
            at com.bumptech.glide.load.engine.EngineRunnable.decode(EngineRunnable.java:101)
            at com.bumptech.glide.load.engine.EngineRunnable.run(EngineRunnable.java:58)
            at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
            at java.util.concurrent.FutureTask.run(FutureTask.java:237)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:841)
            at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor$DefaultThreadFactory$1.run(FifoPriorityThreadPoolExecutor.java:52)
R.layout.main

Source: any resource that has a file associated with it but is not a valid image file (e.g. layout, anim).
Result: BitmapFactory returns null, this time correctly.

17.622   9907-10147 D/skia﹕ --- SkImageDecoder::Factory returned null
17.652    9907-9907 D/GLIDE﹕ onException(null, 2130968603, Target for: android.widget.ImageView{42b44270 V.ED.... ......ID 0,0-150,150 #7f090023 app:id/image}, true)
null

Source: nothing.
Result: no exception, but forwarded to onException, acceptable, but see #268.

48.669  10358-10358 D/GLIDE﹕ onException(null, null, Target for: android.widget.ImageView{42ad4c40 V.ED.... ......I. 0,0-0,0 #7f090023 app:id/image}, true)
@TWiStErRob
Copy link
Collaborator Author

The above happens for fixed size or wrap_content:

    <ImageView
        android:id="@+id/image"
        android:layout_width="50dp"
        android:layout_height="50dp"
        />

When the image view has match_parent for both dimensions, the stack is different, but still crashes the whole app:

23.315  W/ResourceType﹕ No package identifier when getting name for resource number 0x00000000
23.315  16041-16041 D/AndroidRuntime﹕ Shutting down VM
23.315  16041-16041 W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x418cbda0)
23.325  16041-16041 E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: net.twisterrob.app, PID: 16041
    android.content.res.Resources$NotFoundException: Unable to find resource ID #0x0
            at android.content.res.Resources.getResourcePackageName(Resources.java:2708)
            at com.bumptech.glide.load.model.ResourceLoader.getResourceFetcher(ResourceLoader.java:32)
            at com.bumptech.glide.load.model.ResourceLoader.getResourceFetcher(ResourceLoader.java:16)
            at com.bumptech.glide.load.model.ImageVideoModelLoader.getResourceFetcher(ImageVideoModelLoader.java:39)
            at com.bumptech.glide.request.GenericRequest.onSizeReady(GenericRequest.java:417)
            at com.bumptech.glide.request.target.ViewTarget$SizeDeterminer.notifyCbs(ViewTarget.java:132)
            at com.bumptech.glide.request.target.ViewTarget$SizeDeterminer.checkCurrentDimens(ViewTarget.java:148)
            at com.bumptech.glide.request.target.ViewTarget$SizeDeterminer.access$000(ViewTarget.java:116)
            at com.bumptech.glide.request.target.ViewTarget$SizeDeterminer$SizeDeterminerLayoutListener.onPreDraw(ViewTarget.java:247)
            at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:879)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2131)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1236)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6471)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:803)
            at android.view.Choreographer.doCallbacks(Choreographer.java:603)
            at android.view.Choreographer.doFrame(Choreographer.java:573)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:789)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:157)
            at android.app.ActivityThread.main(ActivityThread.java:5356)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
            at dalvik.system.NativeStart.main(Native Method)

@sjudd
Copy link
Collaborator

sjudd commented Apr 15, 2015

Why should attempting to load an invalid resource id not crash? Unlike most other things, we expect resource ids to be constants. You typically know at compile time which ids will work and which wont? I'm curious what your use case is?

@TWiStErRob
Copy link
Collaborator Author

In a simple answer: because it's not consistent with the rest of the library. I can't think of any other Glide...load(???) that will crash the whole app. Just because an image is not available it shouldn't crash, that's why we have .error() and onException. I think the strongest argument is that null doesn't crash it, which is a worse value for a resource ID than 0.

This is actually not a theoretical issue. I ran into it yesterday. I have the images for categories as res/raw/*.svg. The items in my DB can have a category associated to them by a column which refers to the above mentioned svg files by name. The name is then resolved by calling:

@RawRes int imageiD = context.getResources().getIdentifier(imageColumnValue, "raw", context.getPackageName());

which is then handed to Glide...fromResource()...decoder(svgDecoder)...load(imageID). The resolution with getIdentifier also helps to avoid maintaining an ugly in-code map like:

put("image1", R.raw.image1)
put("image2", R.raw.image2)
... (50 times)

Now, the everyday usage is covered because if the imageID is a valid R.raw.*, it works; but there may be some cases when the resolution may not work and then if you check the [getIdentifier javadoc](file:///P:/tools/android-sdk-windows/docs/reference/android/content/res/Resources.html#getIdentifier%28java.lang.String, java.lang.String, java.lang.String%29) it says:

Returns int The associated resource identifier. Returns 0 if no such resource was found. (0 is not a valid resource ID.)

The current hack is that I check for 0 and replace it with null, because I know that works as I want it (displays .error()). Adding little workarounds like this starting to lead to cyclomatic hell around the image loading as, I, for example also have to check for null images because it is not handled as should be: #268.

@sjudd sjudd added this to the 3.6.0 milestone Apr 15, 2015
@sjudd sjudd added the bug label Apr 15, 2015
@sjudd sjudd closed this as completed in b96adbe Apr 16, 2015
TWiStErRob added a commit to TWiStErRob/net.twisterrob.inventory that referenced this issue Feb 24, 2023
[FIX] bumptech/glide#413 is fixed in SNAPSHOT
[EXP] Try = instead of MATCH maybe refresh will become faster
[COM] Accidental commit of some image related provider experimentation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants