Need help saving mp3 to SD card in Android - android

I am trying to make my Android app save a mp3 from the app to the sd card so it may be of use later, but it is not saving the file anywhere in the phone. In my AndroidManifest file, I have a permission to write external storage.
Here is the code I have thus far:
public void onClick(View v) {
int ressound = R.raw.hodor1;
saveas(ressound);
}
public boolean saveas(int ressound){
byte[] buffer=null;
InputStream fIn = getBaseContext().getResources().openRawResource(ressound);
int size=0;
//1st part
try {
size = fIn.available();
buffer = new byte[size];
fIn.read(buffer);
fIn.close();
} catch (IOException e) {
Log.e(TAG, "IOException first part");
return false;
}
String soundname = "hodor1";
String filename = soundname +".mp3";
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString();
File fullPath = new File(path, filename);
boolean exists = (new File(path)).exists();
if (!exists){new File(path).mkdirs();}
//second part
FileOutputStream save;
try {
save = new FileOutputStream(fullPath);
save.write(buffer);
save.flush();
save.close();
} catch (FileNotFoundException e) {
Log.e(TAG, "FileNotFoundException in second part");
return false;
} catch (IOException e) {
Log.e(TAG, "IOException in second part");
return false;
}
//not working
//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, soundname);
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.Audio.Media.ARTIST, "Elvis");
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
Uri newUri = this.getContentResolver().insert(MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath()), values);
// set as ringtone
//savetype = RingtoneManager.TYPE_RINGTONE;
//RingtoneManager.setActualDefaultRingtoneUri(this, savetype, newUri);
return true;
}

Commonsware answered my post the most accurately. Environment.getExternalStoragePublicDirectory() should be used along with the proper programming techniques like Logging and using the two parameter File constructor.

Related

Setting tone as ringtone/notification in Android 11 / R

I am trying to set ringtone / notification tone in Android 11 since last 4-5 days, but doesn't able to complete it, It's not like i haven't tried anything new or something that, I have code which is already working fine in Android 10 and below version but when i set target to Android 30, It doesn't work.
public boolean saveAsRingtone() {
if (mInterstitialAd != null) {
mInterstitialAd.show(this);
}
InputStream fIn = getBaseContext().getResources().openRawResource(R.raw.file);
try {
byte[] buffer = new byte[fIn.available()];
fIn.read(buffer);
fIn.close();
String path = Environment.getExternalStorageDirectory() + "/Sounds/Media/";
String filename = "Ring.mp3";
if (!new File(path).exists()) {
new File(path).mkdirs();
}
try {
FileOutputStream save = new FileOutputStream(path + filename);
save.write(buffer);
save.flush();
save.close();
sendBroadcast(new Intent("android.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, "RingTone");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.MediaColumns.SIZE, 215454);
values.put(MediaStore.MediaColumns.ARTIST, "Test");
if (RingtoneManager.TYPE_RINGTONE == RingtoneManager.TYPE_RINGTONE) {
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
} else if (RingtoneManager.TYPE_NOTIFICATION == RingtoneManager.TYPE_NOTIFICATION) {
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, false);
}
values.put(MediaStore.Audio.Media.IS_ALARM, Boolean.valueOf(false));
values.put(MediaStore.Audio.Media.IS_MUSIC, Boolean.valueOf(false));
Uri uri = MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath());
getContentResolver().delete(uri, MediaStore.MediaColumns.DATA + "=\"" + k.getAbsolutePath() + "\"", null);
RingtoneManager.setActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE, uri);
Toast.makeText(getApplicationContext(), "Done", Toast.LENGTH_SHORT).show();
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
} catch (IOException e2) {
e2.printStackTrace();
return false;
}
} catch (IOException e3) {
e3.printStackTrace();
return false;
}
}
I already know about scoped storage and other permission related things which i have already declared in manifest file and so on.

How to save audio file from raw folder to phone

Below I have the coding for hiow to set audio as your ringtone. This works fine however I wanna know how could I alter this such that it well save just the audio so that it can be played with my other songs
public boolean save1(int type) {
byte[] buffer = null;
InputStream fIn = getBaseContext().getResources().openRawResource(
R.raw.song);
int size = 0;
try {
size = fIn.available();
buffer = new byte[size];
fIn.read(buffer);
fIn.close();
} catch (IOException e) {
return false;
}
String path = Environment.getExternalStorageDirectory().getPath()
+ "/media/audio/";
String filename = "New song";
FileOutputStream save;
try {
save = new FileOutputStream(path + filename);
save.write(buffer);
save.flush();
save.close();
} catch (FileNotFoundException e) {
return false;
} catch (IOException e) {
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, filename);
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/ogg");
if (RingtoneManager.TYPE_RINGTONE == type) {
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
} else if (RingtoneManager.TYPE_NOTIFICATION == type) {
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, true);
} else if (RingtoneManager.TYPE_ALARM == type) {
values.put(MediaStore.Audio.Media.IS_ALARM, true);
}
Uri uri = MediaStore.Audio.Media.getContentUriForPath(k
.getAbsolutePath());
Uri newUri = MainActivity.this.getContentResolver().insert(uri, values);
RingtoneManager.setActualDefaultRingtoneUri(MainActivity.this, type,
newUri);
this.getContentResolver()
.insert(MediaStore.Audio.Media.getContentUriForPath(k
.getAbsolutePath()), values);
return true;
}
To move raw folder file to sdcard or phone storage below code will work:
private void CopyRAWtoPhone(int id, String path) throws IOException {
InputStream in = getResources().openRawResource(id);
FileOutputStream out = new FileOutputStream(path);
byte[] buff = new byte[1024];
int read = 0;
try {
while ((read = in.read(buff)) > 0) {
out.write(buff, 0, read);
}
} finally {
in.close();
out.close();
}
}
where first Variable id will be your raw file id and String path will be your phone storage path.

Ringtone set as silent on android 2.3, but works on 4.0.3

I have two questions:
When I call my saveas(ressound); (inspired by stealthcopter.com) on a android 4.0.3 device the ringtone is nicely activated as a ringtone, but on a 2.3.3 device the selected ringtone is silent. Where did I go wrong in my code?
The second thing that I want to know is how to delete the file. More importantly, how to get it out of the media store, does this happen automatically if I remove it from the sd?
UPDATE:
Added code to delete the whole folder plus content, works good and clean! (see below)
Try to call this code when I push a button:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
But it will not clean out the mediastore, it works with a reboot.
I also tried the media scan within the dev tools, but that doesn't work. They mention that some apps need to restart, but how to restart the service responsible for displaying the list of available ringtones without rebooting the whole device?
variables:
String soundname;
int ressound;
int savetype;
String path="/sdcard/mysounds/";
savetype = RingtoneManager.TYPE_RINGTONE;
ressound = R.raw.sound1;
soundname = "sound1";
saveas(ressound);
//save as
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) {
return false;
}
String filename= soundname +".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) {
return false;
} catch (IOException e) {
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, soundname);
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.Audio.Media.ARTIST, "Elvis");
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
Uri newUri = this.getContentResolver().insert(MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath()), values);
// set as ringtone
RingtoneManager.setActualDefaultRingtoneUri(this, savetype, newUri);
return true;
}
delete();
public void delete() {
File a = new File(path, "sound1.mp3");
a.delete();
File b = new File(path, "sound2.mp3");
b.delete();
}
deleteFiles(String path);
public static void deleteFiles(String path) {
File file = new File(path);
if (file.exists()) {
String deleteCmd = "rm -r " + path;
Runtime runtime = Runtime.getRuntime();
try {
runtime.exec(deleteCmd);
} catch (IOException e) { }
}
}
"android.permission.MODIFY_AUDIO_SETTINGS"
I think this solves problem one, did not find any problems until now.
deleteFiles(String path);
is a partly solution to problem 2
After reboot the item is gone.

Ringtone is playing the default ringtone

This has been changed from the original post.
Basically what is happening is I have gotten this to display the ringtone in the ringtone list on the phone. It also selects it. In this code it plays the ringtone after it has been selected (I have taken it out to reduce the size). It seems to be playing the phones default ringtone. Any ideas why? Thanks
private void ringtone(int p){
File newSoundFile = new File("/sdcard/media/ringtone", "raven.wav");
Uri mUri = Uri.parse("android.resource://com.fs.hh/"+R.raw.raven);
ContentResolver mCr = getContentResolver();
AssetFileDescriptor soundFile;
try {
soundFile= mCr.openAssetFileDescriptor(mUri, "r");
} catch (FileNotFoundException e) {
soundFile=null;
}
try {
byte[] readData = new byte[1024];
FileInputStream fis = soundFile.createInputStream();
FileOutputStream fos = new FileOutputStream(newSoundFile);
int i = fis.read(readData);
while (i != -1) {
fos.write(readData, 0, i);
i = fis.read(readData);
}
fos.close();
soundFile.close();
} catch (IOException io) {
}
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, newSoundFile.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, "my ringtone");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/wav");
values.put(MediaStore.MediaColumns.SIZE, newSoundFile.length());
values.put(MediaStore.Audio.Media.ARTIST, R.string.app_name);
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);
Uri uri = MediaStore.Audio.Media.getContentUriForPath(newSoundFile.getAbsolutePath());
mCr.delete(uri, MediaStore.MediaColumns.DATA + "=\"" + newSoundFile.getAbsolutePath() + "\"", null);
Uri newUri = mCr.insert(uri, values);
RingtoneManager.setActualDefaultRingtoneUri(Soundboard.this, RingtoneManager.TYPE_RINGTONE, newUri);
}
I have also tried adding a / after ringtone and making it get the byte size. Neither have worked.
I have also tried this piece of code instead and it causes the same problem. It shows up selected in the notification section, but the sound being played is not the correct sound. It sounds like a default ringer.
private boolean setRingtone(int p){
int ressound = whichSound(p); //The R.raw.sound
String fileTitle = fileTitle(p); // sound
String soundTitle = soundTitle(p); // 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;
}
String path="/sdcard/media/notification";
String filename=fileTitle+".wav";
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, soundTitle);
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/wav");
values.put(MediaStore.Audio.Media.ARTIST, "HH");
values.put(MediaStore.Audio.Media.IS_RINGTONE, false);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, true);
values.put(MediaStore.Audio.Media.IS_ALARM, false);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
//Insert it into the database
Uri newUri= this.getContentResolver().insert(MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath()), values);
RingtoneManager.setActualDefaultRingtoneUri(
this,
RingtoneManager.TYPE_NOTIFICATION,
newUri
);
return false;
}
Here is what finally fixed it.
private boolean setRingtone(int p){
int ressound = whichSound(p);
String fileTitle = fileTitle(p);
String soundTitle = soundTitle(p);
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=Environment.getExternalStorageDirectory().getPath()+"/media/ringtone/";
String filename=fileTitle+".wav";
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, soundTitle);
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/wav");
values.put(MediaStore.Audio.Media.ARTIST, "");
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, false);
values.put(MediaStore.Audio.Media.IS_ALARM, false);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
//Insert it into the database
Uri uri = MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath());
getContentResolver().delete(uri, MediaStore.MediaColumns.DATA + "=\"" + k.getAbsolutePath() + "\"", null);
Uri newUri = getContentResolver().insert(uri, values);
RingtoneManager.setActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE, newUri);
return false;
}
In the path String by adding Environment.getExternatStorageDirectory().getPath() instead of just the sdcard it was actually able to play the sound and work properly.
Uri mUri = Uri.parse("android.resource://com.packange.name/"+R.raw.raven);
"com.packange.name" should be the name of your package, I assume you havenĀ“t called it like that. Hardcode your package name, or call getPackageName() from a proper context.
Update: You can get an uri out of your newSoundFile object, just do Uri.fromFile( newSoundFile ).

Saving file as a ringtone, function always returns false, no errors

I'm doing an app which as one part features a soundboard. I'm implementing a neatly written function 'saveas();' of which I'm not the author, however it always returns False. I've spent 2 days finding a solution and now I'm out of ideas and could use some help. The file never gets saved, nor the directory is being created. Thanks for any input.
// Save as Ringtone
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="bio_ring"+".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;
}
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, "Bio_ring");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.Audio.Media.ARTIST, "Bio_Ring");
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, false);
values.put(MediaStore.Audio.Media.IS_ALARM, false);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
//Insert it into the database
Uri newUri= this.getContentResolver().insert(MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath()), values);
RingtoneManager.setActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE, newUri);
return true;
}
From android2.2 the sdcard path is changed to "/mnt/sdcard". The best way is to get sdcard path using "Environment.getExternalStorage()"
String path= Environment.getExternalStorage() + "/media/audio/ringtones/";
This maybe one reason.
You can add logs and find the reason from LogCat.

Categories

Resources