Skip to content

Android: Saving a sound file to SD from resource and setting as ringtone

by mat on January 26th, 2010

Quite a few people have been asking how to save a file to the SD card in order to register it as a ringtone. The following example creates a function that will save a resource to the SD card (ie: from R.raw.soundfile to /sdcard/media/audio/ringtones/soundfile.ogg) and register it as a ringtone.

I have split this example into two parts, the first part goes through the code a section at a time with a brief explanation of what it does, the second half is just the code that you can copy and paste and then edit to your hearts content.

Parts

We first setup our function to return a boolean depicting if we have failed or if we are successful. We accept in an integer which corresponds to the raw sound file.

public boolean saveas(int ressound){

}

So this function would be called in the following fashion:

saveas(R.raw.soundfile);

or utilising its boolean return:

if (saveas(R.raw.soundfile)){
// Code if successful
}
else
{
// Code if unsuccessful
}

The following chunk of code creates an inputstream from the raw sound resource and loads it into a buffer. We add in the mandatory try/catch clause around these operations and return false if an exception is raised (to indicate failure to the rest of our program and to prevent trying to continue act upon this sound).

 byte[] buffer=null;
 InputStream fIn = getBaseContext().getResources().openRawResource(ressound);
 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;
 }

The following saves the buffer to a file on the SD card. It first ensures the folder exists and if not it is created. Then as before the writing operations are surrounded with try/catches

 String path="/sdcard/media/audio/ringtones/";
 String filename="examplefile"+".ogg";

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

The following code sends an intent to tell the Media Scanner that we have added a new file, and sets up its properties in the media database:

 sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://"+path+filename)));

 File k = new File(path, filename);

 ContentValues values = new ContentValues();
 values.put(MediaStore.MediaColumns.DATA, k.getAbsolutePath());
 values.put(MediaStore.MediaColumns.TITLE, "exampletitle");
 values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/ogg");
 values.put(MediaStore.Audio.Media.ARTIST, "cssounds ");
 values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
 values.put(MediaStore.Audio.Media.IS_NOTIFICATION, true);
 values.put(MediaStore.Audio.Media.IS_ALARM, true);
 values.put(MediaStore.Audio.Media.IS_MUSIC, false);

 //Insert it into the database
 this.getContentResolver().insert(MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath()), values);

Final code
Putting all this code together gives us our final functions:

public boolean saveas(int ressound){
 byte[] buffer=null;
 InputStream fIn = getBaseContext().getResources().openRawResource(ressound);
 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/media/audio/ringtones/";
 String filename="examplefile"+".ogg";

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

 sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://"+path+filename)));

 File k = new File(path, filename);

 ContentValues values = new ContentValues();
 values.put(MediaStore.MediaColumns.DATA, k.getAbsolutePath());
 values.put(MediaStore.MediaColumns.TITLE, "exampletitle");
 values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/ogg");
 values.put(MediaStore.Audio.Media.ARTIST, "cssounds ");
 values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
 values.put(MediaStore.Audio.Media.IS_NOTIFICATION, true);
 values.put(MediaStore.Audio.Media.IS_ALARM, true);
 values.put(MediaStore.Audio.Media.IS_MUSIC, false);

 //Insert it into the database
 this.getContentResolver().insert(MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath()), values);


 return true;
}

Comments, suggestions etc. are always welcome. Hope this has been helpful.

67 Comments
  1. mrj05hua permalink

    so i declared them globally as
    int[] soundids = {R.raw.sound1, R.raw.sound2, R.raw.sound3};
    that part works but how do i function call into them in the save as or play feature? Is there a link I missed I will gladly do whatever research you send me too.

  2. mrj05hua permalink

    I have gotten some of the code compiled and changed, I got it to pass an integer to the save as functions, it even saves the number of the resource id. But has some debugging errors, how can i get to use the name. Or am I going in the wrong direction.

    I passed the int as
    int[ ] soundid ={raw files, raw file, raw file};
    int j = 0;

    then in the button clicks it assigns the int to the corresponding number. But in the saveas it saves the resource location IE 2693889.mp3. How can I change this.

  3. Just make a matching string array.

    String[] name ={ “Sound 1″, “Sound name 2″, “Chainsaw!”};
    int[] sounds = {R.raw.sound1, R.raw.sound2, R.raw.chainsaw};

    then just have saveas(0); using the passed integer to correspond to the name and sound in the arrays.

  4. satish permalink

    hi i tried this code. this code doesnt shows any error when i run this program. but it does not set it as a ringtone i dont know y…if save as true i have user the toast. but the toast itslf is not being displayed . pls help me i need this code working becase i need to submit my project

  5. mrj05hua permalink

    @mat how do you assign an integer to that specific spot of the string or int arrays. I say a few ways to code it but I keep messing it up.

  6. mrj05hua permalink

    nevermind lol figured it out thank you so so much!!!!!

  7. Tommy permalink

    @mrJ05hua I am encountering the same problem you were and I can not figure it out. After googling I found this site. How did you set up the call of your arrays in the function that saves the file, well chooses the file the save? I know this is old but hey maybe you will reply :) Thanks.

  8. Excellent post, help me a lot!

  9. Patry permalink

    Hi,

    I have a problem related to that but in a differente way. I am trying to do a recorder player in Android. I got the file “example.3gp” in the SD card but then, I would like to give an option to discard or save the sound with a different name. Is there any idea of that? How can I use just the example.3gp as a temporal var?

    Thanks in advance.

  10. I am thankful that I found this blog , exactly the right information that I was searching for! .

  11. John permalink

    I implemented your code, very helpful thanks!!!!!
    After that i added ringtonemanager to set it as a ringtone.
    But on a android 2.3.3 device it will not work.
    I posted my question on stackoverflow.

    If you have time, could you take a look at it?

    http://stackoverflow.com/questions/10105877/ringtone-set-as-silent-on-android-2-3-but-works-on-4-0-3

  12. Why use Hostgator Web Hosting to host your website.
    Host gator also provide set up of worth additional companies cost-free to all their buyers.
    The over two million domains hosted by Host -
    Gator make up approximately 1% of the world.

  13. sajid khan permalink

    Thank u sooo much!
    your post was helpfull. I was facing this problem which made me crazy if did’t find your blog….
    thanks
    may i have your personal id to keep in touch with you?

  14. Nadzwyczaj korzystny wpis, zalecam wszystkim

  15. When I initially left a comment I apper to have clicked on the -Notify me when new comments are added- checkbox and from now on whenever a comment is added I recieve four emails with the exact samne comment.

    Is there a way youu are able to remove me from that service?

    Thanks!

Trackbacks & Pingbacks

  1. Tweets that mention stealthcopter.com ยป Android: Saving a sound file to SD from resource and setting as ringtone -- Topsy.com
  2. Save Bitmap for a future use in the application | Learn Android Today

Leave a Reply

Note: I am currently writing my thesis so probably wont have time to reply to your comment
Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS