I will share the exception which needs to be corrected. I have extracted music files from external memory of the phone in my Project. I try to set it as a defualt ringtone for the Android Alarm application. It is being displayed in the alarm whenever I set it, but it is not being played. I guess because of the below exception.
E/DatabaseUtils﹕ Writing exception to parcel
java.lang.SecurityException: External path: /storage/sdcard/Maid with the Flaxen Hair.mp3: Neither user 1000 nor current process has android.permission.READ_EXTERNAL_STORAGE.
at android.app.ContextImpl.enforce(ContextImpl.java:1685)
at android.app.ContextImpl.enforceCallingOrSelfPermission(ContextImpl.java:1714)
at com.android.providers.media.MediaProvider.checkAccess(MediaProvider.java:4615)
at com.android.providers.media.MediaProvider.openFileAndEnforcePathPermissionsHelper(MediaProvider.java:4578)
at com.android.providers.media.MediaProvider.openFile(MediaProvider.java:4502)
at android.content.ContentProvider.openFile(ContentProvider.java:1157)
at android.content.ContentProvider$Transport.openFile(ContentProvider.java:300)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:232)
at android.os.Binder.execTransact(Binder.java:404)
at dalvik.system.NativeStart.run(Native Method)
This error persists, even though I have added the READ_EXTERNAL_STORAGE Permission and included grantUriPermission() for conentProvider.
This is the Manifest File.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ctsprojects.com.alarmapp" >
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"></uses-permission>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".songList"
android:label="@string/title_activity_song_list"
android:exported="true" >
</activity>
<activity
android:name=".NextAlarm"
android:label="@string/title_activity_next_alarm" >
</activity>
</application>
</manifest>
The activity in which I am using the code for setting the Ringtone. Here it goes..
import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Path;
import android.media.MediaPlayer;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Environment;
import android.os.StrictMode;
import android.provider.MediaStore;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.DatePicker;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.TimePicker;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.Calendar;
public class songList extends Activity {
private String[] mMusicList;
ListView mListView;
String s, path;
String[] pathhh;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_song_list);
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog()
.penaltyDeath().build());
mListView = (ListView) findViewById(R.id.listView);
mMusicList = getMusic();
ArrayAdapter<String> mAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, mMusicList);
mListView.setAdapter(mAdapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
try {
/*playSong(mMusicList[arg2]);*/
path = pathhh[arg2];
s = (String) mListView.getItemAtPosition(arg2);
Log.d("songName", s);
File k = new File(path);
System.out.println(k);
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, k.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, s);
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());
grantUriPermission("android.media.MediaPlayer", uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().delete(uri, MediaStore.MediaColumns.DATA + "=\"" + k.getAbsolutePath() + "\"", null);
Uri newUri = getContentResolver().insert(uri, values);
try {
RingtoneManager.setActualDefaultRingtoneUri(songList.this, RingtoneManager.TYPE_ALARM, newUri);
} catch (Throwable t) {
}
//Intent a = new Intent(songList.this, NextAlarm.class);
//a.putExtra("song", s);
// startActivity(a);
finish();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_song_list, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private String[] getMusic() {
final Cursor mCursor = getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.MediaColumns.TITLE, MediaStore.MediaColumns.DATA, MediaStore.Audio.AudioColumns.ALBUM}, null, null,
"LOWER(" + MediaStore.Audio.Media.TITLE + ") ASC");
int count = mCursor.getCount();
String[] songs = new String[count];
int i = 0;
String[] pathh= new String[count];
if (mCursor.moveToFirst()) {
do {
songs[i] = mCursor.getString(0);
pathh[i] = mCursor.getString(mCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
i++;
} while (mCursor.moveToNext());
}
pathhh = pathh;
mCursor.close();
return songs;
}
}
In the above activity. I am taking out the songs from external sd card. Populate them in a listView. And on click of a song, I have my code to set the Default Alarm Ringtone. That's what the code does.
I have a listView in which all the songs are populated. My work is to click a song from the list and set it as a ringtone. I need to get the path and fileName from the listView itself. Is there any possible way for that?