android 铃声设置流程讲解 一【最近更新】

总体思路为 :
1.截取铃声
2.保存入sd卡
3.获取铃声信息
4.将信息和文件路径写入数据库获得铃声Uri
5.将获得的Uri设置为铃声。


核心实现:在
public class DefaultRingtonePreference extends RingtonePreference {private static final String TAG = "DefaultRingtonePreference";public DefaultRingtonePreference(Context context, AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onPrepareRingtonePickerIntent(Intent ringtonePickerIntent) {super.onPrepareRingtonePickerIntent(ringtonePickerIntent);/** Since this preference is for choosing the default ringtone, it* doesn't make sense to show a 'Default' item.*/ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false);}@Overrideprotected void onSaveRingtone(Uri ringtoneUri) { //注意这个方法 他是实现铃声设置的核心方法RingtoneManager.setActualDefaultRingtoneUri(getContext(), getRingtoneType(), ringtoneUri);}@Overrideprotected Uri onRestoreRingtone() {return RingtoneManager.getActualDefaultRingtoneUri(getContext(), getRingtoneType());}}DefaultRingtonePreference 单机后出现的是一个AlertDialog 但是在DefaultRingtonePreference没看见任何构造Dialog的信息 显然构建在父亲那的于是出现RingtonePreference的代码:public class RingtonePreference extends Preference implements PreferenceManager.OnActivityResultListener {private static final String TAG = "RingtonePreference";private int mRingtoneType;private boolean mShowDefault;private boolean mShowSilent;private int mRequestCode;public RingtonePreference(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.RingtonePreference, defStyle, 0);mRingtoneType = a.getInt(com.android.internal.R.styleable.RingtonePreference_ringtoneType, RingtoneManager.TYPE_RINGTONE);mShowDefault = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showDefault, true);mShowSilent = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showSilent, true);a.recycle();}public RingtonePreference(Context context, AttributeSet attrs) {this(context, attrs, com.android.internal.R.attr.ringtonePreferenceStyle);}public RingtonePreference(Context context) {this(context, null);}/*** Returns the sound type(s) that are shown in the picker.* * @return The sound type(s) that are shown in the picker.* @see #setRingtoneType(int)*/public int getRingtoneType() {return mRingtoneType;}/*** Sets the sound type(s) that are shown in the picker.* * @param type*            The sound type(s) that are shown in the picker.* @see RingtoneManager#EXTRA_RINGTONE_TYPE*/public void setRingtoneType(int type) {mRingtoneType = type;}/*** Returns whether to a show an item for the default sound/ringtone.* * @return Whether to show an item for the default sound/ringtone.*/public boolean getShowDefault() {return mShowDefault;}/*** Sets whether to show an item for the default sound/ringtone. The default* to use will be deduced from the sound type(s) being shown.* * @param showDefault*            Whether to show the default or not.* @see RingtoneManager#EXTRA_RINGTONE_SHOW_DEFAULT*/public void setShowDefault(boolean showDefault) {mShowDefault = showDefault;}/*** Returns whether to a show an item for 'Silent'.* * @return Whether to show an item for 'Silent'.*/public boolean getShowSilent() {return mShowSilent;}/*** Sets whether to show an item for 'Silent'.* * @param showSilent*            Whether to show 'Silent'.* @see RingtoneManager#EXTRA_RINGTONE_SHOW_SILENT*/public void setShowSilent(boolean showSilent) {mShowSilent = showSilent;}@Overrideprotected void onClick() { //注意这对DefaultRingtonePreference单机事件左的处理有跳转// Launch the ringtone pickerIntent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);onPrepareRingtonePickerIntent(intent);getPreferenceManager().getActivity().startActivityForResult(intent, mRequestCode);}/*** Prepares the intent to launch the ringtone picker. This can be modified* to adjust the parameters of the ringtone picker.* * @param ringtonePickerIntent*            The ringtone picker intent that can be modified by putting*            extras.*/protected void onPrepareRingtonePickerIntent(Intent ringtonePickerIntent) {ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, onRestoreRingtone());ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, mShowDefault);if (mShowDefault) {ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, RingtoneManager.getDefaultUri(getRingtoneType()));}ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, mShowSilent);ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, mRingtoneType);}/*** Called when a ringtone is chosen.* 

* By default, this saves the ringtone URI to the persistent storage as a* string.* * @param ringtoneUri* The chosen ringtone's {@link Uri}. Can be null.*/protected void onSaveRingtone(Uri ringtoneUri) {persistString(ringtoneUri != null ? ringtoneUri.toString() : "");}/*** Called when the chooser is about to be shown and the current ringtone* should be marked. Can return null to not mark any ringtone.*

* By default, this restores the previous ringtone URI from the persistent* storage.* * @return The ringtone to be marked as the current ringtone.*/protected Uri onRestoreRingtone() {final String uriString = getPersistedString(null);return !TextUtils.isEmpty(uriString) ? Uri.parse(uriString) : null;}@Overrideprotected Object onGetDefaultValue(TypedArray a, int index) {return a.getString(index);}@Overrideprotected void onSetInitialValue(boolean restorePersistedValue, Object defaultValueObj) {String defaultValue = (String) defaultValueObj;/** This method is normally to make sure the internal state and UI* matches either the persisted value or the default value. Since we* don't show the current value in the UI (until the dialog is opened)* and we don't keep local state, if we are restoring the persisted* value we don't need to do anything.*/if (restorePersistedValue) {return;}// If we are setting to the default value, we should persist it.if (!TextUtils.isEmpty(defaultValue)) {onSaveRingtone(Uri.parse(defaultValue));}}@Overrideprotected void onAttachedToHierarchy(PreferenceManager preferenceManager) {super.onAttachedToHierarchy(preferenceManager);preferenceManager.registerOnActivityResultListener(this);mRequestCode = preferenceManager.getNextRequestCode();}public boolean onActivityResult(int requestCode, int resultCode, Intent data) { //注意该方法回调了子类的onSaveRingtone方法if (requestCode == mRequestCode) {if (data != null) {Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);if (callChangeListener(uri != null ? uri.toString() : "")) {onSaveRingtone(uri);}}return true;}return false;}}

对DefaultRingtonePreference的单机跳转到 RingtonePickerActivity.java 下篇
android 铃声设置流程讲解 二继续讲解    

android 铃声设置流程讲解 二【最近跟新】【完】

package com.android.internal.app;import com.android.internal.app.AlertActivity;import com.android.internal.app.AlertController;import android.content.DialogInterface;import android.content.Intent;import android.database.Cursor;import android.media.Ringtone;import android.media.RingtoneManager;import android.net.Uri;import android.os.Bundle;import android.os.Handler;import android.provider.MediaStore;import android.provider.Settings;import android.view.View;import android.widget.AdapterView;import android.widget.ListView;import android.widget.TextView;/*** The {@link RingtonePickerActivity} allows the user to choose one from all of* the available ringtones. The chosen ringtone's URI will be persisted as a* string.* * @see RingtoneManager#ACTION_RINGTONE_PICKER*/public final class RingtonePickerActivity extends AlertActivity implements AdapterView.OnItemSelectedListener, Runnable, DialogInterface.OnClickListener,AlertController.AlertParams.OnPrepareListViewListener {private static final String TAG = "RingtonePickerActivity";private static final int DELAY_MS_SELECTION_PLAYED = 300;private RingtoneManager mRingtoneManager;private Cursor mCursor;private Handler mHandler;/** The position in the list of the 'Silent' item. */private int mSilentPos = -1;/** The position in the list of the 'Default' item. */private int mDefaultRingtonePos = -1;/** The position in the list of the last clicked item. */private int mClickedPos = -1;/** The position in the list of the ringtone to sample. */private int mSampleRingtonePos = -1;/** Whether this list has the 'Silent' item. */private boolean mHasSilentItem;/** The Uri to place a checkmark next to. */private Uri mExistingUri;/** The number of static items in the list. */private int mStaticItemCount;/** Whether this list has the 'Default' item. */private boolean mHasDefaultItem;/** The Uri to play when the 'Default' item is clicked. */private Uri mUriForDefaultItem;/*** A Ringtone for the default ringtone. In most cases, the RingtoneManager* will stop the previous ringtone. However, the RingtoneManager doesn't* manage the default ringtone for us, so we should stop this one manually.*/private Ringtone mDefaultRingtone;private DialogInterface.OnClickListener mRingtoneClickListener = new DialogInterface.OnClickListener() {/** On item clicked*/public void onClick(DialogInterface dialog, int which) {// Save the position of most recently clicked itemmClickedPos = which;// Play clipplayRingtone(which, 0);}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mHandler = new Handler();Intent intent = getIntent();/** Get whether to show the 'Default' item, and the URI to play when the* default is clicked*/mHasDefaultItem = intent.getBooleanExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);mUriForDefaultItem = intent.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI);if (mUriForDefaultItem == null) {mUriForDefaultItem = Settings.System.DEFAULT_RINGTONE_URI;}// Get whether to show the 'Silent' itemmHasSilentItem = intent.getBooleanExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true);// Give the Activity so it can do managed queriesmRingtoneManager = new RingtoneManager(this);// Get whether to include DRM ringtonesboolean includeDrm = intent.getBooleanExtra(RingtoneManager.EXTRA_RINGTONE_INCLUDE_DRM, true);mRingtoneManager.setIncludeDrm(includeDrm);// Get the types of ringtones to showint types = intent.getIntExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, -1);if (types != -1) {mRingtoneManager.setType(types);}mCursor = mRingtoneManager.getCursor();// The volume keys will control the stream that we are choosing a// ringtone forsetVolumeControlStream(mRingtoneManager.inferStreamType());// Get the URI whose list item should have a checkmarkmExistingUri = intent.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI);//mAlertParams 是父亲的属性final AlertController.AlertParams p = mAlertParams;   //开始构造Dailog了哦p.mCursor = mCursor;p.mOnClickListener = mRingtoneClickListener;//这个事件是对列表选择的时候播放该歌曲p.mLabelColumn = MediaStore.Audio.Media.TITLE;p.mIsSingleChoice = true;p.mOnItemSelectedListener = this;p.mPositiveButtonText = getString(com.android.internal.R.string.ok);p.mPositiveButtonListener = this; //选择确定后的事件 在该类onClick中实现p.mNegativeButtonText = getString(com.android.internal.R.string.cancel);p.mPositiveButtonListener = this; //取消事件 在该类onClick中实现p.mOnPrepareListViewListener = this;p.mTitle = intent.getCharSequenceExtra(RingtoneManager.EXTRA_RINGTONE_TITLE);if (p.mTitle == null) {p.mTitle = getString(com.android.internal.R.string.ringtone_picker_title);}setupAlert();}public void onPrepareListView(ListView listView) {if (mHasDefaultItem) {mDefaultRingtonePos = addDefaultRingtoneItem(listView);if (RingtoneManager.isDefault(mExistingUri)) {mClickedPos = mDefaultRingtonePos;}}if (mHasSilentItem) {mSilentPos = addSilentItem(listView);// The 'Silent' item should use a null Uriif (mExistingUri == null) {mClickedPos = mSilentPos;}}if (mClickedPos == -1) {mClickedPos = getListPosition(mRingtoneManager.getRingtonePosition(mExistingUri));}// Put a checkmark next to an item.mAlertParams.mCheckedItem = mClickedPos;}/*** Adds a static item to the top of the list. A static item is one that is* not from the RingtoneManager.* * @param listView*            The ListView to add to.* @param textResId*            The resource ID of the text for the item.* @return The position of the inserted item.*/private int addStaticItem(ListView listView, int textResId) {TextView textView = (TextView) getLayoutInflater().inflate(com.android.internal.R.layout.select_dialog_singlechoice, listView, false);textView.setText(textResId);listView.addHeaderView(textView);mStaticItemCount++;return listView.getHeaderViewsCount() - 1;}private int addDefaultRingtoneItem(ListView listView) {return addStaticItem(listView, com.android.internal.R.string.ringtone_default);}private int addSilentItem(ListView listView) {return addStaticItem(listView, com.android.internal.R.string.ringtone_silent);}/** On click of Ok/Cancel buttons*/public void onClick(DialogInterface dialog, int which) {  //该方法实现保存选择的音乐并放回给调用者boolean positiveResult = which == BUTTON1; //如果悬着的int which是BUTTON1那么返回真//意思是单机的未知==1那么就是单机了确定按钮// Stop playing the previous ringtonemRingtoneManager.stopPreviousRingtone();if (positiveResult) {Intent resultIntent = new Intent();Uri uri = null;if (mClickedPos == mDefaultRingtonePos) {// Set it to the default Uri that they originally gave usuri = mUriForDefaultItem;} else if (mClickedPos == mSilentPos) {// A null Uri is for the 'Silent' itemuri = null;} else {uri = mRingtoneManager.getRingtoneUri(getRingtoneManagerPosition(mClickedPos));}resultIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI, uri);setResult(RESULT_OK, resultIntent);} else {setResult(RESULT_CANCELED); //放回该调用者的信息}getWindow().getDecorView().post(new Runnable() {public void run() {mCursor.deactivate();}});finish();}/** On item selected via keys*/public void onItemSelected(AdapterView parent, View view, int position, long id) {playRingtone(position, DELAY_MS_SELECTION_PLAYED);}public void onNothingSelected(AdapterView parent) {}private void playRingtone(int position, int delayMs) { //播放歌曲注意mHandler会调用自己应为本类实现了 RunnablemHandler.removeCallbacks(this);mSampleRingtonePos = position;mHandler.postDelayed(this, delayMs);}public void run() {if (mSampleRingtonePos == mSilentPos) {return;}/** Stop the default ringtone, if it's playing (other ringtones will be* stopped by the RingtoneManager when we get another Ringtone from it.*/if (mDefaultRingtone != null && mDefaultRingtone.isPlaying()) {mDefaultRingtone.stop();mDefaultRingtone = null;}Ringtone ringtone;if (mSampleRingtonePos == mDefaultRingtonePos) {if (mDefaultRingtone == null) {mDefaultRingtone = RingtoneManager.getRingtone(this, mUriForDefaultItem);}ringtone = mDefaultRingtone;/** Normally the non-static RingtoneManager.getRingtone stops the* previous ringtone, but we're getting the default ringtone outside* of the RingtoneManager instance, so let's stop the previous* ringtone manually.*/mRingtoneManager.stopPreviousRingtone();} else {ringtone = mRingtoneManager.getRingtone(getRingtoneManagerPosition(mSampleRingtonePos));}if (ringtone != null) {ringtone.play();}}@Overrideprotected void onStop() {super.onStop();stopAnyPlayingRingtone();}@Overrideprotected void onPause() {super.onPause();stopAnyPlayingRingtone();}private void stopAnyPlayingRingtone() {if (mDefaultRingtone != null && mDefaultRingtone.isPlaying()) {mDefaultRingtone.stop();}if (mRingtoneManager != null) {mRingtoneManager.stopPreviousRingtone();}}private int getRingtoneManagerPosition(int listPos) {return listPos - mStaticItemCount;}private int getListPosition(int ringtoneManagerPos) {// If the manager position is -1 (for not found), return thatif (ringtoneManagerPos < 0)return ringtoneManagerPos;return ringtoneManagerPos + mStaticItemCount;}}

 




转载于:https://www.cnblogs.com/MMLoveMeMM/articles/4742340.html

更多相关文章

  1. Android(安卓)root的两种方法 -- udev漏洞和setuid漏洞
  2. android 中如何获取camera当前状态
  3. android获取时间差的方法
  4. App优化之提升你的App启动速度之实例挑战
  5. Android(安卓)4.4源码编译环境升级gcc版本的方法
  6. android ActivityGroup认识
  7. Android实现异步加载图片 ListView
  8. Android(安卓)调用Remote Service方法
  9. Android中Cursor 的一些方法

随机推荐

  1. 王家林,云计算,大数据,Hadoop,Android,iOS,HTML
  2. 安卓View理解总结
  3. android开发学习笔记(2)android的基本介绍
  4. ArcGIS for Android 支持模拟器开发
  5. Android 5.0之应用中实现材料设计—Mater
  6. Android XML解析学习——Dom方式
  7. Android动态加载外部jar包及jar包中图片
  8. Android 开发新方向 Android Wear ——概
  9. Android Alarm驱动源代码分析(Alarm.c)
  10. android手电筒原理