Get the URI of an image stored in drawable
Asked Answered
D

5

89

I am adding a couple of sample items in my application so it doesn't look so empty when the user look at it the first time. The list with the sample items should have an image and the image I am going to use is already stored in the /res/drawable-folder of the application.

Since I already have a method that load the items images from a URI i'd like to get the URI to the /res/drawable/myImage.jpg but I don't seem to be able to get it right.

The flow is as follows: Create item with string that represents the URI of the image. Send list of items to an List The list loads the image in a background task by converting the string to URL and then run url.openStream();

I have tried a few options for the URI without any success. "android.resource://....." says unknow protocoll "file://" file not found

So right now I'm a little bit lost about how to fix this..

Dyandyana answered 6/7, 2011 at 20:18 Comment(0)
E
114

You should use ContentResolver to open resource URIs:

Uri uri = Uri.parse("android.resource://your.package.here/drawable/image_name");
InputStream stream = getContentResolver().openInputStream(uri);

Also you can open file and content URIs using this method.

Erich answered 7/7, 2011 at 5:26 Comment(11)
I get a MalformedUrlException for the following: Uri path = Uri.parse("android.resource://se.javalia.myDrinks/drawable/image0109"); The image is stored in the drawable folder and is a jpg-file.Dyandyana
That's strange because Uri.parse() mustn't throw this exception. When you parse an Uri it just checks for a null reference but doesn't actually parse it.Erich
@Dyandyana You have done mistake somewhere. This does work very well.Pleven
Can we use this stream as well as toString() also?Bowra
@ÇağrıÇakır I'm not sure I understand what you mean. Do you want to convert data from the stream to a string?Erich
@Erich Exactly. Well I use iText library to generate pdf document for example, and I need to put some image on it but the getting instance of resource address is not working for stream but it is working for string definition: Image image = Image.getInstance(" string ");Bowra
I think the only way for you to create an Image is to create a Bitmap from the InputStream, then get raw pixels from the Bitmap using Bitmap. getPixels() and pass these data to Image.getInstance(byte[]).Erich
You can set src of ImageView to Uri parsed from string Michel provided.Allottee
@Erich I have a question, here you have answer for open resource from drawable, it is possible to save the favicon of the Url into drawable or in the InternalStorage and than to show that icon ?Armstead
@Spritzig You can save it to a jpeg, a webp, or a png file on the storage and load it later as a BitmapDrawable.Erich
Can you see my question or can we have a room chat because I am trying to achieve this ? The question. #54234315Armstead
C
59
/**
 * get uri to drawable or any other resource type if u wish 
 * @param context - context
 * @param drawableId - drawable res id
 * @return - uri 
 */
public static final Uri getUriToDrawable(@NonNull Context context, 
                                         @AnyRes int drawableId) {
    Uri imageUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE 
            + "://" + context.getResources().getResourcePackageName(drawableId)
            + '/' + context.getResources().getResourceTypeName(drawableId)
            + '/' + context.getResources().getResourceEntryName(drawableId) );
    return imageUri;
}

based on above - tweaked version for any resource:

 /**
 * get uri to any resource type Via Context Resource instance
 * @param context - context
 * @param resId - resource id
 * @throws Resources.NotFoundException if the given ID does not exist.
 * @return - Uri to resource by given id 
 */
public static final Uri getUriToResource(@NonNull Context context, 
                                         @AnyRes int resId)
                           throws Resources.NotFoundException {
    /** Return a Resources instance for your application's package. */
    Resources res = context.getResources();
    Uri resUri = getUriToResource(res,resId);
    return resUri;
}

 /**
 * get uri to any resource type via given Resource Instance
 * @param res - resources instance
 * @param resId - resource id
 * @throws Resources.NotFoundException if the given ID does not exist.
 * @return - Uri to resource by given id 
 */
public static final Uri getUriToResource(@NonNull Resources res, 
                                         @AnyRes int resId)
                           throws Resources.NotFoundException {
    /**
     * Creates a Uri which parses the given encoded URI string.
     * @param uriString an RFC 2396-compliant, encoded URI
     * @throws NullPointerException if uriString is null
     * @return Uri for this given uri string
     */
    Uri resUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE +
            "://" + res.getResourcePackageName(resId)
            + '/' + res.getResourceTypeName(resId)
            + '/' + res.getResourceEntryName(resId));
    /** return uri */
    return resUri;
}

some info:

From the Java Language spec.:

"17.5 Final Field Semantics

... when the object is seen by another thread, that thread will always
see the correctly constructed version of that object's final fields.
It will also see versions of any object or array referenced by
those final fields that are at least as up-to-date as the final fields
are."

In that same vein, all non-transient fields within Uri
implementations should be final and immutable so as to ensure true
immutability for clients even when they don't use proper concurrency
control.

For reference, from RFC 2396:

"4.3. Parsing a URI Reference

   A URI reference is typically parsed according to the four main
   components and fragment identifier in order to determine what
   components are present and whether the reference is relative or
   absolute.  The individual components are then parsed for their
   subparts and, if not opaque, to verify their validity.

   Although the BNF defines what is allowed in each component, it is
   ambiguous in terms of differentiating between an authority component
   and a path component that begins with two slash characters.  The
   greedy algorithm is used for disambiguation: the left-most matching
   rule soaks up as much of the URI reference string as it is capable of
   matching.  In other words, the authority component wins."

...

3. URI Syntactic Components

   The URI syntax is dependent upon the scheme.  
   In general, absolute URI are written as follows:

     <scheme>:<scheme-specific-part>

   An absolute URI contains the name of the scheme being used (<scheme>)
   followed by a colon (":") and then a string  (the <scheme-specific-part>) 
   whose interpretation depends on the scheme.

   The URI syntax does not require that the scheme-specific-part have any
   general structure or set of semantics which is common among all URI.
   However, a subset of URI do share a common syntax for representing
   hierarchical relationships within the namespace.  This "generic URI"
   syntax consists of a sequence of four main components:

     <scheme>://<authority><path>?<query>

sources:

DISPUTE

this answer is correct, however the part about final fields is not - it has nothing to do with the answer – Boris Treukhov

@BorisTreukhov - please elaborate to us what u mean by "the part about final fields is not correct" - question - how to get uri to ...? construct the way it could be parsed (how is uri parsed ? see answer)

package android.net;

/**
 * Immutable URI reference. A URI reference includes a URI and a fragment, the
 * component of the URI following a '#'. Builds and parses URI references
 * which conform to
 * <a href="http://www.faqs.org/rfcs/rfc2396.html">RFC 2396</a>.
 *
 * <p>In the interest of performance, this class performs little to no
 * validation. Behavior is undefined for invalid input. This class is very
 * forgiving--in the face of invalid input, it will return garbage
 * rather than throw an exception unless otherwise specified.
 */
 public abstract class Uri implements Parcelable, Comparable<Uri> { ... }
Cruise answered 17/3, 2016 at 13:59 Comment(5)
This answer is correct, however the part about final fields is not - it has nothing to do with the answerHerbertherbicide
@Cruise the citation of Java Language specification ("final field semantics") has nothing to do with this answer - actual URI implementation does not use final fields at all. And I don't see any connection with the other parts at all.Herbertherbicide
@BorisTreukhov are we talking here about python uri ? or maybe csharp or php uri ? probably im lost ...Cruise
@BorisTreukhov Please see that we are dealing with Uri and not URI here. Uri is specific to Android.Hurd
@Raymond232 That adds a lot, thank you very much, now I understand.Herbertherbicide
C
40

You can use Uri.Builder instead of string concatenation

 Uri imageUri = (new Uri.Builder())
    .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
    .authority(resources.getResourcePackageName(resourceId))
    .appendPath(resources.getResourceTypeName(resourceId))
    .appendPath(resources.getResourceEntryName(resourceId))
    .build()
Cheviot answered 20/9, 2018 at 9:45 Comment(0)
R
33

This is what you really need:

 Uri imageUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE +
 "://" + getResources().getResourcePackageName(R.drawable.ic_launcher)
 + '/' + getResources().getResourceTypeName(R.drawable.ic_launcher) + '/' + getResources().getResourceEntryName(R.drawable.ic_launcher) );
Republican answered 28/12, 2014 at 22:52 Comment(1)
Does this need some permission?I cant use thisPacorro
D
6

in most simple form...

Uri uri = Uri.parse("android.resource://" + getPackageName() + "/" + R.drawable.book);
InputStream iStream = getContentResolver().openInputStream(uri);

where "book" is the name of file in drawable folder.

Duston answered 21/7, 2020 at 16:31 Comment(1)
does not work with me --> E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: /2131099744 (No such file or directory)Rectory

© 2022 - 2024 — McMap. All rights reserved.