Marco Vasapollo
Marco Vasapollo

Reputation: 519

Change Phone Ringtone while ringing

I know that Android has a built-in system that lets the user choose a special ringtone for a single phonebook contact/group, but i have to change the ringtone dinamically while calling:

So, I wrote a Service and load it at phone startup, to set a phone listener that captures incoming call, that saves the default phone ringtone (in a Service variable) and change the original ringtone with another one if necessary, then restore the orignal ringtone when the phone state returns idle. Well, i can save the original tone, set the new one, but can't hear the new ringtone, only the old:

Take a look at my code and keep in mind that, when the phone listener chooses if to change the original ringtone or not, the phone is already ringing.

So, how can i change the ringtone while the phone is already ringing?

I have android.permission.WRITE_SETTINGS and android.permission.READ_PHONE_STATE permissions in my Manifest.

The Service:

public class CallFilterService extends Service {

    private Uri originalRingtoneUri;

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        telephonyManager.listen(new CallFilterListener(this), PhoneStateListener.LISTEN_CALL_STATE);
        return START_STICKY;
    }

    public void saveOriginalRingtone() {
        originalRingtoneUri = RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE);
    }

    public void restoreOriginalRingtone() {
        RingtoneManager.setActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE, originalRingtoneUri);
    }
}

The PhoneListener:

public class MyPhoneListener extends PhoneListener
{
    private CallFilterService service;
    private Uri specialRingtoneUri;

    public CallFilterListener(CallFilterService service) {
        super();
        this.service = service;
        specialRingtoneUri = setSpecialRingtone();       
    }

    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        switch (state) {
            case TelephonyManager.CALL_STATE_RINGING: {
                service.saveOriginalRingtone();
                if (canChangeRingtone(incomingNumber)) {
                    //When in this if block, the default phone ringtone is already playing.
                    RingtoneManager.setActualDefaultRingtoneUri(context, RingtoneManager.TYPE_RINGTONE, specialRingtoneUri);
                }
                break;
            }
            case TelephonyManager.CALL_STATE_IDLE: 
            {
                service.restoreOriginalRingtone();
                break;
            }
            default:
                break;
        }
    }
}

Upvotes: 1

Views: 723

Answers (1)

Zoe - Save the data dump
Zoe - Save the data dump

Reputation: 28228

First, create a file with the path and filename:

File file = new File(path, songName); 

Then, prepare the query:

ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, "My Song title");
values.put(MediaStore.MediaColumns.SIZE, 215454);
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.Audio.Media.ARTIST, "Artist");
values.put(MediaStore.Audio.Media.DURATION, 230);
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);

Then insert it into the database:

Uri uri = MediaStore.Audio.Media.getContentUriForPath(file.getAbsolutePath());
Uri newUri = this.getContentResolver().insert(uri, values);

And finally, set the ringtone:

RingtoneManager.setActualDefaultRingtoneUri(
  myActivity,
  RingtoneManager.TYPE_RINGTONE,
  newUri
);  

This assumes you have the appropriate permissions. If you target API 23 or above, you have to request the permission at runtime in addition to declaring it in the manifest

Upvotes: 1

Related Questions