In one of my apps, I want to add the possibility for the user to set a ringtone with a sound from my res/raw folder.
As I had no idea about how to do it, I found a piece of code on this website.
I created clone of my project and I want to test this piece of code before adapting it to my app.
here is the code :
File file = new File(Environment.getExternalStorageDirectory(),
"/myRingtonFolder/Audio/");
if (!file.exists()) {
file.mkdirs();
}
String path = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/myRingtonFolder/Audio/";
File f = new File(path + "/"+ name + ".mp3");
Uri mUri = Uri.parse("android.resource://"
+ context.getPackageName() + "/raw/" + name);
ContentResolver mCr = context.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(f);
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, f.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, name);
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.MediaColumns.SIZE, f.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(f
.getAbsolutePath());
Uri newUri = mCr.insert(uri, values); //errror here
try {
RingtoneManager.setActualDefaultRingtoneUri(context,
RingtoneManager.TYPE_RINGTONE, newUri);
Settings.System.putString(mCr, Settings.System.RINGTONE,
newUri.toString());
} catch (Throwable t) {
}
The problem is I get this error :
FATAL EXCEPTION: main
Process: com.mtoy.tiboxinshape, PID: 27721
java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.FileInputStream android.content.res.AssetFileDescriptor.createInputStream()' on a null object reference
at com.mtoy.tiboxinshape.SoundAdaptateur$2.onLongClick(SoundAdaptateur.java:117)
at android.view.View.performLongClick(View.java:5243)
at android.widget.TextView.performLongClick(TextView.java:9225)
at android.view.View$CheckForLongPress.run(View.java:21127)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
I know that the problem come from this line : Uri newUri = mCr.insert(uri, values);
. I tried to add the permission in my manifest but I still get this error.
Can you help me to find the problem please.
With the 23 android version you need to ask the authorisation in the code and not only in the manifest.xml. Everything is explained here : https://developer.android.com/training/permissions/requesting.html