获取存储在可绘制图像中的 URI

我在我的应用程序中添加了一些示例项,这样当用户第一次看到它时,它就不会看起来那么空了。包含示例项的列表应该有一个映像,我将要使用的映像已经存储在应用程序的/res/draable-文件夹中。

因为我已经有了一个从 URI 加载项目图像的方法,所以我想把 URI 加载到/res/draable/myImage.jpg,但是我似乎无法做到这一点。

流程如下: 使用表示图像 URI 的字符串创建项。 将项目列表发送到列表 该列表通过将字符串转换为 URL 来加载背景任务中的图像,然后运行 URL.openStream () ;

我已经尝试了几个 URI 选项,但都没有成功。 “ android.resource://... ...”表示未知协议 “ file://”文件未找到

所以现在我有点不知道该怎么解决这个问题。

109590 次浏览

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.

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) );
/**
* 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> { ... }

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()

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.