获取存储在drawable中的图像的URI

Posted

技术标签:

【中文标题】获取存储在drawable中的图像的URI【英文标题】:Get the URI of an image stored in drawable 【发布时间】:2011-09-29 22:52:15 【问题描述】:

我在我的应用程序中添加了几个示例项目,因此当用户第一次查看它时它看起来不会那么空。包含示例项目的列表应该有一个图像,我要使用的图像已经存储在应用程序的 /res/drawable-folder 中。

由于我已经有一个从 URI 加载项目图像的方法,所以我想将 URI 获取到 /res/drawable/myImage.jpg 但我似乎无法正确处理。

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

我尝试了一些 URI 选项,但均未成功。 “android.resource://.....”未知协议说 未找到“file://”文件

所以现在我对如何解决这个问题有点迷茫..

【问题讨论】:

【参考方案1】:

您应该使用ContentResolver 打开资源 URI:

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

您也可以使用此方法打开文件和内容 URI。

【讨论】:

我得到一个 MalformedUrlException 如下: Uri path = Uri.parse("android.resource://se.javalia.myDrinks/drawable/image0109");图像存储在drawable文件夹中,是一个jpg文件。 这很奇怪,因为Uri.parse() 不能抛出这个异常。当您解析 Uri 时,它只会检查 null 引用,但实际上并不解析它。 @Roland 你在某处犯了错误。这确实很好用。 我们可以同时使用streamtoString() 吗? 您可以将 ImageView 的 src 设置为从 Michel 提供的字符串解析的 Uri。【参考方案2】:
/**
 * 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;

基于上述 - 任何资源的调整版本:

 /**
 * 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;

一些信息:

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>

来源:

http://www.rfc-base.org/rfc-2396.html

争议

这个答案是正确的,但是关于最终字段的部分不是 - 它与答案无关 - Boris Treukhov

@BorisTreukhov - 请向我们详细说明 “关于最终字段的部分不正确”的含义 - 问题 - 如何让 uri 到达 ...?构造它可以被解析的方式(uri是如何解析的?看答案)

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>  ... 

【讨论】:

这个答案是正确的,但是关于最终字段的部分不是 - 它与答案无关 @ceph3us 引用 Java 语言规范(“最终字段语义”)与此答案无关 - 实际的 URI 实现根本不使用最终字段。而且我根本看不到与其他部分有任何联系。 @BorisTreukhov 我们在这里谈论 python uri 吗?或者也许 csharp 或 php uri ?可能我迷路了...... @BorisTreukhov 请注意我们在这里处理的是Uri 而不是URIUri 特定于 Android。 @Raymond232 补充了很多,非常感谢,现在我明白了。【参考方案3】:

这是你真正需要的:

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

【讨论】:

这需要一些权限吗?我不能用这个【参考方案4】:

您可以使用Uri.Builder 代替字符串连接

 Uri imageUri = (new Uri.Builder())
    .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
    .authority(resources.getResourcePackageName(resourceId))
    .appendPath(resources.getResourceTypeName(resourceId))
    .appendPath(resources.getResourceEntryName(resourceId))
    .build()

【讨论】:

这是最好的解决方案。 完美解决方案【参考方案5】:

以最简单的形式...

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

其中“book”是可绘制文件夹中的文件名。

【讨论】:

不适用于我 --> E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: /2131099744 (No such file or directory)

以上是关于获取存储在drawable中的图像的URI的主要内容,如果未能解决你的问题,请参考以下文章

将drawable中的图像作为文件读取

我需要从存储在我的 res/drawables 中的图像中将图像设置到我的 ImageView

将存储在 resources/drawable 文件夹中的图像保存到图库中

ANDROID将存储在/res/drawable中的jpeg图像转换为位图对象[重复]

如何根据sqlite数据库中的名称从drawable中获取图像,然后在列表视图中显示

Android Studio 将图像从 drawable 上传到 firebase 存储