(学习笔记)android 5.0 系统去电流程状态判断
需求:
判断系统拨号的每个状态,根据状态不同弹窗提示。
需求分析:
1、无卡开机要求提示用户:Emergency calls only. Please enter Emergency Number;
2、无网络覆盖情况,当户用拨打所有号码,界面上立即给出提示“No network coverage!";
3、飞行模式打开的情况下,用户拨打紧急号码时,弹出提示,提示用户要先关闭飞行模式;
4、当两张卡都处于有限服务状态的时候 拨打号码, 手机提示"Emergency call only, Please enter an Emergency number!"
目的:
通过需求了解去电的基本流程。
以下有关流程图转自:http://blog.csdn.net/yihongyuelan
流程图分析的太过详细,重点为了解决需求问题,从而简要分析一下代码结构。
这一篇笔记只能分析流程图上的从Dialer到InCallUI进程的启动流程(第一部分),找出对sim卡判断的代码。感谢大神的图。
从系统拨号盘按下拨号按钮开始分析:
一、从Dialer到InCallUI的流程分析
1.按下拨号按钮开始 (DialpadFragment.java)
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.dialpad_floating_action_button:
mHaptic.vibrate(); // 震动一下
handleDialButtonPressed(); //进入去电流程
break;
case R.id.deleteButton: {
keyPressed(KeyEvent.KEYCODE_DEL);
break;
}
case R.id.digits: {
if (!isDigitsEmpty()) {
mDigits.setCursorVisible(true);
}
break;
}
case R.id.dialpad_overflow: {
mOverflowPopupMenu.show();
break;
}
default: {
Log.wtf(TAG, "Unexpected onClick() event from: " + view);
return;
}
}
}
首先会调用一下震动器接口,接着进入handleDialButtonPressed()方法,中间比较繁琐的代码省略。
handleDialButtonPressed(int type) {
if (isDigitsEmpty()) { // 没有输入电话号码,号码为空.
// 如果上次输入记录不为空,自动补全上次输入的号码。。。
handleDialButtonClickWithEmptyDigits();
} else {
final String number = mDigits.getText().toString();
// "persist.radio.otaspdial" is a temporary hack needed for one carrier's automated
// test equipment.
// TODO: clean it up.
// mProhibitedPhoneNumberRegexp 为空,默认不走这段代码
if (number != null
&& !TextUtils.isEmpty(mProhibitedPhoneNumberRegexp)
&& number.matches(mProhibitedPhoneNumberRegexp)) {
.....
} else {
final Intent intent;
/** M: [Ip Dial] check the type of call @{ */
// 从拨号盘呼出,默认为type = Constants.DIAL_NUMBER_INTENT_NORMAL
if (type != Constants.DIAL_NUMBER_INTENT_NORMAL) {
intent = CallUtil.getCallIntent(CallUtil.getCallUri(number),
(getActivity() instanceof DialtactsActivity ?
((DialtactsActivity) getActivity()).getCallOrigin() : null),
type);
} else {
intent = CallUtil.getCallIntent(number,
(getActivity() instanceof DialtactsActivity ?
((DialtactsActivity) getActivity()).getCallOrigin() : null));
}
/** @} */
DialerUtils.startActivityWithErrorToast(getActivity(), intent);
hideAndClearDialpad(false);
}
}
}
HandleDialButtonPressed方法主要为了处理号码是否为空的情况,号码为空就试着去调用上次输入的记录,不为空就通过CallUtil.getCallIntent()方法创建一个意图,getCallIntent()方法对callOrigin和accountHandle也有非空判断,callOrigin表示的应该是是否使用系统拨号程序,accountHandle默认为空。
意图包含了Action 和 Uri,一般拨号 Uri 的形式如”tel : 123456“,”tel“ 为uri中scheme的属性 ,String类型; ”123456“为 ssp 属性,Part类型。后面对uri有各种判断。
拨号 Action 有几种,比如Intent.ACTION_CALL_PRIVILEGED 和 Intent.ACTION_CALL 等等。由于是系统拨号程序,此处CallUtil类将Aciton设置成Intent.ACTION_CALL_PRIVILEGED。Intent.ACTION_CALL一般为第三方拨号程序启用的Aciton。
接下来通过DialerUtils.startActivityWithErrorToast()方法进入具体拨号流程。此方法处理比较简单,如果Action 为 Intent.ACTION_CALL_PRIVILEGED 直接跳转,如果是 Intent.ACTION_CALL,就封装进一个bundle(bundle 存入的是最后一次点击屏幕的x/y点的坐标,具体干什么不知道,TouchPointManager 类上面注释说明 ”Used to pass on to the InCallUI for animation“),接着再跳转。
5.0上已经将同样拥有Aciton: Intent.ACTION_CALL_PRIVILEGED 的类OutgoingCallBroadcaster的enabled属性设置成false。所以直接启动CallActivity。
private void processIntent(Intent intent) {
// Ensure call intents are not processed on devices that are not capable of calling.
if (!isVoiceCapable()) {
return;
}
//如果不是通过ACTION_CALL_PRIVILEGED Action启动的,强制将intent.Acion设为ACTION_CALL
verifyCallAction(intent);
String action