104

I need to open an intent to view an image as follows:

Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("@drawable/sample_1.jpg");
intent.setData(uri);
startActivity(intent);

The problem is that Uri uri = Uri.parse("@drawable/sample_1.jpg"); is incorrect.

Axarydax
  • 16,035
  • 19
  • 91
  • 150
user602874
  • 1,289
  • 2
  • 11
  • 8

7 Answers7

147

The format is:

"android.resource://[package]/[res id]"

[package] is your package name

[res id] is value of the resource ID, e.g. R.drawable.sample_1

to stitch it together, use

Uri path = Uri.parse("android.resource://your.package.name/" + R.drawable.sample_1);

Axarydax
  • 16,035
  • 19
  • 91
  • 150
  • 3
    Uri path = Uri.parse("android.resource://net.londatiga.android.twitpic/" + R.drawable.icon); String mpath = path.toString(); I get No such file or directory error when i am doing this – hemanth kumar Sep 04 '12 at 12:45
  • 4
    when i try to send image as email attachment it is sending the file but without .jpg extension. So the image isn't valid in the receipients pc. – ruben May 30 '13 at 05:56
  • @hemanthkumar See this answer as a reference : http://stackoverflow.com/a/8476930/62921 He explain that there is no drawable folder except on your machine. That's why it uses IDs and that your path.toString() doesn't work. – ForceMagic Jul 16 '13 at 15:21
  • This does not work for me. I get ActivityNotFoundException. (android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=android.resource://com.mypackage.myapp/2130837582 }. LG E400 Android 2.3.6. – Lucio Crusca Feb 25 '14 at 19:29
  • @LucioCrusca - maybe you should specify the intent type - is it jpeg or png image? – Axarydax Feb 26 '14 at 11:19
  • Just a reminder that the constant in the framework is: `ContentResolver.SCHEME_ANDROID_RESOURCE` – Simon Nov 22 '14 at 02:49
  • Thank you! Worked for me. Before I tried this (which did not work): `Uri uri = Uri.parse(String.valueOf(R.id.drawable_name));` – Azurespot Apr 27 '15 at 07:00
  • So is the resource type required or not? It's not working for me when I don't include the resource typ: http://stackoverflow.com/questions/19566840/get-uri-from-drawable-image – fobbymaster Nov 21 '15 at 01:01
83

Here is a clean solution which fully leverages the android.net.Uri class via its Builder pattern, avoiding repeated composition and decomposition of the URI string, without relying on hard-coded strings or ad hoc ideas about URI syntax.

Resources resources = context.getResources();
Uri uri = new Uri.Builder()
    .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
    .authority(resources.getResourcePackageName(resourceId))
    .appendPath(resources.getResourceTypeName(resourceId))
    .appendPath(resources.getResourceEntryName(resourceId))
    .build();

Minimally more elegant with Kotlin:

fun Context.resourceUri(resourceId: Int): Uri = with(resources) {
    Uri.Builder()
        .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
        .authority(getResourcePackageName(resourceId))
        .appendPath(getResourceTypeName(resourceId))
        .appendPath(getResourceEntryName(resourceId))
        .build()
}

In Jetpack Compose:

@Composable
fun rememberResourceUri(resourceId: Int): Uri {
    val context = LocalContext.current

    return remember(resourceId) {
        with(context.resources) {
            Uri.Builder()
                .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
                .authority(getResourcePackageName(resourceId))
                .appendPath(getResourceTypeName(resourceId))
                .appendPath(getResourceEntryName(resourceId))
                .build()
        }
    }
}
Uli
  • 2,583
  • 17
  • 21
59
public static Uri resourceToUri(Context context, int resID) {
        return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
                context.getResources().getResourcePackageName(resID) + '/' +
                context.getResources().getResourceTypeName(resID) + '/' +
                context.getResources().getResourceEntryName(resID) );
    }
Nick Cardoso
  • 19,801
  • 12
  • 67
  • 115
xnagyg
  • 4,576
  • 2
  • 31
  • 24
11

For those having error, you may be entering the wrong package name. Just use this method.

public static Uri resIdToUri(Context context, int resId) {
    return Uri.parse(Consts.ANDROID_RESOURCE + context.getPackageName()
                     + Consts.FORESLASH + resId);
}

Where

public static final String ANDROID_RESOURCE = "android.resource://";
public static final String FORESLASH = "/";
sandalone
  • 40,244
  • 59
  • 212
  • 332
4

You want the URI of the image resource, and R.drawable.goomb is an image resource. The Builder function creates the URI that you are asking for:

String resourceScheme = "res";
Uri uri = new Uri.Builder()
  .scheme(resourceScheme)
  .path(String.valueOf(intResourceId))
  .build();
Cody Gray
  • 230,875
  • 49
  • 477
  • 553
roide
  • 129
  • 1
  • 4
  • So you're passing something like "18" to path. That seems incorrect – Nick Cardoso Aug 09 '16 at 10:29
  • @NickCardoso R.drawable.goomba is the the drawable that I have in my resource folder. If its value is 18, does that make the assignment incorrect ? – roide Aug 09 '16 at 21:15
  • Of course it does. https://developer.android.com/reference/android/net/Uri.Builder.html#path(java.lang.String) The ID in the R file needs to be used to resolve a real path. – Nick Cardoso Aug 10 '16 at 06:59
  • @NickCardoso thanks but it does not and it works perfectly. The Scheme takes care of that path as the documentation you pointed out suggests. – roide Aug 10 '16 at 09:50
4

Based on the answers above I want to share a kotlin example on how to get a valid Uri for any resource in your project. I think it's the best solution because you don't have to type any strings in your code and risk typing it wrongly.

    val resourceId = R.raw.scannerbeep // r.mipmap.yourmipmap; R.drawable.yourdrawable
    val uriBeepSound = Uri.Builder()
        .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
        .authority(resources.getResourcePackageName(resourceId))
        .appendPath(resources.getResourceTypeName(resourceId))
        .appendPath(resources.getResourceEntryName(resourceId))
        .build()
Sergio
  • 2,014
  • 1
  • 18
  • 25
0

Based on @xnagyg answer above I've made a convenience extension which hopefully will be useful for others also,

fun Resources.getRawUri(@RawRes rawRes: Int) = "%s://%s/%s/%s".format(
    ContentResolver.SCHEME_ANDROID_RESOURCE, this.getResourcePackageName(rawRes),
    this.getResourceTypeName(rawRes), this.getResourceEntryName(rawRes)
)

which can be used like context.resources.getRawUri(R.raw.rawid)

Ebrahim Byagowi
  • 9,074
  • 4
  • 60
  • 74