android 铃声设置流程
16lz
2021-01-26
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.*对DefaultRingtonePreference的单机跳转到 RingtonePickerActivity.java 下篇* 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;}}
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
更多相关文章
- Android(安卓)root的两种方法 -- udev漏洞和setuid漏洞
- android 中如何获取camera当前状态
- android获取时间差的方法
- App优化之提升你的App启动速度之实例挑战
- Android(安卓)4.4源码编译环境升级gcc版本的方法
- android ActivityGroup认识
- Android实现异步加载图片 ListView
- Android(安卓)调用Remote Service方法
- Android中Cursor 的一些方法