一:直接定位到onCreate()方法
super.onCreate(savedInstanceState);调用了父类的onCreate方法
这个是父类的onCreate方法:
super.onCreate(icicle);//还要调父类的方法
int helpResource = getHelpResource();
if (helpResource != 0) {
mHelpUrl = getResources().getString(helpResource);
}
得出父类也没做啥事继续
ContentResolver resolver = getContentResolver();//是android中存了数据,用contentprovider提供接口,在activity中用此方法获得contentresover对象,来操
int activePhoneType = TelephonyManager.getDefault().getCurrentPhoneType();//调用getDefault()方法获得TelephoneManager类,调用getCurrentPhoneType()<的意思是获得当前phone的类型,GSM/COMA
TelephonyManager.java这个方法就是
public static TelephonyManager getDefault() {
return sInstance;
}
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);//这个服务获得系统音量,铃声之类的管理继续
addPreferencesFromResource(R.xml.sound_settings);//这个方法是加载xml布局的
if (TelephonyManager.PHONE_TYPE_CDMA != activePhoneType) {
// device is not CDMA, do not display CDMA emergency_tone
getPreferenceScreen().removePreference(findPreference(KEY_EMERGENCY_TONE));
}
if (!getResources().getBoolean(R.bool.has_silent_mode)) {
findPreference(KEY_RING_VOLUME).setDependency(null);
}
if (getResources().getBoolean(com.android.internal.R.bool.config_useFixedVolume)) {
// device with fixed volume policy, do not display volumes submenu
getPreferenceScreen().removePreference(findPreference(KEY_RING_VOLUME));
}//第一个if语句是判断设备不是CDMA,下面findPreference(KEY值)类似与实例化控件,它实例化的是KEY值,移除该控件getResoures()获得资源路径这个方法的意思是在values文件下有一个bool的xml文件,会根据屏幕的尺寸选择用哪个代码优化代码,实例化那个组建,第三个也是移除这个组建的KEY值
mVibrateWhenRinging = (CheckBoxPreference) findPreference(KEY_VIBRATE);//根据KEY值实例化 mVibrateWhenRinging.setPersistent(false); mVibrateWhenRinging.setChecked(Settings.System.getInt(resolver, Settings.System.VIBRATE_WHEN_RINGING, 0) != 0);//在android的framwork层Settings类里面已经存好了设置好的值,根据那个值来判定!=0的boolean来给于选中还是不选中应该是:响铃时震动 mDtmfTone = (CheckBoxPreference) findPreference(KEY_DTMF_TONE); mDtmfTone.setPersistent(false); mDtmfTone.setChecked(Settings.System.getInt(resolver,//拨号键盘触摸音效 Settings.System.DTMF_TONE_WHEN_DIALING, 1) != 0); mSoundEffects = (CheckBoxPreference) findPreference(KEY_SOUND_EFFECTS); mSoundEffects.setPersistent(false); mSoundEffects.setChecked(Settings.System.getInt(resolver,//触摸提示音 Settings.System.SOUND_EFFECTS_ENABLED, 1) != 0); mHapticFeedback = (CheckBoxPreference) findPreference(KEY_HAPTIC_FEEDBACK); mHapticFeedback.setPersistent(false); mHapticFeedback.setChecked(Settings.System.getInt(resolver,//触摸时震动 Settings.System.HAPTIC_FEEDBACK_ENABLED, 1) != 0); mLockSounds = (CheckBoxPreference) findPreference(KEY_LOCK_SOUNDS); mLockSounds.setPersistent(false); mLockSounds.setChecked(Settings.System.getInt(resolver,//锁屏提示音 Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) != 0); 上面的这四个chekBox都是实例化,然后根据数据库存的东西和Settings设置好的值比较,来给于选中不选中 mRingtonePreference = findPreference(KEY_RINGTONE);//实例化铃声设置 mMultiSimRingtonePreference = findPreference(KEY_MULTISIM_RINGTONE);//实例化多SIM铃声设置
if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) {
//
getPreferenceScreen().removePreference(mRingtonePreference);
mRingtonePreference = null;
} else {
//if it is not multi sim, remove multi sim ringtone setting, and show ringtone setting
getPreferenceScreen().removePreference(mMultiSimRingtonePreference);
mMultiSimRingtonePreference = null;
}如果支持多SIM卡,删除铃声设置,显示多SIM铃声设置/反之如果不是支持多SIM卡,删除多SIM铃声设置,并显示铃声设置
mNotificationPreference = findPreference(KEY_NOTIFICATION_SOUND);通知提示音
class="javascript">Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
if (vibrator == null || !vibrator.hasVibrator()) {
removePreference(KEY_VIBRATE);
removePreference(KEY_HAPTIC_FEEDBACK);
}//如果震动服务为null或者,不能开启,移除响铃时震动控件的KEY和,触摸时震动的KEY
if (TelephonyManager.PHONE_TYPE_CDMA == activePhoneType) {
ListPreference emergencyTonePreference =
(ListPreference) findPreference(KEY_EMERGENCY_TONE);
emergencyTonePreference.setValue(String.valueOf(Settings.Global.getInt(
resolver, Settings.Global.EMERGENCY_TONE, FALLBACK_EMERGENCY_TONE_VALUE)));
emergencyTonePreference.setOnPreferenceChangeListener(this);
}//如果是CDMA设备实例化控件,从数据库中的数据给他设置上去,设置单机事件
mSoundSettings = (PreferenceGroup) findPreference(KEY_SOUND_SETTINGS);//实例化铃声设置
mMusicFx = mSoundSettings.findPreference(KEY_MUSICFX);
Intent i = new Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL);
PackageManager p = getPackageManager();
List ris = p.queryIntentActivities(i, PackageManager.GET_DISABLED_COMPONENTS);
if (ris.size() <= 2) {
mSoundSettings.removePreference(mMusicFx);
}铃声设置控件
if (!Utils.isVoiceCapable(getActivity())) {
for (String prefKey : NEED_VOICE_CAPABILITY) {
Preference pref = findPreference(prefKey);
if (pref != null) {
getPreferenceScreen().removePreference(pref);
}
}
}一个for循环来删除NEED_VOICE-CAPABILITY里面数据,数据是几个KEY值,相当于移除控件
mRingtoneLookupRunnable = new Runnable() {
public void run() {
if (mRingtonePreference != null) {
updateRingtoneName(RingtoneManager.TYPE_RINGTONE, mRingtonePreference,
MSG_UPDATE_RINGTONE_SUMMARY);
}
if (mNotificationPreference != null) {
updateRingtoneName(RingtoneManager.TYPE_NOTIFICATION, mNotificationPreference,
MSG_UPDATE_NOTIFICATION_SUMMARY);
}
}
};//如果SIM铃声控件部位空,更新铃声名字,因为默认有一个铃声的名字,如果通知提示音控件不为空,默认有一个名字,每次进来要设置,果然是在onResume方法中做的
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
下面是xml文件
-----------------------------------声音设置
//铃声
--------------------------------------------来电铃声和震动
------------------------------------------系统声音
-------------------------------dock
//设置dock的title的
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.add_layout_preference,null);
return v;
}
三:指向OnCreateActivity()是PreferenceFragment的
四:指向OnResume()
@Override
public void onResume() {
super.onResume();
lookupRingtoneNames();此处是更新铃声名字和提示音名字的
IntentFilter filter = new IntentFilter(Intent.ACTION_DOCK_EVENT);
getActivity().registerReceiver(mReceiver, filter);注册一个广播接受着
}
五:指向onPreferenceTreeClick单机事件,也是PreferenceFragment的单机事件,注意和Settings的继承的还是activity,所以与headClick区分
if (preference == mVibrateWhenRinging) {
Settings.System.putInt(getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING,//响铃时震动chekBox,根据值来选择设置进去put
mVibrateWhenRinging.isChecked() ? 1 : 0);
} else if (preference == mDtmfTone) {
Settings.System.putInt(getContentResolver(), Settings.System.DTMF_TONE_WHEN_DIALING,//拨号键盘触摸音效chekBox,根据值put进去数据库
mDtmfTone.isChecked() ? 1 : 0);
} else if (preference == mSoundEffects) {
if (mSoundEffects.isChecked()) {
mAudioManager.loadSoundEffects();
} else {
mAudioManager.unloadSoundEffects();
}
Settings.System.putInt(getContentResolver(), Settings.System.SOUND_EFFECTS_ENABLED,//触摸提示音chekBox,根据值put进去数据库
mSoundEffects.isChecked() ? 1 : 0);
} else if (preference == mHapticFeedback) {
Settings.System.putInt(getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED,//触摸时震动chekBox,根据值put进去
mHapticFeedback.isChecked() ? 1 : 0);
} else if (preference == mLockSounds) {
Settings.System.putInt(getContentResolver(), Settings.System.LOCKSCREEN_SOUNDS_ENABLED,//锁屏提示音checkBox,根据值put进去
mLockSounds.isChecked() ? 1 : 0);
} else if (preference == mMusicFx) {
// let the framework fire off the intent
return false;
} else if (preference == mDockAudioSettings) {
int dockState = mDockIntent != null
? mDockIntent.getIntExtra(Intent.EXTRA_DOCK_STATE, 0)
: Intent.EXTRA_DOCK_STATE_UNDOCKED;
if (dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
showDialog(DIALOG_NOT_DOCKED);
} else {
boolean isBluetooth = mDockIntent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) != null;
if (isBluetooth) {
Intent i = new Intent(mDockIntent);
i.setAction(DockEventReceiver.ACTION_DOCK_SHOW_UI);
i.setClass(getActivity(), DockEventReceiver.class);
getActivity().sendBroadcast(i);
} else {
PreferenceScreen ps = (PreferenceScreen)mDockAudioSettings;
Bundle extras = ps.getExtras();
extras.putBoolean("checked",
Settings.Global.getInt(getContentResolver(),
Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1);
super.onPreferenceTreeClick(ps, ps);
}
}--------------------------------------这一段,好像没实例化?
} else if (preference == mDockSounds) {
Settings.Global.putInt(getContentResolver(), Settings.Global.DOCK_SOUNDS_ENABLED,
mDockSounds.isChecked() ? 1 : 0);
} else if (preference == mDockAudioMediaEnabled) {
Settings.Global.putInt(getContentResolver(), Settings.Global.DOCK_AUDIO_MEDIA_ENABLED,
mDockAudioMediaEnabled.isChecked() ? 1 : 0);
} else if (mMultiSimRingtonePreference != null &&-------------------------------------多SIM铃声设置
preference == mMultiSimRingtonePreference) {
Intent intent = mMultiSimRingtonePreference.getIntent();
intent.putExtra(SelectSubscription.PACKAGE,
"com.android.multisimsettings");
intent.putExtra(SelectSubscription.TARGET_CLASS,
"com.android.multisimsettings.MultiSimSoundSettings");
startActivity(intent);
}
return true;
}
六:此时发现音量,手机铃声,默认系统提示音等等不是chekBox的控件,没有写单机事件,但是还是会弹出对话框,按理说应该是在五的时候写单机事件,设定跳转,仔细研究才发现原来是自己定义了控件,来分析XML文件
此时再看音量:RinferVolumePreference这个音量类
RingerVolumePreference.java类继承了VolumePreference
直接定位到构造方法
public RingerVolumePreference(Context context, AttributeSet attrs) {
super(context, attrs);
// The always visible seekbar is for ring volume
setStreamType(AudioManager.STREAM_RING);
setDialogLayoutResource(R.layout.preference_dialog_ringervolume);//这个地方就是加载xml文件的布局
//setDialogIcon(R.drawable.ic_settings_sound);
mSeekBarVolumizer = new SeekBarVolumizer[SEEKBAR_ID.length];
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}
----------------------------------------------------------------------------------------最外层是滚动视图
------------------------------------------------------------------------------------------上面是一个linearLayout主要是把下面的四个布局加到这个里面
--------------------------------------------------------------------------------------------其中一个的媒体的
--------------------------------------------------------------------------------------------------ringer的
--------------------------------------------------------------------------------------------------铃声和通知的
-------------------------------------------------------------------------------------------------------闹钟的设置
下面定位到onBindDialogView
for (int i = 0; i < SEEKBAR_ID.length; i++) {
SeekBar seekBar = (SeekBar) view.findViewById(SEEKBAR_ID[i]);
mSeekBars[i] = seekBar;
if (SEEKBAR_TYPE[i] == AudioManager.STREAM_MUSIC) {
mSeekBarVolumizer[i] = new SeekBarVolumizer(getContext(), seekBar,
SEEKBAR_TYPE[i], getMediaVolumeUri(getContext()));
} else {
mSeekBarVolumizer[i] = new SeekBarVolumizer(getContext(), seekBar,
SEEKBAR_TYPE[i]);
}
}
mSeekBars[0].setOnKeyListener(new View.OnKeyListener(){
public boolean onKey(View v, int keyCode, KeyEvent event) {
boolean isdown = (event.getAction() == KeyEvent.ACTION_DOWN);
switch (keyCode) {
case 21:
if (isdown) {
mSeekBarVolumizer[0].changeVolumeBy(-1);
}
return true;
case 22:
if (isdown) {
mSeekBarVolumizer[0].changeVolumeBy(1);
}
return true;
case KeyEvent.KEYCODE_VOLUME_MUTE:
if (isdown) {
mSeekBarVolumizer[0].muteVolume();
}
return true;
default:
return false;
}
}});
mSeekBars[2].setOnKeyListener(new View.OnKeyListener(){
public boolean onKey(View v, int keyCode, KeyEvent event) {
boolean isdown = (event.getAction() == KeyEvent.ACTION_DOWN);
switch (keyCode) {
case 21:
if (isdown) {
mSeekBarVolumizer[2].changeVolumeBy(-1);
}
return true;
case 22:
if (isdown) {
mSeekBarVolumizer[2].changeVolumeBy(1);
}
return true;
case KeyEvent.KEYCODE_VOLUME_MUTE:
if (isdown) {
mSeekBarVolumizer[2].muteVolume();
}
return true;
default:
return false;
}
}});
mSeekBars[1].setOnKeyListener(new View.OnKeyListener(){
public boolean onKey(View v, int keyCode, KeyEvent event) {
boolean isdown = (event.getAction() == KeyEvent.ACTION_DOWN);
switch (keyCode) {
case 21:
if (isdown) {
mSeekBarVolumizer[1].changeVolumeBy(-1);
}
return true;
case 22:
if (isdown) {
mSeekBarVolumizer[1].changeVolumeBy(1);
}
return true;
case KeyEvent.KEYCODE_VOLUME_MUTE:
if (isdown) {
mSeekBarVolumizer[1].muteVolume();
}
return true;
default:
return false;
}
}});
mSeekBars[3].setOnKeyListener(new View.OnKeyListener(){
public boolean onKey(View v, int keyCode, KeyEvent event) {
boolean isdown = (event.getAction() == KeyEvent.ACTION_DOWN);
switch (keyCode) {
case 21:
if (isdown) {
mSeekBarVolumizer[3].changeVolumeBy(-1);
}
return true;
case 22:
if (isdown) {
mSeekBarVolumizer[3].changeVolumeBy(1);
}
return true;
case KeyEvent.KEYCODE_VOLUME_MUTE:
if (isdown) {
mSeekBarVolumizer[3].muteVolume();
}
return true;
default:
return false;
}
}});
// Register callbacks for mute/unmute buttons
for (int i = 0; i < mCheckBoxes.length; i++) {
ImageView checkbox = (ImageView) view.findViewById(CHECKBOX_VIEW_ID[i]);
mCheckBoxes[i] = checkbox;
}
// Load initial states from AudioManager
updateSlidersAndMutedStates();
// Listen for updates from AudioManager
if (mRingModeChangedReceiver == null) {
final IntentFilter filter = new IntentFilter();
filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
mRingModeChangedReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED, intent
.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
}
}
};
getContext().registerReceiver(mRingModeChangedReceiver, filter);
}
boolean useMasterVolume = getContext().getResources().
getBoolean(com.android.internal.R.bool.config_useMasterVolume);
if (useMasterVolume) {
// If config_useMasterVolume is true, all streams are treated as STREAM_MASTER.
// So hide all except a stream.
int id;
if (Utils.isVoiceCapable(getContext())) {
id = R.id.ringer_section;
} else {
id = R.id.media_section;
}
for (int i = 0; i < SEEKBAR_SECTION_ID.length; i++) {
if (SEEKBAR_SECTION_ID[i] != id) {
view.findViewById(SEEKBAR_SECTION_ID[i]).setVisibility(View.GONE);
}
}
} else {
// Disable either ringer+notifications or notifications
int id;
if (!Utils.isVoiceCapable(getContext())) {
id = R.id.ringer_section;
} else {
id = R.id.notification_section;
}
View hideSection = view.findViewById(id);
hideSection.setVisibility(View.GONE);
}
}
class DefaultRingtonePreference extends RingtonePreference
public class DefaultRingtonePreference extends RingtonePreference {
private static final String TAG = "DefaultRingtonePreference";
public DefaultRingtonePreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected 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);
}
@Override
protected void onSaveRingtone(Uri ringtoneUri) {
RingtoneManager.setActualDefaultRingtoneUri(getContext(), getRingtoneType(), ringtoneUri);
}
@Override
protected Uri onRestoreRingtone() {
return RingtoneManager.getActualDefaultRingtoneUri(getContext(), getRingtoneType());
}
}