Incoming call dynamically override default ringtone
My app allows you to specify a di开发者_开发知识库fferent 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.
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.
Starting with API 5 (Android 2.x), the Contacts database has a CUSTOM_RINGTONE field, see this page:
http://developer.android.com/reference/android/provider/ContactsContract.ContactOptionsColumns.html#CUSTOM_RINGTONE
The value for this field must be a content://
URI to a media file. You can obtain one from the MedciaStore
content provider:
http://developer.android.com/reference/android/provider/MediaStore.MediaColumns.html
That may be enough to get you started. This is all standard content provider stuff; lots of existing material for both tasks.
精彩评论