Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incoming call dynamically override default ringtone

My app allows you to specify a different ringtone for different incoming events. EG: incoming call, incoming SMS, etc.

What I am trying to accomplish is when I receive for example an incoming call, I check my apps database if a specific option is selected and if there is a ringtone option set play that ringtone.

However the problem I am having is I am unable to override / stop the default phone ringtone from playing.

I have tried several different ways, but from the docs most of those methods only stop the current instance and are not global methods.

I can't set the ringtone in the default phones ringtone settings as it needs to be dynamic based on the incoming call.

If anyone knows of a trick or a way to accomplish this that would be great. I hope that makes sense.

like image 930
userdelroot Avatar asked Aug 02 '10 12:08

userdelroot


1 Answers

There are a several steps to dynamically change the ringtone.

1. Prepare ringtone

    File k = new File("/sdcard/ringtone", "kolyan_.mp3");
    ContentValues values = new ContentValues();
    values.put(MediaStore.MediaColumns.DATA, k.getAbsolutePath());
    values.put(MediaStore.MediaColumns.TITLE, "My Song title");
    values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mpeg");
    values.put(MediaStore.Audio.Media.ARTIST, "Some Artist");
    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);

2. Insert it into the database

    Uri uri = MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath());
    // Line below is major because we need to delete old entry
    getContentResolver().delete(uri, MediaStore.MediaColumns.DATA + "=\"" + k.getAbsolutePath() + "\"", null);
    mUri = getContentResolver().insert(uri, values);

3. Save the current default ringtone and subscribe to CallListener

    // Be careful by calling getActualDefaultRingtoneUri in CallListener, it could return null, better way to save it in OnCreate
    mOldUri = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE);

    TelephonyManager mTelephonyMgr = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
    mTelephonyMgr.listen(new MyCallListener(), PhoneStateListener.LISTEN_CALL_STATE);

4. Create MyCallListener class

class MyCallListener extends PhoneStateListener {
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:
                // On call you replace the ringtone with your own mUri
                RingtoneManager.setActualDefaultRingtoneUri(
                        MainActivity.this,
                        RingtoneManager.TYPE_RINGTONE,
                        mUri
                );
                break;
            case TelephonyManager.CALL_STATE_IDLE:
                // Restore the default ringtone
                RingtoneManager.setActualDefaultRingtoneUri(
                        MainActivity.this,
                        RingtoneManager.TYPE_RINGTONE,
                        mOldUri
                );
                break;
            default:
                break;
        }

        super.onCallStateChanged(state, incomingNumber);
    }
}

5. Add permissions to you AndroidManifest.xml

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>

6. Done

The main idea is hooking for incoming call and replace the ringtone by your own. And of course you should restore default ringtone to saved value after call.

like image 169
asktomsk Avatar answered Oct 01 '22 04:10

asktomsk