75

I have many .mp3 files stored in res/raw folder.

I am getting URI of .mp3 file using following code.

Uri.parse("android.resource:///com.my.android.sharesound/"+resId);

This returns : android.resource:///com.my.android.sharesound/2130968609

Now I am using this URI in creating Share Intent

    shareIntent.putExtra(Intent.EXTRA_STREAM,Uri.parse("android.resource://com.my.android.sharesound/"+resId));
    startActivity(Intent.createChooser(shareIntent,"Share Sound");

When i select any Mail application eg. Gmail or YahooMail from the Share Intent, the mp3 file attached successfully. But it shows that 2130968609(as an attachment)

i dont want resourceId(2130968609) to appear.

I want to display fileName.mp3

How can i do that? Am i missing something ?

OR

Is there any other way to attach .mp3 file stored in res/raw to mail via Share Intent.

Kartik Domadiya
  • 29,868
  • 19
  • 93
  • 104

7 Answers7

186

Finally after searching a lot i found the solution.

If you want to get any resource URI then there are two ways :

  1. Using Resource Name

    Syntax : android.resource://[package]/[res type]/[res name]

    Example : Uri.parse("android.resource://com.my.package/drawable/icon");

  2. Using Resource Id

    Syntax : android.resource://[package]/[resource_id]

    Example : Uri.parse("android.resource://com.my.package/" + R.drawable.icon);

This were the examples to get the URI of any image file stored in drawable folder.

Similarly you can get URIs of res/raw folder.

In my case i used 1st way ie. Using Resource Name

Kartik Domadiya
  • 29,868
  • 19
  • 93
  • 104
  • 7
    thanks for the answer. IMO, I think the second way would be preferred as renaming the resource etc can be easily refactored. Hence, I chose that. – Dheeraj Bhaskar Jan 11 '13 at 15:22
  • 9
    to aid the refactoring, you can also replace package name with `Context.getPackageName()` – Richard Le Mesurier Jun 20 '14 at 16:12
  • 3
    Oh, just to continue the fun tidbits, you can use `File.separator` instead of hardcoding `/`. And, you could go crazy with `File.pathSeparator` instead of hardcoding `:`. Also, great answer! – Anonsage Nov 06 '14 at 23:14
  • 5
    `"android.resource"` = `ContentResolver.SCHEME_ANDROID_RESOURCE` – frouo Apr 19 '16 at 12:32
  • If you want to use this URL in a WebView, at least in Lollipop (I did not try other versions) you need to set a custom WebViewClient that handles those URLs, something like this: `public WebResourceResponse shouldInterceptRequest(WebView view, String url) { if (url.startsWith(ContentResolver.SCHEME_ANDROID_RESOURCE + "://")) { int idPos = url.lastIndexOf('/'); int id = Integer.parseInt(url.substring(idPos + 1)); return new WebResourceResponse("text/html", "", resources.openRawResource(id)); } return null; }` – ChristophK Jun 30 '16 at 08:24
  • @KyleJahnke How do you solved this in Lollipop, a few points in right direction will be appreciated. – Mudassir Oct 03 '18 at 06:33
  • I have a case that there are 2 localized raw folder, default raw and raw-en. In my device settings, it's using English. When I share file via intent: sharingIntent.putExtra( Intent.EXTRA_STREAM, Uri.parse("android.resource://" + this.getPackageName() + "/raw/" + name )); it always share file in **raw-en** (might be affected by device's setting). **Is there any way to share exact file in *raw* folder regardless device's settings?** – Phong Nguyen Jul 23 '21 at 09:26
46

This work like magic: Assuming the mp3 is saved in the raw folder as

notification_sound.mp3

then simple doing this works:

Uri uri=Uri.parse("android.resource://"+getPackageName()+"/raw/notification_sound");
Andrew Sam
  • 469
  • 4
  • 3
15

Don't construct string on your own, use Uri.Builder:

/**
 * @param resourceId identifies an application resource
 * @return the Uri by which the application resource is accessed
 */
internal fun Context.getResourceUri(@AnyRes resourceId: Int): Uri = Uri.Builder()
    .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
    .authority(packageName)
    .path(resourceId.toString())
    .build()

From AOSP-DeskClock.

Dewey Reed
  • 4,353
  • 2
  • 27
  • 41
8

Here are some methods that might help someone:

    public Uri getRawUri(String filename) {
        return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + File.pathSeparator + File.separator + getPackageName() + "/raw/" + filename);
    }
    public Uri getDrawableUri(String filename) {
        return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + File.pathSeparator + File.separator + getPackageName() + "/drawable/" + filename);
    }
    public Uri getMipmapUri(String filename) {
        return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + File.pathSeparator + File.separator + getPackageName() + "/mipmap/" + filename);
    }

Just call the method like this:

Uri rawUri = getRawUri("myFile.filetype");
Samuel Liew
  • 76,741
  • 107
  • 159
  • 260
2

One line Answer

RingtoneManager.getRingtone(getContext(),Uri.parse("android.resource://com.my.package/" + R.raw.fileName)).play();
Radesh
  • 13,084
  • 4
  • 51
  • 64
1

Here is a clean way to get any resource,

 Uri.parse(String.format("android.resource://%s/%s/%s",this.getPackageName(),"resource_folder_name","file_name"));
Remario
  • 3,813
  • 2
  • 18
  • 25
0

Try saving the file to your SDCard and maybe then send the new URI,

 public boolean saveAs(int resSoundId){
 byte[] buffer = null;
 InputStream fIn = getBaseContext().getResources().openRawResource(resSoundId);
 int size=0;

 try {
  size = fIn.available();
  buffer = new byte[size];
  fIn.read(buffer);
  fIn.close();
 } catch (IOException e) {
  // TODO Auto-generated catch block
  return false;
 }

 String path = "/sdcard/yourapp/temp/";
 String filename = "filename"+".mp3";

 boolean exists = (new File(path)).exists();
 if (!exists){new File(path).mkdirs();}

 FileOutputStream save;
 try {
  save = new FileOutputStream(path+filename);
  save.write(buffer);
  save.flush();
  save.close();
 } catch (FileNotFoundException e) {
  // TODO Auto-generated catch block
  return false;
 } catch (IOException e) {
  // TODO Auto-generated catch block
  return false;
 }    

Remember to delete the file after the email is sent successfully.

Reno
  • 33,594
  • 11
  • 89
  • 102
  • Thanks Reno. But dont you think it will take some amount of time to write the file to sdcard, get uri and then delete it. ?.. Delete will create problem for me. When should i delete the file ?. We cannot predict the Share Intent apps. result. – Kartik Domadiya Nov 02 '11 at 06:48
  • True, this is only a workaround, in-case you don't get anything. Delete the temp directory when your app closes. – Reno Nov 02 '11 at 06:55
  • @Kartik [Try this solution](http://stackoverflow.com/questions/5888718/android-share-images-from-assets-folder/7177103#7177103), it worked for someone. – Reno Nov 02 '11 at 07:04
  • ok. i think there is no other way to get URI of res. I am having other question but related to this only. When i select any Mail app, file gets attached. But when i select Whatsapp, it asks me to choose contact but doesnot show the file attached. – Kartik Domadiya Nov 02 '11 at 07:06
  • I really don't know how Whatsapp handles their attachment intents, and yes, go for whichever option is convenient – Reno Nov 02 '11 at 09:13
  • I got it working : see my answer http://stackoverflow.com/questions/7976141/get-uri-of-mp3-file-stored-in-res-raw-folder-in-android/7979084#7979084 – Kartik Domadiya Nov 02 '11 at 10:49