Question

Before Jelly Bean level 18 I can use music files which are not in Media store (for example, a private .mp3 file in a folder contains .nomedia file, so Media Scanner does not scan this folder and does not know about this file) but from Android 4.3 (tested on Nexus 4) I can not do that, it only works for music files which are already scanned by Media Scanner.

The real reason of this problem is I cannot insert ContentValues with MediaColumns.DATA is a absolute path of a file not scanned by Media Scanner, insert method always return null.

Uri newUri = getCR().insert(uri, contentValues); // returns null in Android 4.3 

Does anyone have a workaround to use a private file (not scanned and not recognized by Media Scanner) as ringtone?

Here is how I set ringtone:

    File ringtoneFile = new File(audio.getPath());

    ContentValues cv = new ContentValues();
    cv.put(MediaColumns.DATA, ringtoneFile.getAbsolutePath());
    cv.put(MediaColumns.TITLE, audio.getTitle());

    cv.put(MediaColumns.MIME_TYPE, "audio/*");
    if (audio.getArtist() != null)
        cv.put(Media.ARTIST, audio.getArtist());

    cv.put(Media.IS_RINGTONE, true);
    cv.put(Media.IS_NOTIFICATION, false);
    cv.put(Media.IS_ALARM, false);
    cv.put(Media.IS_MUSIC, false);

    Uri uri = Media.getContentUriForPath(ringtoneFile.getAbsolutePath());
    Uri newUri = getCR().insert(uri, cv); ////return null in Android 4.3
    if (newUri == null)
    {
        Cursor c = getCR().query(uri, new String[] { Media._ID }, Media.DATA + "=?",
                new String[] { ringtoneFile.getAbsolutePath() }, null);
        long id = -1;
        if (c != null && c.moveToFirst())
        {
            id = c.getLong(c.getColumnIndex(Media._ID));
            newUri = Uri.parse(uri.toString() + "/" + id);
            c.close();
        }
    }       

    if (newUri != null)
    {
        RingtoneManager.setActualDefaultRingtoneUri(getAppContext(), RingtoneManager.TYPE_RINGTONE, newUri);            
    }       
Was it helpful?

Solution 2

This is my workaround:

  • Copy media file to Ringtones folder (Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_RINGTONES)), remember to create that folder if it does not exist.
  • Set that file as default ringtone using the same code in the question.

OTHER TIPS

I have try with something and its work for me. Hope it will also help you.

I am fetching all the available songs in device with below method:

public static long [] getAllSongs(Context context) {
    //System.out.println("In get All Songs Method");
    Cursor c = query(context, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
            new String[] {MediaStore.Audio.Media._ID}, MediaStore.Audio.Media.IS_MUSIC +"!= 0",
            null, MediaStore.Audio.Media.TITLE + " ASC");
    try {
        if (c == null || c.getCount() == 0) {
            return null;
        }
        int len = c.getCount();
        long [] list = new long[len];
        for (int i = 0; i < len; i++) {
            c.moveToNext();
            list[i] = c.getLong(0);
            //System.out.println("ID IS: "+c.getLong(0));
        }
        //System.out.println("Total Songs are: );

       // ALL_SONGS_ID = list;
        return list;
    } finally {
        if (c != null) {
            c.close();
        }
    }
}

After fetching that songs i am selecting the sound file and set it as Ringtone with below code:

 static void setRingtone(Context context, long id) {
   ContentResolver resolver = context.getContentResolver();
   // Set the flag in the database to mark this as a ringtone
   Uri ringUri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
   try {
       ContentValues values = new ContentValues(2);
       values.put(MediaStore.Audio.Media.IS_RINGTONE, "1");
       values.put(MediaStore.Audio.Media.IS_ALARM, "1");
       resolver.update(ringUri, values, null, null);
   } catch (UnsupportedOperationException ex) {
       // most likely the card just got unmounted
       Log.e("Music app", "couldn't set ringtone flag for id " + id);
       return;
   }

   String[] cols = new String[] {
           MediaStore.Audio.Media._ID,
           MediaStore.Audio.Media.DATA,
           MediaStore.Audio.Media.TITLE
   };

   String where = MediaStore.Audio.Media._ID + "=" + id;
   Cursor cursor = query(context, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
           cols, where , null, null);
   try {
       if (cursor != null && cursor.getCount() == 1) {
           // Set the system setting to make this the current ringtone
           cursor.moveToFirst();
           Settings.System.putString(resolver, Settings.System.RINGTONE, ringUri.toString());
           String message = context.getString(R.string.ringtone_set, cursor.getString(2));
           Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
       }
   } finally {
       if (cursor != null) {
           cursor.close();
       }
   }

}

In above method id is the Song id of selected song.

Hope this will help you. Be free to ask if you dont get the solution.

Enjoy Coading... :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top