I used to use following code to save a raw sound file to external storage and set it as ringtone. But things seems to change in android 10. Can you help me or show me some guideline how to update my code to work with android 10?
Here is the code to save file to external storage:
Saving file:
String path = Environment.getExternalStorageDirectory() + "/customsounds";
public File getFile() {
boolean exists = (new File(path).exists());
if (!exists) {
new File(path).mkdirs();
}
File newSoundFile = new File(path, sound.getFileName() + ".mp3");
Uri mUri = Uri.parse("android.resource://com.example.customsounds/" + sound.getId());
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();
} catch (IOException io) {
Log.e(TAG, "io exception");
return null;
}
return newSoundFile;
}
Setting as ringtone:
public void setAsRingtone() {
File newSoundFile = getFile();
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, newSoundFile.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, sound.getTitle());
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
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());
getContentResolver().delete(uri,
MediaStore.MediaColumns.DATA + "=?", new String[]{newSoundFile.getAbsolutePath()});
Uri newUri = getContentResolver().insert(uri, values);
RingtoneUtils.setRingtone(this, newUri, type);
}
Here is the RingtoneUtils:
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
public class RingtoneUtils {
private static final String LOG_TAG = "RingtoneUtils";
public static boolean setRingtone(#NonNull Context context, #NonNull Uri ringtoneUri, int type) {
Log.v(LOG_TAG, "Setting Ringtone to: " + ringtoneUri);
if (!hasMarshmallow()) {
Log.v(LOG_TAG, "On a Lollipop or below device, so go ahead and change device ringtone");
setActualRingtone(context, ringtoneUri, type);
return true;
} else if (hasMarshmallow() && canEditSystemSettings(context)) {
Log.v(LOG_TAG, "On a marshmallow or above device but app has the permission to edit system settings");
setActualRingtone(context, ringtoneUri, type);
return true;
} else if (hasMarshmallow() && !canEditSystemSettings(context)) {
Log.d(LOG_TAG, "On android Marshmallow and above but app does not have permission to" +
" edit system settings. Opening the manage write settings activity...");
startManageWriteSettingsActivity(context);
Toast.makeText(context, "Please allow app to edit settings so your ringtone/notification can be updated", Toast.LENGTH_LONG).show();
return false;
}
return false;
}
private static void setActualRingtone(#NonNull Context context, #NonNull Uri ringtoneUri, int type) {
RingtoneManager.setActualDefaultRingtoneUri(context, type, ringtoneUri);
String message="";
if(type == RingtoneManager.TYPE_RINGTONE) {
message = context.getString(R.string.ringtone_set_success);
} else if(type == RingtoneManager.TYPE_NOTIFICATION) {
message = context.getString(R.string.notification_set_success);
}
if ((RingtoneManager.getActualDefaultRingtoneUri(context, type)).equals(ringtoneUri)) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, context.getString(R.string.operation_failed), Toast.LENGTH_SHORT).show();
}
}
#RequiresApi(api = Build.VERSION_CODES.M)
private static void startManageWriteSettingsActivity(#NonNull Context context) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
// Passing in the app package here allows the settings app to open the exact app
intent.setData(Uri.parse("package:" + context.getApplicationContext().getPackageName()));
// Optional. If you pass in a service context without setting this flag, you will get an exception
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
private static boolean hasMarshmallow() {
// returns true if the device is Android Marshmallow or above, false otherwise
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
#RequiresApi(api = Build.VERSION_CODES.M)
private static boolean canEditSystemSettings(#NonNull Context context) {
// returns true if the app can edit system settings, false otherwise
return Settings.System.canWrite(context.getApplicationContext());
}
}
Pre-Android 10 exception:(#greywolf82)
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.lastIndexOf(int)' on a null object reference
at android.os.Parcel.readException(Parcel.java:1957)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
at android.content.ContentProviderProxy.insert(ContentProviderNative.java:476)
at android.content.ContentResolver.insert(ContentResolver.java:154
This method works for almost all api's.
private boolean SetAsRingtoneOrNotification(File k, int type) {
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.TITLE, k.getName());
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
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);
}
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Uri newUri = this.getContentResolver()
.insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values);
try (OutputStream os = getContentResolver().openOutputStream(newUri)) {
int size = (int) k.length();
byte[] bytes = new byte[size];
try {
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(k));
buf.read(bytes, 0, bytes.length);
buf.close();
os.write(bytes);
os.close();
os.flush();
} catch (IOException e) {
return false;
}
} catch (Exception ignored) {
return false;
}
RingtoneManager.setActualDefaultRingtoneUri(Emotes.this, type,
newUri);
return true;
} else {
values.put(MediaStore.MediaColumns.DATA, k.getAbsolutePath());
Uri uri = MediaStore.Audio.Media.getContentUriForPath(k
.getAbsolutePath());
getContentResolver().delete(uri, MediaStore.MediaColumns.DATA + "=\"" + k.getAbsolutePath() + "\"", null);
Uri newUri = Emotes.this.getContentResolver().insert(uri, values);
RingtoneManager.setActualDefaultRingtoneUri(Emotes.this, type,
newUri);
this.getContentResolver()
.insert(MediaStore.Audio.Media.getContentUriForPath(k
.getAbsolutePath()), values);
return true;
}
}
/working in android 10 and 11/
private void SetAsRingtoneAndroid(File k) {
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.TITLE, k.getName());
values.put(MediaStore.MediaColumns.MIME_TYPE, getMIMEType(k.getAbsolutePath()));//// getMIMEType(k.getAbsolutePath())
values.put(MediaStore.MediaColumns.SIZE, k.length());
values.put(MediaStore.Audio.Media.ARTIST, R.string.app_name);
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Uri newUri = getContentResolver()
.insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values);
try (OutputStream os = getContentResolver().openOutputStream(newUri)) {
int size = (int) k.length();
byte[] bytes = new byte[size];
try {
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(k));
buf.read(bytes, 0, bytes.length);
buf.close();
os.write(bytes);
os.close();
os.flush();
} catch (IOException e) {
}
} catch (Exception ignored) {
}
RingtoneManager.setActualDefaultRingtoneUri(getApplicationContext(), RingtoneManager.TYPE_RINGTONE, newUri);
Toast.makeText(this, "Ringtone set", Toast.LENGTH_SHORT).show();
}
}
public static String getMIMEType(String url) {
String mType = null;
String mExtension = MimeTypeMap.getFileExtensionFromUrl(url);
if (mExtension != null) {
mType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(mExtension);
}
return mType;
}
You can't access directly using a File interface anymore in Android 10, in addition you can't access to the DATA column. You can remove your method getFile and you need to change the method setAsRingtone():
public void setAsRingtone() {
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.TITLE, sound.getTitle());
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
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 newUri = getContentResolver().insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values);
try (OutputStream os = getContentResolver().openOutputStream(newUri)) {
//copy your file from asset into os here
} catch(Exception ignored) {
}
RingtoneUtils.setRingtone(this, newUri, type);
}
Related
I use the following code to save a music and select it as alarm music, but it does not work. where is the problem from?
(Files are saved but not selected as ringtone)
holder.btn_alarm.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int resId = getMusicId(position, ringTonesDao);
File file = saveMusic(resId);
setForAlarm(file);
}
});
This code receives the music ID in the software.
public int getMusicId(int position, RingTonesDao ringTonesDao) {
long id = ringTonesList.get(position).getId();
String musicAddress = ringTonesDao.checkMusicAddress(id);
int resId = context.getResources().getIdentifier(musicAddress, "raw", context.getPackageName());
return resId;
}
This code, after receiving the music ID, saves it in the internal memory of the mobile and returns the saved file as the output of the method.
public File saveMusic(int resId) {
File dir;
String folderName = "Ringtones";
if (Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
dir = new File(Environment.getExternalStorageDirectory(), folderName);
} else {
dir = context.getCacheDir();
}
if (!dir.exists()) {
dir.mkdirs();
}
File file = new File(dir, resId + ".mp3");
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show();
}
try {
InputStream inputStream = context.getResources().openRawResource(resId);
OutputStream outputStream = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
outputStream.flush();
outputStream.close();
inputStream.close();
} catch (Exception e) {
Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
return file;
}
This code receives the file and sets it as an alert song.
public void setForAlarm(File file) {
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, "alarm" + file.getName());
values.put(MediaStore.MediaColumns.SIZE, file.length());
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.Audio.Media.ARTIST, R.string.app_name);
values.put(MediaStore.Audio.Media.DURATION, 230);
values.put(MediaStore.Audio.Media.IS_RINGTONE, false);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, false);
values.put(MediaStore.Audio.Media.IS_ALARM, true);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
Uri uri = MediaStore.Audio.Media.getContentUriForPath(file.getAbsolutePath());
Uri newUri = context.getContentResolver().insert(uri, values);
String[] columns = {MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.IS_ALARM
};
Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, columns, MediaStore.Audio.Media.DATA + " = '" + file.getAbsolutePath() + "'", null, null);
if (cursor != null) {
int idColumn = cursor.getColumnIndex(MediaStore.Audio.Media._ID);
int fileColumn = cursor.getColumnIndex(MediaStore.Audio.Media.DATA);
int ringtoneColumn = cursor.getColumnIndex(MediaStore.Audio.Media.IS_ALARM);
while (cursor.moveToNext()) {
String audioFilePath = cursor.getString(fileColumn);
if (cursor.getString(ringtoneColumn) != null && cursor.getString(ringtoneColumn).equals("1")) {
Uri hasUri = MediaStore.Audio.Media.getContentUriForPath(audioFilePath);
newUri = Uri.withAppendedPath(hasUri, cursor.getString(idColumn));
}
}
cursor.close();
}
RingtoneManager.setActualDefaultRingtoneUri(context, RingtoneManager.TYPE_ALARM, newUri);
}
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.
I made my app to get file from Raw folder and set that file as Ringtone.
But there is a problem, the file is created and set as ringtone: http://prntscr.com/2so80e
But file does not have any sound, and idk why I am guessing by default my device is playing another ringtone.
Here is my code:
case 64:
String path = "android.resource://" + getPackageName() + "/"+R.raw.fusrodah;
File k= new File(path);
Log.i("OUTPUT", path);
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, k .getPath());
values.put(MediaStore.MediaColumns.TITLE, "Fusrodah File");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/ogg");
values.put(MediaStore.Audio.Media.ARTIST, "Testing");
values.put(MediaStore.MediaColumns.SIZE, 215454);
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);
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(Context.this,
RingtoneManager.TYPE_RINGTONE, newUri);
break;
What Am I doing wrong?
Is there something that I am missing?
I have all permissions, file is created but doesn't have any sound.
It looks like you should copy your file to SD-card firstly, then use this copy as ringtone. Here full code sample (I have file "kalimba.mp3" in my assets):
private int size;
private static final int BUFFER_LEN = 1024;
private void copyFile(AssetManager assetManager, String fileName, File out) throws FileNotFoundException, IOException {
size = 0;
FileOutputStream fos = new FileOutputStream(out);
InputStream is = assetManager.open(fileName);
int read = 0;
byte[] buffer = new byte[BUFFER_LEN];
while ((read = is.read(buffer, 0, BUFFER_LEN)) >= 0) {
fos.write(buffer, 0, read);
size += read;
}
fos.flush();
fos.close();
is.close();
}
#Override
public void onClick(View arg0) {
AssetManager assetManager = getAssets();
File file = new File(Environment.getExternalStorageDirectory(),
"/myRingtonFolder/Audio/");
if (!file.exists()) {
file.mkdirs();
}
String path = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/myRingtonFolder/Audio/";
File out = new File(path + "/", "kalimba.mp3");
if(!out.exists()){
try {
copyFile(assetManager, "kalimba.mp3", out);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, out.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, "name");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.MediaColumns.SIZE, out.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, true);
Uri uri = MediaStore.Audio.Media.getContentUriForPath(out.getAbsolutePath());
ContentResolver mCr = getContentResolver();
Uri newUri = mCr.insert(uri, values);
try {
RingtoneManager.setActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE, newUri);
Settings.System.putString(mCr, Settings.System.RINGTONE,
newUri.toString());
}
catch (Throwable t)
{
//TODO Handle exception
}
}
I am developing an application: I am trying to set an audio file as a ringtone.
I saw many posts, but no one actually helped me, so I decided to ask this question.
I use this code when the Button is clicked:
#Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.setType("audio/*");
startActivityForResult(Intent.createChooser(intent, "Choose Sound File"), Audio);
}
in onActivityResult I am trying to get the file path and then set the audio file as ringtone using the code below:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == Audio && requestCode==RESULT_OK) {
Uri s1 = data.getData();
String s = s1.getPath();
if(s!=null){
try {
k = new File(new URI(s)); //(File k;)
} catch (URISyntaxException e) {
e.printStackTrace();
}
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, k.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, "My Song title");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mpeg");
values.put(MediaStore.Audio.Media.ARTIST, "Some Artist");
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 uri = MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath());
Uri newUri = getContentResolver().insert(uri, values);
RingtoneManager.setActualDefaultRingtoneUri(
MainActivity.this,
RingtoneManager.TYPE_RINGTONE,
newUri);
}
}
}
Unfortunately this code doesn't work.
I would appreciate your answers. Sorry for my bad English.
I saw many posts but anyone showed what i should actually have to do. So i decided to create this complete answer , in which i have the solution of my problem...
Here is my MainActivity.java which i used
import java.io.File;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
Button b;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
b = (Button) findViewById(R.id.button2);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent1 = new Intent();
intent1.setAction(Intent.ACTION_GET_CONTENT);
intent1.setType("audio/*");
startActivityForResult(
Intent.createChooser(intent1, "Choose Sound File"), 6);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == 6) {
Uri i = data.getData(); // getData
String s = i.getPath(); // getPath
File k = new File(s); // set File from path
if (s != null) { // file.exists
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, k.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, "ring");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.MediaColumns.SIZE, k.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(k
.getAbsolutePath());
getContentResolver().delete(
uri,
MediaStore.MediaColumns.DATA + "=\""
+ k.getAbsolutePath() + "\"", null);
Uri newUri = getContentResolver().insert(uri, values);
try {
RingtoneManager.setActualDefaultRingtoneUri(
MainActivity.this, RingtoneManager.TYPE_RINGTONE,
newUri);
} catch (Throwable t) {
}
}
}
}
}
Lastly, its really important to add those permissions in your AndroidManifest.xml for example if you don't add the permission to write external storage your app will crash like mine.. xD
What you need:
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
You can try my app on Google Play : BackAtel Audio Manager
Hope that helps.... my problem is now solved!! i hope that i solved your problem too :))
I had the same problem and couldn't find an answer anywhere.
This is the code i used.
#SuppressLint("SdCardPath")
public class Content extends Activity {
int selectedSoundId;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content);
final MediaPlayer player = new MediaPlayer();
final Resources res = getResources();
//just keep them in the same order, e.g. button01 is tied to back to you
final int[] buttonIds = { R.id.Button01, R.id.Button02, R.id.Button03, R.id.Button04, R.id.Button05, R.id.Button06,R.id.button1};
final int[] soundIds = { R.raw.deargod, R.raw.donttalk, R.raw.lookat, R.raw.stop, R.raw.text,R.raw.john, R.raw.sherlock, };
View.OnClickListener listener = new View.OnClickListener() {
public void onClick(View v) {
//find the index that matches the button's ID, and then reset
//the MediaPlayer instance, set the data source to the corresponding
//sound effect, prepare it, and start it playing.
for(int i = 0; i < buttonIds.length; i++) {
if(v.getId() == buttonIds[i]) {
selectedSoundId = soundIds[i];
AssetFileDescriptor afd = res.openRawResourceFd(soundIds[i]);
player.reset();
try {
player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
player.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
player.start();
break;
}
}
}
};
//set the same listener for every button ID, no need
//to keep a reference to every button
for(int i = 0; i < buttonIds.length; i++) {
Button soundButton = (Button)findViewById(buttonIds[i]);
registerForContextMenu(soundButton);
soundButton.setOnClickListener(listener);
// new code to prevent crash is below.
if(soundButton!= null)
{
selectedSoundId = soundIds[1];
}
}
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.setHeaderTitle("Save as...");
menu.add(0, v.getId(), 0, "Ringtone");
menu.add(0, v.getId(), 0, "Notification");
}
#Override
public boolean onContextItemSelected(MenuItem item) {
if(item.getTitle()=="Ringtone"){function1(item.getItemId());}
else if(item.getTitle()=="Notification"){function2(item.getItemId());}
else {return false;}
return true;
}
public void function1(int id){
if
(savering(selectedSoundId)){
// Code if successful
Toast.makeText(this, "Saved as Ringtone", Toast.LENGTH_SHORT).show();
}
else
{
// Code if unsuccessful
Toast.makeText(this, "Failed - Check your SDCard", Toast.LENGTH_SHORT).show();
}
}
public void function2(int id){
if
(savenot(selectedSoundId)){
// Code if successful
Toast.makeText(this, "Saved as Notification", Toast.LENGTH_SHORT).show();
}
else
{
// Code if unsuccessful
Toast.makeText(this, "Failed - Check your SDCard", Toast.LENGTH_SHORT).show();
}
}
//Save into Ring tone Folder
public boolean savering(int ressound){
byte[] buffer=null;
InputStream fIn = getBaseContext().getResources().openRawResource(ressound);
int size=50;
try {
size = fIn.available();
buffer = new byte[size];
fIn.read(buffer);
fIn.close();
} catch (IOException e) {
// TODO Auto-generated catch block
}
String path="/sdcard/sounds/";
String filename="Sherlock"+".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
} catch (IOException e) {
// TODO Auto-generated catch block
}
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, "SHRingtone");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.Audio.Media.ARTIST, "Sherlock ");
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);
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 true;
}
//Save in Notification Folder
#SuppressLint("SdCardPath")
public boolean savenot(int ressound){
byte[] buffer=null;
InputStream fIn = getBaseContext().getResources().openRawResource(ressound);
int size=50;
try {
size = fIn.available();
buffer = new byte[size];
fIn.read(buffer);
fIn.close();
} catch (IOException e) {
// TODO Auto-generated catch block
}
String path="/sdcard/sounds/";
String filename="Sherlock"+".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
} catch (IOException e) {
// TODO Auto-generated catch block
}
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, "SHNotification");
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.Audio.Media.ARTIST, "sherlock ");
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);
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_NOTIFICATION, newUri);
return true;
}
}
setting audio as a ringtone is the same as setting tone in alarm heres the code:
ContentValues values = new ContentValues(4);
long current = System.currentTimeMillis();
values.put(MediaStore.MediaColumns.DATA, path+audioname );
values.put(MediaStore.MediaColumns.TITLE, path+audioname );
values.put(MediaStore.Audio.Media.DATE_ADDED, (int) (current / 1000));
values.put(MediaStore.Audio.Media.MIME_TYPE, "audio/3gpp");
//new
values.put(MediaStore.Audio.Media.ARTIST, "cssounds ");
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, false);
values.put(MediaStore.Audio.Media.IS_ALARM, true);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
///new
// values.put(MediaStore.Audio.Media.DATA, audiofile.getAbsolutePath());
// ContentResolver contentResolver = getContentResolver();
//Insert it into the database
this.getContentResolver().insert(MediaStore.Audio.Media.getContentUriForPath(path+audioname), values);
//RingtoneManager.setActualDefaultRingtoneUri(Activity.this,
// RingtoneManager.TYPE_RINGTONE, newUri);
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+path+audioname
+ Environment.getExternalStorageDirectory())));
// sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://"+path+editText1)));
//Toast.makeText(this, "New Alarm Sound " + editText1 +format, Toast.LENGTH_LONG).show();
}
using this code it allows your sound to be put in specific sd card folders and then setting it as ringtone and alarmtone:
values.put(MediaStore.Audio.Media.IS_RINGTONE, true);
values.put(MediaStore.Audio.Media.IS_ALARM, true);
or you can follow a complete tutorial regarding this problem.
I created a test project with a methed called testringtone(), that sets a ringtones. It ran fine. When I copied this method in another project, I get a error thats says RingtunesstarwarsActivity cannot be resolved to a type, the line is
RingtunesstarwarsActivity.this.getPackageName()+ "/" + "raw/blasters";
Uri mUri = Uri.parse(strUri);.
This works fine in my test project.
complete
method void testringtone()
{
File newSoundFile = new File("/sdcard/", "myringtone.oog");
ERROR HERE ///////////////////////////////////////////////////
String strUri = "android.resource://"+
RingtunesstarwarsActivity.this.getPackageName()+ "/" + "raw/blasters";
Uri mUri = Uri.parse(strUri);
/////////////////////////////
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();
} 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/oog");
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());
Uri newUri = mCr.insert(uri, values);
try {
RingtoneManager.setActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE, newUri);
} catch (Throwable t) {
// Log.d(TAG, "catch exception");
}
///////////////////////////////////////
} // end methed
It seems like you forgot to rename your code to reference your new actvity. Sounds like RingtunesstarwarsActivity is part of the old code and you haven't done the refactoring needed to bring everything up to date.
Either way, I don't even think you need the ClassName.this prefacing getPackageName() unless testringtone() is inside an inner class of some sort, such as an onClickListener.