来电静音,界面也不显示来电信息怀孕腰疼咋回事事

后使用快捷导航没有帐号?
除了游戏之外,本周在 App Store 推荐新应用上登陆的《图卡自然》、《实时地球》等应...
苹果iPad上的A系列应用处理器使英特尔遭受了数十亿美元损失,另外也严重威胁了其他平...
可能用到手机坏了都没完全发挥它的功能。
谷歌,我希望你能回到祖国怀抱。
AppHeads 是一款即将上架 Cydia 的新插件,它对 iPhone 和 iPad上 的多任务界面进行了...
新的 OTA 升级机制让安卓 5.0 系统的无线升级速度加快,但要求更为严格。
这部乔布斯传记片的发布日期还没有确定,但消息人士预计该片将在明年开拍。
难以挑剔的超薄全金属中端手机,定位年轻人市场,主打拍照娱乐。
曾推出过人气记事应用《Awesome Note》——中文叫做《乐顺备忘录》的开发商 BRID 时隔...
《摇滚僵尸》( Rock Zombie )是游戏开发商 Miguel Garcia Corchero 所推出的一款 3D...
《超级无底》(ULTRAHYPER)是一款考验手速的快速躲避类游戏,看到有戏的标题小编就已...
2010年一款名为《神之手(Godfinger)》模拟经营游戏上架苹果商店中,没有想到游戏发...
《Living Earth(实时地球)》是一款与众不同天气工具,它以 3D 地球仪的形式显示世界...
时隔多年,经典的《炸弹人(ボンバーマン)》再度出山,KONAMI 率领之下的《炸弹人》...
最近由开发商 ustwo 制作的一款游戏同样是主打清新视觉路线,不过它却很好地利用了三...
随着移动科技的发展,各种用智能手机操控的玩具也层出不穷,之前大家见过很多用智能设...
大部分消费者都会选择为iPhone佩戴手机套,来增强防护性。那么,既能保持iPhone 6美感...
还记得小时候在小区花园或是广场上观看露天电影的情景吗,前方幕布流动的光影早已幻化...
告别单调无聊,手机壳也玩出了新高度。
随着科技的发展,各种移动设备层出不穷,各式各样的设备可以方便的满足人们的各种生活...
在苹果 10 月发布会上将 iPad mini 3配色增加金色之后,Delux 立即更新小 i mini 产品...
还在苦恼新 iPhone 6 Plus 的小容量空间存不下多个慢动作视频?让 iBridge 帮你救急吧...
你想要为 iPhone 6 / Plus 选择什么样的保护壳?
彻底抛弃sbs用quick do!sbs六开关+虚拟home键+来电静音+多任务管理+虚拟开关键+截屏
注册时间 最后登录
在线时间285 小时 UID
主题帖子人气
青苹果, 积分 158, 距离下一级还需 42 积分
我在这里发点牢骚这篇帖子是我发的为数不多的几篇帖子之一我一直更新还是挺勤快的但是大家可以看到阅读下载附件量也算不小回复也算不错 可是一看全是报错的 我个人觉得自己写的够明白了 以后出错请自己仔细看帖子 不要看了没几下就pm我
3.6版quick do追加 很好用
12月20日更新免安装开关包(已汉化)! 几乎包含所有可用开关!路径为var/mobile/
12月15日更新wifi锁屏不掉线就是有名的insomnia!
11月26日更新新增亮度和音量开关!!deb格式的为3.4
pxl的为3.3
91中有3.3.2不建议更新有闪退现象!
十月十六号新增sbs六开关!!真正抛弃sbs(请安最后两个附件说明一下不用安sbs的) (情况再遭也无白苹果!!!)这是我第一次发帖希望大家支持 感谢pingsen大大让我发现这个软件
QuickDo是一个iPhone OS上很方便实用的快捷工具,QuickDo利用iPhone和Touch的触发功能,让你可以通过多种手势来让iPhone执行各种操作。来电静音或挂断等。它能够很大程度的保护iPhone和Touch的Home键/Power键等,延长iPhone的使用时间。
安装并启用QuickDo后,在屏幕的底部,从底部手指轻轻的滑上去,就会看到一条浅黄色的线条(触发条颜色可以在设置里面设置),即为QuickDo的触发条。 所有的手势操作都通过其来完成。只要触发条激活,即使滑动离开了触发条也有效。
如果启用了“有键盘自动隐藏”,当键盘出现时触发条会自动隐藏,键盘消失时又会恢复。此功能可避免触发条影响键盘输入。
向上或向下(状态条触发时)直线滑动3/4屏幕的距离可切换触发条位置。当你滑动结束时,可看见白色的横条往滑动的方向滑过屏幕。
当触发条在顶端时,如果有状态条,QuickDo触发条是不可见的,触发区域触发效果和状态条一样。如果设置了”在状态条上面“那么触发条就会覆盖状态条上面。
设置更改即生效,无需重启SpringBoard。
启用QuickDo = 是否启用QuickDo
同时启用状态条触发 = 同时使用QuickDo触发条和iPhone的状态条来滑动操作
滑动切换位置 = 可以通过直线滑动3/4屏幕的距离让触发条在屏幕底部或顶部来回切换
键盘显示时自动隐藏 = 当键盘显示时自动隐藏触发条
在状态条上面 = 触发条就覆盖状态条上面
显示滑动轨迹 = 显示滑动轨迹
宽度 = 设置触发条的宽度,默认14
颜色 = 设置触发条的颜色和透明度
启用锁屏快捷程序 = 是否启用锁屏快捷程序
启用提示气泡 = 在图标上显示和桌面图标一样的提示气泡
关闭程序时删除图标 = 关闭程序时会同时删除系统后台管理界面的程序图标
还原QuickDo的设置 = 还原QuickDo的设置为初始状态
如果你的是iOS4.0以上系统,并启用了系统后台任务,会在系统任务界面显示音量控制条。
挂断来电和静音
当来电时,默认向左长距离滑动可挂断电话。向右长距离滑动可静音。你也可以在设置里面设置其他手势来对于这些功能。
快捷程序界面/任务管理界面
向上或向下滑动2/5屏幕的距离(默认)即可调出任务管理界面。此界面列出了所有的快捷程序和正在运行的程序。
点状态条位置或下面图标位置空白处即可关闭界面。
上面标题栏显示了快捷程序和正在运行的程序数量。
在界面左右滑动可以滚动图标。点击下面的锁图标可以锁屏。点击下面的房子图标可以返回hOme界面。
运行的程序图标左上角有红色的关闭按钮,点击即可完全关闭程序。点击下面的垃圾桶按钮可一键关闭所有运行的程序。
设置锁屏快捷程序
打开QuickDo的设置程序,选择快捷程序界面,点击右上角“+”号按钮即可添加快捷程序。点击右上角”编辑“按钮可排序快捷程序和删除快捷程序。左右活动也可以删除快捷程序。
锁屏快捷程序
锁屏快捷程序是指在锁屏状态下,会在滑动条的上方出现一排快捷程序图标(可在设置程序任意设置),点击即可快速解锁并打开应用程序。左右滑动可滚动图标。
按住图标1秒以上,等图标背景变暗时,可以拖动设置快捷程序图标的位置。
关于后台运行
只有添加了支持iOS后台运行的程序才可以后台运行。 未添加了支持的程序要后台运行需使用一个叫Backgrounder的软件(可在Cydia搜索安装)。QuikDo后台运行的功能是调用Backgrounder实现的。
与SBSettings共存
如果你使用SBSettings,可设置QuickDo手势来调出SBSettings。
所有手势只要激活了触发条,滑动离开触发条也有效果。
短距离滑动 = 滑动大概一半横屏的距离
长距离滑动 = 滑动大概4/5横屏的距离
向上滑动 = 从触发位置开始垂直滑动大概1/5横屏的距离
左边,中间,右边 = 均分屏幕左,中,右
按住 = 按住触发条大概一秒时间
双击 = 连续点击两次
摇晃 = 摇晃手机
关于安装小白必看 1。安装文件quick do 2。重启两遍iphone(我的是,也可能为一遍) 3。在iphone中打开软件提示注册并看到id 4。在电脑上打开注册机输入id(字母为大写!!!) 5。iphone进入飞行模式,输入id 6。完成使用你的quick do 吧!
注意安装文件为pxl格式但本质仍为deb有兴趣的朋友可以在自动安deb的那个文件夹下找到依赖包和安装程序(这就是要重启两遍的原因!!同时它的使用也是很有效的)
适用固件3.2.2,3.2.1,3.2,3.1.3,3.1.2,3.1,3.0.1,3.0,4.0,4.0.1,4.0.2,4.1,4.2.1,4.3.1,4.3.2,4.3.3
文件在1楼自己占沙发
有封釉问deb格式怎么安把他们放到/var/root/Media/Cydia/AutoInstall路径下重启1----2次就行了
<p id="rate_4452" onmouseover="showTip(this)" tip="威锋有你更给力:)&人气 + 2
" class="mtn mbn">
<p id="rate_429" onmouseover="showTip(this)" tip="什么时候能有内存整理开关呢?&人气 + 7
" class="mtn mbn">
<p id="rate_8036" onmouseover="showTip(this)" tip="楼主救命啊,触发条从头到尾没见到啊,重装也没用。滑动最上面的时候有注销关机重启等&人气 + 1
" class="mtn mbn">
<p id="rate_1578" onmouseover="showTip(this)" tip="威锋有你更精彩:)&人气 + 1
" class="mtn mbn">
<p id="rate_1878" onmouseover="showTip(this)" tip="&人气 + 1
" class="mtn mbn">
<p id="rate_00" onmouseover="showTip(this)" tip="很好用,不知道有没有IPAD版的~&人气 + 3
" class="mtn mbn">
威锋有你更给力:)
什么时候能有内存整理开关呢?
楼主救命啊,触发条从头到尾没见到啊,重装也没用。滑动最上面的时候有注销关机重启等
威锋有你更精彩:)
很好用,不知道有没有IPAD版的~
注册时间 最后登录
在线时间285 小时 UID
主题帖子人气
软件截图(用的就是quick do)
十月十六号强力更新!!!!!!!!!!
彻底抛弃sbs直接用它的开关!!!!!!
100APPLE_IMG_0085.PNG (196 KB, 下载次数: 0)
09:54 上传
十一月五日更新三个开关用的拿
11:08 上传
点击文件名下载附件
518 KB, 下载次数: 4173
pxl格式软件
18:19 上传
点击文件名下载附件
160 KB, 下载次数: 762
18:19 上传
点击文件名下载附件
19 KB, 下载次数: 659
17:26 上传
点击文件名下载附件
39 KB, 下载次数: 358
17:26 上传
点击文件名下载附件
39 KB, 下载次数: 315
自动锁屏开关
17:26 上传
点击文件名下载附件
5 KB, 下载次数: 337
静音普通模式开关
11:10 上传
点击文件名下载附件
485 KB, 下载次数: 1667
最新版quick do安装后多出亮度和音量!
16:15 上传
点击文件名下载附件
730 KB, 下载次数: 682
09:54 上传
点击文件名下载附件
1.54 MB, 下载次数: 2187
免安装开关包
11:24 上传
点击文件名下载附件
554 KB, 下载次数: 1857
注册时间 最后登录
在线时间38 小时 UID
主题帖子人气
亲测可用。pxl可以用winrar解压,用ifunbox,将quickdo3.3.deb拷到cydia app install 目录下,然后重启iphone两次。然后按照楼主后续步骤继续。
注册时间 最后登录
在线时间271 小时 UID
主题帖子人气
注册码错误 楼主
注册时间 最后登录
在线时间285 小时 UID
主题帖子人气
在电脑上打开注册机输入id(字母要为大写!!!)
注册时间 最后登录
在线时间285 小时 UID
主题帖子人气
回 2楼(julianx) 的帖子
其实不用再解压了pxl的可以直接安装了
我只是说明一下为什么要重启两遍
注册时间 最后登录
在线时间2075 小时 UID
主题帖子人气
我忘记用飞行模式就注册好了,没事的吧楼主?
注册时间 最后登录
在线时间100 小时 UID
主题帖子人气
activator也可以实现好多类似功能。
注册时间 最后登录
在线时间285 小时 UID
主题帖子人气
回 6楼(邢馳) 的帖子
其实也没事 我是出于保险
个人经验安软件时习惯到飞行模式
注册时间 最后登录
在线时间285 小时 UID
主题帖子人气
回 7楼(unknown_123) 的帖子
activator没有这个功能全面的
威锋旗下产品
Hi~我是威威!
沪ICP备号-1 丨 深公安网监备案号 5
增值电信业务经营许可证:
Powered by Discuz!查看: 4499|回复: 146
最后登录在线时间0 小时机票1486 大叔币0 注册时间阅读权限100主题精华2积分2479UID849406
机票1486 大叔币0 最后登录注册时间主题精华2UID849406
今天为各位机油带来的是百度云27日更新的百度云26期,新增来电翻转手机自动静音功能!
由于最近在不断的尝试修复OV相机的问题,ROM进度有所下降!
希望OV机型的兄弟们在等待一顿时间,我会继续为你们修复OV相机的疑难杂症的!望各位勿着急!
今日百度云介绍:
1、修改底层文件,系统更加流畅
2、替换内核为B207修改
3、S相机问题无偏红现象,自动人头像识别(虽无自动对焦,请各位继续等待下)
4、自带ROOT权限
5、新增来电手机翻转自动静音功能(让你的生活更加自由)
6、新增百度云手电筒功能
7、请看以下百度官方更新以及优化内容
1.& &新增备份与恢复的app秒传功能,备份app省钱更省力!满足以下两个条件者,皆可秒传:
l&&您曾经上传过一次l&&数据库已有,即已和百度应用合作,获得了大部分APP的信息支持;所以大家在百度应用上下载的app,绝大部分都支持秒传功能,欢迎使用噢~
2.& &新增来电时,翻转手机可以静音!(暂不支持C8813)翻转静音功能默认关闭,开启路径: 电话—menu—设置—翻转静音。翻转手机,轻松静音,方便又贴心。
3.& &优化联系人头像管理,备份更省力、布局更合理、使用更贴心! (暂不支持C8813)3.1联系人的备份恢复,同步功能,不再备份联系人自动分配的头像,极大的降低了备份文件的大小;3.2优化联系人头像、来电和通话界面智能判断头像大小。同时增加自动分配开关,让您自行决定是否进行联系人头像自动分配。3.3新增以号码为单位显示通话记录。您可根据自己的习惯和需求来管理通话记录中的各类条目,可将同一个联系人的所有已接、未接来电等记录合并在一起,也可以按照自然时间顺序排列查看。3.4优化自动分配头像的性能,提升了头像自动分配速度;其他改进:【电话】修复 拨打出电话后,再次进入拨号盘,拨号icon未变为绿色(提供者:)【短信】修复 有未接来电和未读信息时,提示灯绿灯常亮,并且有橙色灯在闪烁(提供者:kingdyl)修复 关闭新信息重复提醒后,有未读信息时,还是会重复提醒(提供者:愛我的请举手)【图像搜索】新增 MTK机型中的图像搜索app【状态栏】新增 安装应用后弹出界面,可选择是否禁止该应用后台启动【桌面】修复 在launcher中,点击右上角的按钮,不应该直接打开浏览器,而是弹出对话框选择打开哪个应用【图库】修复 百度云rom23的图库浏览模式问题(提供者:)修复 图库缩略图与实际图片的缩略图不一样修复 扫描不到手机中的多媒体文件【手机找回】修复 手机找回相关问题(提供者:)【百页窗】修复 在3G网络下,百叶窗更新的内容是全是歌曲,设置里面选择的是新闻和歌曲(提供者:)【设置】修复 手机调为振动之后切换回铃声,发现之前的“振动+铃声”变为了“只有铃声”(提供者:)修复 声音设置逻辑混乱(提供者:)修复 无论选择的是&内置存储&还是&外置存储& ,存储使用详情都是显示的“内部存储”(提供者:mcg150197)修复 设置SD卡为默认存储后,存储界面显示的手机存储里的图片、视频信息显示不对【其他】修复 G11音量键唤醒屏幕无效(提供者:在阳光下的梦)修复 3g网络经常不能使用,要把数据关了重新开才可以(提供者:在阳光下的梦)修复 江西电信3G卡,流量短信查询码错误,需更新
下载地址:游客,如果您要查看本帖隐藏内容请
本帖子中包含更多资源
才可以下载或查看,没有帐号?
&一看你这个版主就是不想干了,每次想要下载的ROM,进入下载地址都显示【很抱歉,您要访问的页面不存在!】我真的打心里佩服你是个神人了&
&移动叔叔有个超级重大的BUG就是恢复主题跳转之后提示信息关闭(抱歉,指定的主题不存在或已被删除或正在被审核)&
&我看到了楼主是个神人啊,仅仅用了个十寸左右的上网本就能够把rom给搞出来不错的啊。&
我看到了,楼主是个神人。仅仅用了一个十寸.
总评分:&机票 + 11&
移动叔叔论坛 - 论坛版权
1、发帖作者在本主题帖中的所有言论和图片纯属个人意见,与立场无关
2、发帖作者在本站发表的所有标注为原创的主题帖,其相关版权归发帖作者和所有
3、其他单位或个人若进行使用、转载或引用本文时,需同时征得该发帖作者和的同意
4、发帖作者必须承担一切因本文的发表而直接或者间接导致的民事或刑事法律责任
5、本主题帖的部分内容可能来源于网络,但并不代表本站赞同其观点和对其真实性负责
6、如本帖侵犯到任何版权问题,请提供有效证明材料联系本站,本站将及时删除并致以最深的歉意
7、管理员和版主有权不事先通知随时删除本文
最后登录在线时间0 小时机票570 大叔币0 注册时间阅读权限30主题精华0积分985UID613073
玩机三段, 积分 985, 距离下一级还需 1015 积分
机票570 大叔币0 最后登录注册时间主题精华0UID613073
奶奶地,第一次抢到这么进的沙发。还是多喜爱的
最后登录在线时间0 小时机票570 大叔币0 注册时间阅读权限30主题精华0积分985UID613073
玩机三段, 积分 985, 距离下一级还需 1015 积分
机票570 大叔币0 最后登录注册时间主题精华0UID613073
乐哇啥时候修复啊
最后登录在线时间0 小时机票570 大叔币0 注册时间阅读权限30主题精华0积分985UID613073
玩机三段, 积分 985, 距离下一级还需 1015 积分
机票570 大叔币0 最后登录注册时间主题精华0UID613073
要不先透漏一下,
最后登录在线时间0 小时机票149 大叔币0 注册时间阅读权限20主题精华0积分636UID858077
玩机二段, 积分 636, 距离下一级还需 264 积分
机票149 大叔币0 最后登录注册时间主题精华0UID858077
最后登录在线时间0 小时机票149 大叔币0 注册时间阅读权限20主题精华0积分636UID858077
玩机二段, 积分 636, 距离下一级还需 264 积分
机票149 大叔币0 最后登录注册时间主题精华0UID858077
我这算板凳么
最后登录在线时间0 小时机票225 大叔币0 注册时间阅读权限20主题精华0积分488UID825036
玩机二段, 积分 488, 距离下一级还需 412 积分
机票225 大叔币0 最后登录注册时间主题精华0UID825036
哈哈,刷累啦
最后登录在线时间0 小时机票171 大叔币0 注册时间阅读权限20主题精华0积分280UID831775
玩机二段, 积分 280, 距离下一级还需 620 积分
机票171 大叔币0 最后登录注册时间主题精华0UID831775
@墨汁同学...这个修复死机&黑屏了么...?
最后登录在线时间0 小时机票433 大叔币0 注册时间阅读权限20主题精华0积分806UID831356
玩机二段, 积分 806, 距离下一级还需 94 积分
机票433 大叔币0 最后登录注册时间主题精华0UID831356
看照片好像还是不能对焦啊,不过对焦了我也不能用了。。。o记相机好等~~
最后登录在线时间0 小时机票53 大叔币0 注册时间阅读权限10主题精华0积分101UID870323
玩机小白, 积分 101, 距离下一级还需 19 积分
机票53 大叔币0 最后登录注册时间主题精华0UID870323
最后登录在线时间0 小时机票306 大叔币0 注册时间阅读权限20主题精华0积分554UID823730
玩机二段, 积分 554, 距离下一级还需 346 积分
机票306 大叔币0 最后登录注册时间主题精华0UID823730
谢谢分享,看看再说
最后登录在线时间0 小时机票527 大叔币0 注册时间阅读权限20主题精华0积分864UID822514
玩机二段, 积分 864, 距离下一级还需 36 积分
机票527 大叔币0 最后登录注册时间主题精华0UID822514
支持墨汁童鞋。
华为T移动版
【华为T VIP勋章】发评测即可申请
Nibiru手机
【Nibiru手机 VIP勋章】发评测即可申请
【红米Note VIP勋章】发评测即可申请
移动叔叔. 版权所有,专业的网络售后平台 (
商务合作||||7555人阅读
InCallScreen是什么
本文来自&转载请务必注明出处
本文以MTK平台Android 4.2为分析对象,MTK在原生的基础之上添加了许多自己的东西,因此个别地方跟原生代码以及QCOM的代码不同,请读者知悉。
在电话的呼出流程中,我们最后需要按下拨号键,才能将电话拨打出去,那么在按下拨号键之后,我们可以看到会弹出一个界面,显示拨号信息以及一些其他信息,这个界面就是我们的InCallScreen界面。当然,在来电的时候,弹出的界面依然是InCallScreen,在我们接通电话之后显示的那个界面仍然是InCallScreen。也就是说在通话过程中,我们一直可见并操作的那个界面就是InCallScreen。
图 1 InCallScreen界面
图1中所示就是InCallScreen不同情况下所展示的界面,分别是拨号、接通、来电三种情况下InCallScreen的现实情况。
InCallScreen结构分析
经过对比后可以发现,InCallScreen的拨号以及接通时,界面表现基本一致,而来电界面主要由于多了一个滑动接听的控件,从而导致界面不太一样。这里我们队InCallScreen的结构分析,采用接通之后的界面。如图2:
图 2&来电/去电接通后InCallScreen
InCallScreen布局分析
在InCallScreen.java中,我们可以在onCreate方法中找到InCallScreen加载的布局文件,即incall_screen.xml。在incall_screen.java文件中,我们可以看到有以下几个控件:
call_card:显示当前通话的信息,比如来电号码,通话时间,移动运营商等等;
incall_touch_ui:包括挂断按钮,显示DTMF拨号盘按钮,扬声器,静音,暂停,加入通话等几个按钮,就是通话界面下方的控制按钮;
otaCallCardStub:CDMA模式下跟OTA相关的控件;
manageConferencePanelStub:多方通话管理界面;
vtInCallScreenStub:视屏通话控件;
dtmf_twelve_key_dialer_stub:这个控件为DTMF控件,也就是我们点击按钮之后,会弹出一个0~9以及*和#的拨号盘。
因为我们这里主要分析一般模式下的通话界面,因此暂不涉及到视屏通话。
总的来讲,在图2显示的界面中,我们直观能够看到的控件主要是:call_card以及incall_touch_ui这两块。当我们点击DTMF弹出按钮之后,会显示DTMF控件。当然在我们接入多方通话之后,就会看到多方通话的界面了。
call_card通话信息展示
call_card控件,实际上显示的信息主要为通话联系人的相关信息,布局如下:
&?xml version=&1.0& encoding=&utf-8&?&
&com.android.phone.CallCard xmlns:android=&/apk/res/android&
android:id=&@+id/call_info_container&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:orientation=&vertical&&
&include android:id=&@+id/primary_call_info&
layout=&@layout/primary_call_info& /&
&RelativeLayout android:id=&@+id/largeAreaForSharing&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:visibility=&gone&/&
&/com.android.phone.CallCard&
整个布局情况如下图:
图 3&&CallCard界面
详细信息请参看primary_call_info.xml。
incall_touch_ui通话控制界面
这里所谓的控制主要包括了在通话界面底部的一些操作按钮,比如:挂断、显示/取消显示DTMF拨号界面、开启/关闭扬声器、启动/停止静音、开启/取消来电保持、添加多路通话等一些操作按钮。当然这里并没有将所有的控制按钮或者控制控件全部显示出来,比如当来电时,我们需要滑动接听电话,这里的滑动控件即MultiWaveView也属于incall_touch_ui.xml布局。布局如图4:
图 4&InCallTouchUi
InCallScreen初始化流程
通过查看Phone.apk的AndroidManifest.xml文件可以看到:
&activity android:name=&InCallScreen&
android:theme=&@style/Theme.InCallScreen&
&!-- InCallScreen的Theme
android:label=&@string/phoneIconLabel&
android:excludeFromRecents=&true&
&!-- 该Activity不会显示在最近使用列表中 --&
android:launchMode=&singleInstance&
&!-- 该Activity为单例模式 --&
android:screenOrientation=&nosensor&
&!-- 该Activity不会横竖屏切换,默认竖屏 --&
android:configChanges=&keyboardHidden&
&!-- 该Activity显示时隐藏keyboard --&
android:exported=&false&&
&!-- 该Activity不能被其它调用 --&
&/activity&
查看@style/Theme.InCallScreen可以看到:
&style name=&Theme.InCallScreen& parent=&@android:style/Theme.Holo.NoActionBar&&
&item name=&android:windowBackground&&@android:color/black&/item&
&item name=&*android:windowAnimationStyle&&@style/InCallAnimationStyle&/item&
可以看到InCallScreen的Theme中没有ActionBar,窗口背景为黑色,有过场动画。
因为InCallScreen为单例模式,第一次启动时调用onCreate而后面则会调用其onNewIntent方法。我们知道在onCreate方法中,一般都是对一些对象进行创建并初始化,以及设置布局文件等等。在InCallScreen的onCreate方法中,完成了PhoneApp对象的获取,以及Window参数的设置等等,在这些过程中我们需要关注以下三个方法:
initInCallScreen:初始化CallCard以及InCallTouchUi等截面;
registerForPhoneStates:注册关于Phone状态改变的监听事件,这也就是为什么Phone状态改变之后InCallScreen能够收到变化消息的原因,这一点我们在来电流程中也有提及;
internalResolveIntent:该方法用于处理InCallScreen收到的Intent信息;
同样,在onNewIntent方法中主要调用了internalResolveIntent方法,因此下面我们着重分析以下几个方法在InCallScreen初始化的过程中作用。
initInCallScreen
该方法在InCallScreen的onCreate方法中调用,仅执行一次,代码如下:
private void initInCallScreen() {
... ...省略
// Initialize CallTime 通话时间初始化
mCallTime = new CallTime(this);
// Initialize the CallCard. 通话信息初始化
mCallCard = (CallCard) findViewById(R.id.callCard);
... ...省略
//第二路通话界面初始化
mSecCallInfo = (ViewStub) findViewById(R.id.secondary_call_info);
mCallCard.setInCallScreenInstance(this);
//通话录音按钮初始化
mVoiceRecorderIcon = (ImageView) findViewById(R.id.voiceRecorderIcon);
mVoiceRecorderIcon.setBackgroundResource(R.drawable.voice_record);
mVoiceRecorderIcon.setVisibility(View.INVISIBLE);
// Initialize the onscreen UI elements. 通话控制布局初始化
initInCallTouchUi();
... ...省略
// The DTMF Dialpad. DTMF拨号盘初始化
ViewStub stub = (ViewStub) findViewById(R.id.dtmf_twelve_key_dialer_stub);
mDialer = new DTMFTwelveKeyDialer(this, stub);
mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
// Initialize VTInCallScreen 视屏电话初始化
mVTInCallScreen = new VTInCallScreenProxy(this, mDialer);
可以看到这里全都是对InCallScreen上布局的一些初始化过程,我们继续看到其中对于InCallTouchUi初始化的代码:
private void initInCallTouchUi() {
... ...省略
mInCallTouchUi = (InCallTouchUi) findViewById(R.id.inCallTouchUi);
mInCallTouchUi.setInCallScreenInstance(this);
// 挂断并通话短信回复
mRespondViaSmsManager = new RespondViaSmsManager();
mRespondViaSmsManager.setInCallScreenInstance(this);
通过代码可以知道InCallScreen上的布局显示几乎都是在initInCallScreen方法中做的,如果我们修改了InCallScreen的布局那么我们应该在这里对修改后的布局进行初始化。
registerForPhoneStates
该方法在initInCallScreen方法之后,我们在来电流程中也有分析过该方法,代码如下:
private void registerForPhoneStates() {
if (!mRegisteredForPhoneStates) {
if (FeatureOption.MTK_GEMINI_SUPPORT) {
... ...省略
mCMGemini.registerForIncomingRingGemini(mHandler, PHONE_INCOMING_RING, null, PhoneConstants.GEMINI_SIM_1);
mCMGemini.registerForIncomingRingGemini(mHandler, PHONE_INCOMING_RING2, null, PhoneConstants.GEMINI_SIM_2);
... ...省略
... ...省略
mCM.registerForIncomingRing(mHandler, PHONE_INCOMING_RING, null);
... ...省略
这里所用的mHandler就是InCallScreen的mHandler,这里通过register****方法注册监听实际上为观察者模式的运用。
internalResolveIntent
该方法是InCallScreen用于处理Intent的方法,代码如下:
private void internalResolveIntent(Intent intent) {
... ...省略
if (action.equals(intent.ACTION_MAIN)) {
//是否显示Dialpad
if (intent.hasExtra(SHOW_DIALPAD_EXTRA)) {
boolean showDialpad = intent.getBooleanExtra(SHOW_DIALPAD_EXTRA, false);
if (VDBG) log(&- internalResolveIntent: SHOW_DIALPAD_EXTRA: & + showDialpad);
mApp.inCallUiState.showDialpad = showD
final boolean hasActiveCall = mCM.hasActiveFgCall();
final boolean hasHoldingCall = mCM.hasActiveBgCall();
if (showDialpad && !hasActiveCall && hasHoldingCall) {
PhoneUtils.switchHoldingAndActive(mCM.getFirstActiveBgCall());
... ...省略
//强制开启扬声器
if (FeatureOption.MTK_TB_APP_CALL_FORCE_SPEAKER_ON) {
if (intent.hasExtra(EXTRA_FORCE_SPEAKER_ON)) {
boolean forceSpeakerOn = intent.getBooleanExtra(EXTRA_FORCE_SPEAKER_ON, false);
if (forceSpeakerOn)
Log.e(&MTK_TB_APP_CALL_FORCE_SPEAKER_ON&, &forceSpeakerOn is true&);
if (!PhoneGlobals.getInstance().isHeadsetPlugged()
&& !(mApp.isBluetoothHeadsetAudioOn())) {
//Only force the speaker ON while not video call and speaker is not ON
if (!intent.getBooleanExtra(Constants.EXTRA_IS_VIDEO_CALL, false)
&& !PhoneUtils.isSpeakerOn(mApp)) {
Log.e(&MTK_TB_APP_CALL_FORCE_SPEAKER_ON&, &PhoneUtils.turnOnSpeaker&);
PhoneUtils.turnOnSpeaker(mApp, true, true, true);
//视屏通话处理
if (FeatureOption.MTK_VT3G324M_SUPPORT) {
if (getInVoiceAnswerVideoCall()) {
setInVoiceAnswerVideoCall(false);
if (mCM.getState() == PhoneConstants.State.RINGING) {
if (DBG) {
log(&call manager state is ringing&);
// When VT call incoming, use voice call incoming call GUI
mVTInCallScreen.setVTVisible(false);
mVTInCallScreen.setVTScreenMode(Constants.VTScreenMode.VT_SCREEN_CLOSE);
} else if (intent.getBooleanExtra(Constants.EXTRA_IS_VIDEO_CALL, false)) {
if (DBG) {
log(&vt extra is true&);
// When dialing VT call, inflate VTInCallScreen
mVTInCallScreen.initVTInCallScreen();
// When dialed a VT call, but dialed failed, needs not init state for dialing
if (CallStatusCode.SUCCESS == mApp.inCallUiState.getPendingCallStatusCode()) {
mVTInCallScreen.initDialingSuccessVTState();
mVTInCallScreen.initDialingVTState();
mVTInCallScreen.initCommonVTState();
if (PhoneConstants.State.IDLE != PhoneGlobals.getInstance().mCM.getState() &&
!VTCallUtils.isVideoCall(mCM.getActiveFgCall())) {
// When voice is connected and place a VT call, need close VT GUI
mVTInCallScreen.setVTScreenMode(Constants.VTScreenMode.VT_SCREEN_CLOSE);
mVTInCallScreen.setVTScreenMode(Constants.VTScreenMode.VT_SCREEN_OPEN);
// set VT open or close according the active foreground call
if (mCM.getState() != PhoneConstants.State.IDLE && VTCallUtils.isVideoCall(mCM.getActiveFgCall())) {
if (DBG) {
log(&receive ACTION_MAIN, but active foreground call is video call&);
mVTInCallScreen.initVTInCallScreen();
mVTInCallScreen.initCommonVTState();
mVTInCallScreen.setVTScreenMode(Constants.VTScreenMode.VT_SCREEN_OPEN);
} else if (!intent.getBooleanExtra(Constants.EXTRA_IS_NOTIFICATION, false)) {
mVTInCallScreen.setVTScreenMode(Constants.VTScreenMode.VT_SCREEN_CLOSE);
mVTInCallScreen.updateVTScreen(mVTInCallScreen.getVTScreenMode());
//接听电话时触发
if (action.equals(Intent.ACTION_ANSWER)) {
internalAnswerCall();
mApp.setRestoreMuteOnInCallResume(false);
//OTA相关处理
if (action.equals(OtaUtils.ACTION_DISPLAY_ACTIVATION_SCREEN)) {
if (!TelephonyCapabilities.supportsOtasp(mPhone)) {
throw new IllegalStateException(
&Received ACTION_DISPLAY_ACTIVATION_SCREEN intent on non-OTASP-capable device: &
+ intent);
setInCallScreenMode(InCallScreenMode.OTA_NORMAL);
if ((mApp.cdmaOtaProvisionData != null)
&& (!mApp.cdmaOtaProvisionData.isOtaCallIntentProcessed)) {
mApp.cdmaOtaProvisionData.isOtaCallIntentProcessed =
mApp.cdmaOtaScreenState.otaScreenState =
CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION;
// 异常和未定义intent处理
if (action.equals(OtaUtils.ACTION_PERFORM_CDMA_PROVISIONING)) {
throw new IllegalStateException(
&Unexpected ACTION_PERFORM_CDMA_PROVISIONING received by InCallScreen: &
+ intent);
} else if (action.equals(Intent.ACTION_CALL)
|| action.equals(Intent.ACTION_CALL_EMERGENCY)) {
throw new IllegalStateException(&Unexpected CALL action received by InCallScreen: &
+ intent);
} else if (action.equals(ACTION_UNDEFINED)) {
Log.wtf(LOG_TAG, &internalResolveIntent: got launched with ACTION_UNDEFINED&);
Log.wtf(LOG_TAG, &internalResolveIntent: unexpected intent action: & + action);
InCallScreen初始化小结
经过以上几个关键步骤之后,InCallScreen的初始化就完成了,紧接着自然是进入onResume方法执行,这里就不展开去介绍onResume方法了,其主要就是为显示InCallScreen之前做一些准备工作和检查工作。
InCallScreenUI控制流程
通过前面的分析,InCallScreen的UI控制主要包括以下6个方面:
incomingCallWidget:接通/挂断/短信回复时需要使用;
dialpadButton:也就是显示或隐藏拨号盘(DTMF);
audioButton:开启/关闭扬声器;
muteButton:开启/关闭麦克风静音,开启之后对方无法听到你的声音;
holdButton:开启/关闭呼叫保持;
addButton:增加多路通话;也就是在通话的过程中可以暂停当前通话,拨打另一路通话并接通;
当我们点击addButton之后,会弹出拨号盘提示添加一路通话,添加通话之后整个InCallScreen界面将会变成如图5所示:
图 5 添加一路通话界面以及添加后界面
在改变之后的界面中,我们可以看到多了两个图标:和,前者表示在两路通话之间进行切换,后者表示开启视屏电话。
incomingCallWidget滑动控件
该滑动控件在来电的时候,会显示在InCallScreen界面上,默认情况下用户可以选择接听、挂断、挂断并短信回复三种模式,向右滑动为接听,向左滑动为挂断,向上滑动为挂断并选择快捷短信回复,如图6:
图 6 incomingCallWidget在来电时的显示
该控件只有在来电的时候才会显示出来,用户可以滑动中间的白色部分到图5中的三个方向:左、上、右,分别触发不同的效果。实际上该控件和解锁界面上的滑动解锁使用的是同一控件,使用滑动的方式触发不同的效果,接下来我们就来看看其控制流程吧。
1)布局文件
Phone/res/layout/incall_touch_ui.xml
&com.android.internal.widget.multiwaveview.GlowPadView
android:id=&@+id/incomingCallWidget&
android:layout_width=&match_parent&
android:layout_height=&wrap_content&
android:layout_gravity=&center|bottom&
android:layout_marginTop=&20dip&
android:layout_marginBottom=&-110dip&
android:background=&@android:color/black&
android:visibility=&gone&
android:gravity=&top&
prvandroid:targetDrawables=&@array/incoming_call_widget_3way_targets&
prvandroid:targetDescriptions=&@array/incoming_call_widget_3way_target_descriptions&
prvandroid:directionDescriptions=&@array/incoming_call_widget_3way_direction_descriptions&
prvandroid:handleDrawable=&@drawable/ic_in_call_touch_handle&
prvandroid:innerRadius=&@*android:dimen/glowpadview_inner_radius&
prvandroid:outerRadius=&@*android:dimen/glowpadview_target_placement_radius&
prvandroid:outerRingDrawable=&@*android:drawable/ic_lockscreen_outerring&
prvandroid:snapMargin=&@*android:dimen/glowpadview_snap_margin&
prvandroid:vibrationDuration=&20&
prvandroid:feedbackCount=&1&
prvandroid:glowRadius=&@*android:dimen/glowpadview_glow_radius&
prvandroid:pointDrawable=&@*android:drawable/ic_lockscreen_glowdot&
(2)初始化文件
Phone/src/com/android/phone/inCallTouchUi.java
(3)工作流程
首先初始化,代码如下:
private GlowPadView mIncomingCallW
mIncomingCallWidget = (GlowPadView) findViewById(R.id.incomingCallWidget);
mIncomingCallWidget.setOnTriggerListener(this);
通过初始化代码我们可以看到其注册了一个TriggerListener并且就在本类中就有其实现,那么我继续找到其TriggerListener的实现,代码如下:
* Handles &Answer& and &Reject& actions for an incoming call.
* We get this callback from the incoming call widget
* when the user triggers an action.
public void onTrigger(View view, int whichHandle) {
... ...省略
mShowInCallControlsDuringHidingAnimation =
switch (whichHandle) {
//来电选择接听电话
case ANSWER_CALL_ID:
if (DBG) log(&ANSWER_CALL_ID: answer!&);
cancelIncomingPingTime();
mInCallScreen.handleOnscreenButtonClick(R.id.incomingCallAnswer);
mShowInCallControlsDuringHidingAnimation =
mLastIncomingCallActionTime = SystemClock.uptimeMillis();
//来电选择挂断并通过短信回复
case SEND_SMS_ID:
if (DBG) log(&SEND_SMS_ID!&);
mInCallScreen.handleOnscreenButtonClick(R.id.incomingCallRespondViaSms);
//来电选择拒接
case DECLINE_CALL_ID:
if (DBG) log(&DECLINE_CALL_ID: reject!&);
mInCallScreen.handleOnscreenButtonClick(R.id.incomingCallReject);
mLastIncomingCallActionTime = SystemClock.uptimeMillis();
Log.wtf(LOG_TAG, &onDialTrigger: unexpected whichHandle value: & + whichHandle);
//隐藏滑动控件
hideIncomingCallWidget();
// Regardless of what action the user did, be sure to clear out
// the hint text we were displaying while the user was dragging.
mInCallScreen.updateIncomingCallWidgetHint(0, 0);
最终根据用户的不同选择,跳转到InCallScreen.java中的handleOnscreenButtonClick方法去执行具体代码,如下:
public void handleOnscreenButtonClick(int id) {
... ...省略
switch (id) {
//来电正常接听
case R.id.incomingCallAnswer:
internalAnswerCall();
//来电拒接
case R.id.incomingCallReject:
... ...省略
hangupRingingCall();
//来电拒接并短信回复
case R.id.incomingCallRespondViaSms:
internalRespondViaSms();
... ...省略
//更新InCallTouchUi
updateInCallTouchUi();
时序图以来电接听为例,如图7:
图 7 来电接听时序图
dialpadButton显示/隐藏拨号盘
这里提到的dialpadButton实际上为InCallTouchUi布局上的:。
该控件的作用是点击之后显示或隐藏拨号盘,当电话接通之后如果用户点击该控件则会如图8所示:
图 8 DTMF拨号盘
当用户再次点击该控件时,拨号盘隐藏。
(1)布局文件
Phone/res/layout/incall_touch_ui.xml
&ToggleButton android:id=&@+id/dialpadButton&
style=&@style/InCallCompoundButton&
android:background=&@drawable/btn_dialpad&
android:contentDescription=&@string/onscreenShowDialpadText&/&
Phone/res/layout/incall_screen.xml
&ViewStub android:id=&@+id/dtmf_twelve_key_dialer_stub&
android:layout=&@layout/dtmf_twelve_key_dialer_view&
android:layout_width=&match_parent&
android:layout_height=&match_parent&
android:layout_marginBottom=&@dimen/dialpad_vertical_margin_dtmf&/&
(2)初始化文件
Phone/src/com/android/phone/inCallTouchUi.java
Phone/src/com/android/phone/inCallScreen.java
(3)工作流程
控件初始化代码如下:
dialpadButton控件初始化:
private CompoundButton mDialpadB
mDialpadButton = (CompoundButton) mInCallControls.findViewById(R.id.dialpadButton);
mDialpadButton.setOnClickListener(this);
mDialpadButton.setOnLongClickListener(this);
这里的LongClick实际上是,在我们长按该控件时会弹出一个toast显示该控件的作用。
拨号盘控件初始化:
private DTMFTwelveKeyDialer mD
ViewStub stub = (ViewStub) findViewById(R.id.dtmf_twelve_key_dialer_stub);
mDialer = new DTMFTwelveKeyDialer(this, stub);
我们先找到mDialpadButton的onClick实现方法,如下:
public void onClick(View view) {
int id = view.getId();
... ...省略
switch (id) {
... ...省略
case R.id.dialpadButton:
... ...省略
mInCallScreen.handleOnscreenButtonClick(id);
... ...省略
这里还是调用了InCallScreen中的handleOnscreenButtonClick方法,代码如下:
public void handleOnscreenButtonClick(int id) {
... ...省略
switch (id) {
... ...省略
case R.id.dialpadButton:
onOpenCloseDialpad();
... ...省略
这里最终调用onOpenCloseDialpad方法去实现打开或者关闭拨号盘,这里我们继续查看onOpenCloseDialpad方法,代码如下:
public void onOpenCloseDialpad() {
... ...省略
//判断拨号盘是否已经打开,如果是则隐藏反之则显示
if (mDialer.isOpened()) {
closeDialpadInternal(true);
openDialpadInternal(true);
mApp.updateProximitySensorMode(mCM.getState());
//显示拨号盘
private void openDialpadInternal(boolean animate) {
mDialer.openDialer(animate);
mApp.inCallUiState.showDialpad =
//以藏拨号盘
private void closeDialpadInternal(boolean animate) {
mDialer.closeDialer(animate);
mApp.inCallUiState.showDialpad =
这里的拨号盘实际上是InCallScreen中一块独立的布局,也就是DTMFTwelveKeyDialer,当我们点击dialpadButton后,最终调用到openDialpadInternal或者closeDialpadInternal,通过mDialer去实现拨号盘的显示或隐藏,如mDialer.openDialer代码如下:
public void openDialer(boolean animate) {
... ...省略
if (!isOpened()) {
// 这里animate=true
if (animate) {
AnimationUtils.Fade.show(mDialerView);
... ...省略
查看AnimationUtils.Fade.show方法如下:
public static void show(final View view) {
... ...省略
view.setVisibility(View.VISIBLE);
... ...省略
最终使得mDialerView显示到界面上。
图 9 接通后显示拨号盘时序图
audioButton开启/关闭扬声器
扬声器实际上就是手机的外放,在InCallTouchUi布局上显示为:。
该控件的作用是点击之后开启或关闭扬声器,也就是使得对方的通话声音能够通过外放增大。如果我们此时连接了蓝牙耳机,那么显示界面如图10所示:
图 10 接入蓝牙耳机后InCallTouchUi上audioButton改变
我可以选择三种不同的音频输出方式:Speaker即扬声器,Handset earpiece手机听筒,Bluetooth蓝牙耳机。
(1)布局文件
Phone/res/layout/incall_touch_ui.xml
&ToggleButton android:id=&@+id/audioButton&
style=&@style/InCallCompoundButton&
android:background=&@drawable/btn_compound_audio&
android:contentDescription=&@string/onscreenAudioText&/&
(2)初始化文件
Phone/src/com/android/phone/inCallTouchUi.java
(3)工作流程
控件初始化代码如下:
audioButton控件初始化:
private CompoundButton mAudioB
mAudioButton = (CompoundButton) mInCallControls.findViewById(R.id.audioButton);
mAudioButton.setOnClickListener(this);
mAudioButton.setOnLongClickListener(this);
这里的LongClick实际上是,在我们长按该控件时会弹出一个toast显示该控件的作用。找到audioButton的onClick实现方法,如下:
public void onClick(View view) {
int id = view.getId();
... ...省略
switch (id) {
... ...省略
case R.id.audioButton:
... ...省略
handleAudioButtonClick();
... ...省略
这里的handleAudioButtonClick方法对是否接入了蓝牙耳机进行了判断,如果是则会像图9所示那样,弹出三个选项按钮。这里我们假设没有连接蓝牙耳机,代码如下:
private void handleAudioButtonClick() {
... ...省略
//如果连接了蓝牙耳机则执行if里面的代码
if (inCallControlState.bluetoothEnabled) {
... ...省略
... ...省略
mInCallScreen.toggleSpeaker();
这里我们继续查看InCallScreen中的toggleSpeaker方法:
public void toggleSpeaker() {
... ...省略
PhoneUtils.turnOnSpeaker(this, newSpeakerState, true);
... ...省略
这里最终交由PhoneUtils中的turnOnSpeaker去最终负责打开扬声器。
图 11 开启/关闭扬声器
muteButton开启/关闭麦克风静音
麦克风静音的作用是在通话过程中,屏蔽自己这段的声音输入,在InCallTouchUi布局上显示为:。
(1)布局文件
Phone/res/layout/incall_touch_ui.xml
&ToggleButton android:id=&@+id/muteButton&
style=&@style/InCallCompoundButton&
android:background=&@drawable/btn_compound_mute&
android:contentDescription=&@string/onscreenMuteText&/&
(2)初始化文件
Phone/src/com/android/phone/inCallTouchUi.java
(3)工作流程
控件初始化代码如下:
muteButton控件初始化:
private CompoundButton mMuteB
mMuteButton = (CompoundButton) mInCallControls.findViewById(R.id.muteButton);
mMuteButton.setOnClickListener(this);
mMuteButton.setOnLongClickListener(this);
这里的LongClick实际上是,在我们长按该控件时会弹出一个toast显示该控件的作用。找到muteButton的onClick实现方法,如下:
public void onClick(View view) {
int id = view.getId();
... ...省略
switch (id) {
... ...省略
case R.id.muteButton:
... ...省略
mInCallScreen.handleOnscreenButtonClick(id);
... ...省略
依然调用了InCallScreen中的handleOnscreenButtonClick方法,代码如下:
public void handleOnscreenButtonClick(int id) {
... ...省略
switch (id) {
... ...省略
case R.id.muteButton:
onMuteClick();
... ...省略
然后调用onMuteClick方法来实现开启/关闭麦克风静音功能,代码如下:
public void onMuteClick() {
... ...省略
PhoneUtils.setMute(newMuteState);
... ...省略
最终的实现仍然在PhoneUtils中的setMute方法,该方法将继续传递直到audioManager去执行该静音操作。
图 12 麦克风静音开启/关闭
holdButton开启/关闭呼叫保持
holdButton实际上就是呼叫保持的开关,用户可以暂停当前通话,在InCallTouchUi布局上显示为:。当用户在通话过程中点击该图标之后,对方将会听到类&#20284;提示音“请稍等,现在是呼叫保持……”,该功能用于在两路通话之间进行切换,但只有一路通话时无法开启呼叫保持功能。
(1)布局文件
Phone/res/layout/incall_touch_ui.xml
&ToggleButton android:id=&@+id/holdButton&
style=&@style/InCallCompoundButton&
android:background=&@drawable/btn_compound_hold&
android:contentDescription=&@string/onscreenHoldText&/&
(2)初始化文件
Phone/src/com/android/phone/inCallTouchUi.java
(3)工作流程
控件初始化代码如下:
muteButton控件初始化:
private CompoundButton mHoldB
mHoldButton = (CompoundButton) mInCallControls.findViewById(R.id.holdButton);
mHoldButton.setOnClickListener(this);
mHoldButton.setOnLongClickListener(this);
这里的LongClick实际上是,在我们长按该控件时会弹出一个toast显示该控件的作用。找到holdButton的onClick实现方法,如下:
public void onClick(View view) {
int id = view.getId();
... ...省略
switch (id) {
... ...省略
case R.id.muteButton:
... ...省略
mInCallScreen.handleOnscreenButtonClick(id);
... ...省略
依然调用了InCallScreen中的handleOnscreenButtonClick方法,代码如下:
public void handleOnscreenButtonClick(int id) {
... ...省略
switch (id) {
... ...省略
case R.id.holdButton:
onHoldClick();
... ...省略
然后调用onHoldClick方法来实现开启/关闭呼叫保持功能,代码如下:
private void onHoldClick() {
... ...省略
if (hasActiveCall && !hasHoldingCall) {
// 开启呼叫保持
PhoneUtils.switchHoldingAndActive(
mCM.getFirstActiveBgCall());
// Really means &hold& in this state
newHoldState =
holdButtonEnabled =
} else if (!hasActiveCall && hasHoldingCall && !haveMultipleHoldingCall) {
// 取消呼叫保持
PhoneUtils.switchHoldingAndActive(
mCM.getFirstActiveBgCall());
// Really means &unhold& in this state
newHoldState =
holdButtonEnabled =
... ...省略
// 强制关闭拨号盘
closeDialpadInternal(true);
// do the &closing& animation
继续追踪可以找到PhoneUtils中的switchHoldingAndActive方法,代码如下:
static void switchHoldingAndActive(Call heldCall) {
... ...省略
CallManager cm = PhoneGlobals.getInstance().mCM;
... ...省略
cm.switchHoldingAndActive(heldCall);
... ...省略
最终的实现会通过CallManager一层层的向下传递,并最终实现呼叫保持功能。
图 13 呼叫保持开启/关闭
addButton添加一路通话
addButton的意思就是在当前通话的基础上添加一路通话,当前通话将会切换到呼叫保持状态。该图标在InCallTouchUi布局上显示为:。
当用户在当前通话过程中点击该图标之后,界面出现拨号盘,如果添加一路通话成功则会如下图14所示:
图 14 添加一路通话界面以及添加后界面
(1)布局文件
Phone/res/layout/incall_touch_ui.xml
&ImageButton android:id=&@+id/addButton&
style=&@style/InCallButton&
android:src=&@drawable/ic_add_contact_holo_dark&
android:contentDescription=&@string/onscreenAddCallText&/&
(2)初始化文件
Phone/src/com/android/phone/inCallTouchUi.java
(3)工作流程
控件初始化代码如下:
addButton控件初始化:
private CompoundButton mAddB
mAddButton = (CompoundButton) mInCallControls.findViewById(R.id.addButton);
mAddButton.setOnClickListener(this);
mAddButton.setOnLongClickListener(this);
这里的LongClick实际上是,在我们长按该控件时会弹出一个toast显示该控件的作用。找到holdButton的onClick实现方法,如下:
public void onClick(View view) {
int id = view.getId();
... ...省略
switch (id) {
... ...省略
case R.id.addButton:
... ...省略
mInCallScreen.handleOnscreenButtonClick(id);
... ...省略
依然调用了InCallScreen中的handleOnscreenButtonClick方法,代码如下:
public void handleOnscreenButtonClick(int id) {
... ...省略
switch (id) {
... ...省略
case R.id.addButton:
onAddCallClick();
... ...省略
然后调用onAddClick方法来实现增加一路通话的功能,代码如下:
private void onAddCallClick() {
PhoneUtils.startNewCall(mCM);
继续追踪可以找到PhoneUtils中的startNewCall方法,代码如下:
/* package */ static boolean startNewCall(final CallManager cm) {
final PhoneGlobals app = PhoneGlobals.getInstance();
... ...省略
// 将当前的通话静音
if (cm.hasActiveFgCall()) {
setMuteInternal(cm.getActiveFgCall().getPhone(), true);
app.setRestoreMuteOnInCallResume(true);
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(ADD_CALL_MODE_KEY, true);
//跳转到拨号界面
app.startActivity(intent);
} catch (ActivityNotFoundException e) {
... ...省略
需要注意的是,当我们点击addButton后,当前通话会开启静音功能,在我们拨打新一路通话时,先前的通话将会自动切换到呼叫保持状态。这里的Intent.ACTION_DIAL查找对应的具体字符串为“android.intent.action.DIAL”,查找对应的Activity找到Contacts中的NoPhoneActivity,该Activity用于加载拨号盘。
图 15 新增一路通话时序图
endButton挂断当前通话
endButton就是挂断电话的那个按钮,点击之后将挂断当前通话。该图标在InCallTouchUi布局上显示为:。
(1)布局文件
Phone/res/layout/incall_touch_ui.xml
&ImageButton android:id=&@+id/endButton&
style=&@style/InCallEndButton&
android:layout_width=&match_parent&
android:layout_weight=&1&
android:src=&@drawable/ic_end_call&
android:background=&@drawable/end_call_background&
android:contentDescription=&@string/onscreenEndCallText& /&
(2)初始化文件
Phone/src/com/android/phone/inCallTouchUi.java
(3)工作流程
控件初始化代码如下:
endButton控件初始化:
private CompoundButton mEndB
mEndButton = (CompoundButton) mInCallControls.findViewById(R.id.addButton);
mEndButton.setOnClickListener(this);
这里只注册了onClick的监听事件,没有LongOnClick的监听事件。找到endButton的onClick实现方法,如下:
public void onClick(View view) {
int id = view.getId();
... ...省略
switch (id) {
... ...省略
case R.id.endButton:
... ...省略
mInCallScreen.handleOnscreenButtonClick(id);
... ...省略
依然调用了InCallScreen中的handleOnscreenButtonClick方法,代码如下:
public void handleOnscreenButtonClick(int id) {
... ...省略
switch (id) {
... ...省略
case R.id.endButton:
internalHangup();
... ...省略
然后调用internalHangup方法来实现挂断当前通话,代码如下:
private void internalHangup() {
... ...省略
PhoneUtils.hangup(mCM);
... ...省略
继续追踪可以找到PhoneUtils中的hangup方法,代码如下:
public static boolean hangup(CallManager cm) {
... ...省略
ringing = cm.getFirstActiveRingingCall();
fg = cm.getActiveFgCall();
bg = cm.getFirstActiveBgCall();
... ...省略
//因为选择的是挂断当前通话,因此fg.isIdle()为false
} else if (!fg.isIdle() || fg.state == Call.State.DISCONNECTING) {
if (DBG) log(&hangup(): hanging up foreground call&);
hungup = hangup(fg);
... ...省略
这里我们需要注意,fg=cm.getActiveFgCall返回类型是Call类型的,这里的hangup(fg)实际处理代码为:
static boolean hangup(Call call) {
... ...省略
//挂断当前通话
call.hangup();
... ...省略
到了这里需要注意下,这里的call对象是什么呢?因为我们这里使用的是GSM卡(WCDMA卡也一样),因此这里我们实际上得到的call对象是GsmCall.java的对象,从而直接找到GsmCall中的hangup方法,代码如下:
public void
hangup() throws CallStateException {
owner.hangup(this);
这里最终会调用到GsmCallTracker中的hangup(GsmCall)方法中去,这里就不详解了。
图 16 挂断当前通话时序图
InCallScreen CallCard通话信息显示
CallCard说起来感觉很陌生,实际上在我们通话过程中,除了InCallTouchUi之外,InCallScreen所展示的界面就是CallCard了,如图17:
图 17 CallCard通话信息
如图17所显示,CallCard包含了通话时间、通话背景、通话对象号码(10086)、来电/去电状态、号码归属地、SIM卡运营商类型。
CallCard布局文件
通话信息界面实际上也在incall_screen.xml的布局中,但实际引用的布局为call_card.xml,整个call_card的布局较为复杂,因为通话可以是一路通话但也可以是两路通话,可以是来电也可以是去电,因此CallCard的布局较为繁杂,通过Hierarchy Viewer可以查看到。
CallCard界面更新
因为CallCard界面主要用于告知用户当前的通话状态,主要反映的是一些状态信息,因此我们主要查看其更新的代码,在InCallScreen的onResume中,我们可以看到有关于同步Phone状态的代码如下:
SyncWithPhoneStateStatus status = syncWithPhoneState();
而这里的syncWithPhoneState方法就是用于同步Phone的状态,代码如下:
private SyncWithPhoneStateStatus syncWithPhoneState() {
... ...省略
if (mCM.hasActiveFgCall() || mCM.hasActiveBgCall() || mCM.hasActiveRingingCall()
|| hasPendingMmiCodes || hasPendingMmiCodes2 || showProgressIndication || showScreenEvenAfterDisconnect) {
if (VDBG) log(&syncWithPhoneState: it' update the screen...&);
updateScreen();
return SyncWithPhoneStateStatus.SUCCESS;
... ...省略
这里会执行到updateScreen方法中,继续查看代码:
private void updateScreen() {
... ...省略
mCallCard.updateState(mCM);
... ...省略
因为这里我们主要关注CallCard的更新,其它内容就省略掉了。这里调用了CallCard的对象mCallCard,并调用其中的updataState方法。如下:
/* package */ void updateState(CallManager cm) {
... ...省略
//更新来电信息
updateRingingCall(cm);
... ...省略
//更新当前通话信息
updateForegroundCall(cm);
... ...省略
//更新已断开连接的通话信息
updateAlreadyDisconnected(cm);
... ...省略
//更新没有通话的界面信息
updateNoCall(cm);
... ...省略
在updateState中会根据不同的条件选择更新不同的界面,从而在InCallScreen中展示不同的结果。有以下四个方法用于更新不同状态下的CallCard信息:
updateRingingCall:显示/更新来电界面信息;
updateForegroundCall:显示/更新当前通话界面信息;updateAlreadyDisconnected:更新/显示已断开连接的通话界面信息,该界面只是一瞬间状态;
updateNoCall:更新/显示没有通话时的通话界面信息;该界面一般不会出现,只为以防万一;
CallCard更新时序图
图18 CallCard更新时序图
在MTK的Android 4.2平台上,InCallScreen相对于原生的界面改动不算大,但其也增加了一些属于自己的东西,如:视屏通话界面,双卡控制界面,来电归属地等等,这些功能的添加使得Android手机在使用上更加便捷,也增加了用户体验。
在弄清楚了这界面UI的控制流程之后,对于修改InCallScreen界面有很大帮助,便于后续对InCallScreen进行个性化定制。
本文旨在分析InCallScreen上的UI控制流程,基于MTK Android 4.2的源码分析,其中不乏缺漏之处还恳请各位看官见谅。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:309720次
积分:3772
积分:3772
排名:第2719名
原创:52篇
评论:325条
(1)(1)(1)(1)(1)(2)(3)(1)(1)(1)(1)(1)(1)(2)(1)(1)(1)(1)(4)(1)(4)(3)(1)(1)(3)(2)(7)(1)(1)(3)

我要回帖

更多关于 ios8来电界面 的文章

 

随机推荐