2

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?

Surya
  • 628
  • 3
  • 9
  • 26
  • add your manifest file and are you using proguard? – Ankit Khare Jun 24 '15 at 05:43
  • I have added the Manifest file. I am not using a proguard. – Surya Jun 24 '15 at 06:27
  • http://stackoverflow.com/questions/4603941/setting-audio-file-as-ringtone try from this link – Mit Bhatt Jun 24 '15 at 09:21
  • @MitBhatt I have done the same thing in my code. I am able to set it as my defualt Alarm Ringtone. Works fine as I wanted. But it doesn't play. I get the above error. – Surya Jun 24 '15 at 09:29
  • Can you show your songList activity ? – Mit Bhatt Jun 24 '15 at 09:39
  • I have added the code in my Question. Have a look. – Surya Jun 24 '15 at 09:44
  • http://stackoverflow.com/questions/21141725/android-how-to-set-mp3-as-ringtone check this link. You are doing some mistake while you insert the record. calm your mind and see above code. you will get your solution. – Mit Bhatt Jun 24 '15 at 09:51
  • two extra permissions : – Mit Bhatt Jun 24 '15 at 09:56
  • I am sorry to say this, but I tried with the code in the link which you pasted. It opens a menu of ringtones and I selected one out of them. But still it shows the same error and the file doesn't play at all. – Surya Jun 24 '15 at 10:13
  • @MitBhatt I have mentioned in my code a function getMusic() to fetc songs from sd card using MediaProvider Class. I have populated them in a listView "mListView" using Adapters. I need to get path and fileName from it. is there any possible way to do it. Please help me. Thanks – Surya Jun 24 '15 at 11:45
  • Okay, I got the answer as you told my insertions and retreiving the path of the file has some issues in it. Thanks a lot for your help. – Surya Jun 24 '15 at 13:39

2 Answers2

0

Share the Manifest File. Check whether the permission is added correctly.

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Arjun
  • 197
  • 3
  • 15
0

You have to add android:exported="true" in the manifest file to the activity where you are content provider.

For more details

http://developer.android.com/guide/topics/manifest/activity-element.html#exported

Ankit Khare
  • 1,345
  • 11
  • 30
  • have you tried this, if works please accept this answer. – Ankit Khare Jun 24 '15 at 07:18
  • I added the line. You can see that I added it in the activity SongList where I have the code to set Alarm Ringtone. I edited the manifest again. – Surya Jun 24 '15 at 09:07