Android N 通话界面_InCallActivity

时间:2021-11-20 20:31:29

本流程图基于MTK平台 Android 7.0,普通来电,本流程只作为沟通学习使用

本篇博客主要来看看整个 IncallUI 界面的容器 InCallActivity

InCallActivity

启动流程

我们知道正常情况下 InCallActivity 的启动分两种情况,MOMT 我们就以 MO 为例来看看它的启动流程(MT其实也差不多)
Android N 通话界面_InCallActivity

最关键的两个地方:

1.//InCallController.connect 方法中通过binder 绑定到了InCallService 服务
Intent intent = new Intent(InCallService.SERVICE_INTERFACE);

2.//InCallPresenter.getInCallIntent 中指定了启动的界面
intent.setClass(mContext, InCallActivity.class);

类图关系

Android N 通话界面_InCallActivity

通过上面的类图关系我们可以知道,InCallActivity 是整个 incallUI 的容器,它控制着几乎所有 fragment 的显示和隐藏,然而 InCallPresenter 又控制着 InCallActivity 的创建和销毁。InCallPresenter 还类似于一个状态机,它控制并管理者大部分 与call 相关的状态,incallUI 上面和 call 相关的界面变化都会通过 InCallPresenter 来收集和分发。

界面布局

<!-- In-call Phone UI; see InCallActivity.java. -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:id="@+id/main" >

</FrameLayout>

InCallActivity 的layout 是 incall_screen,然而 incall_screen 的所有代码就只有上面那么6行,只定义了一个占满全屏的 FrameLayout 里面什么子控件都没有,那么复杂的incallUI又是怎么显示出来的呢?
其实 InCallActivity 的作用就如我上面所说,针对界面显示而言它只是一个容器,具体的界面实现是通过加载 CallCardFragment 来显示的(onCreate–>internalResolveIntent–>showCallCardFragment(true)),下面我们就来简单分析一下 CallCardFragment 吧。

CallCardFragment

类图关系

Android N 通话界面_InCallActivity

部分说明:

  • call_card_fragment 是 CallCardFragment 的布局文件,它里面不仅包含很多控件,还include 了其它的布局文件
  • CallCardFragment 中又包含了 AnswerFragment、DialpadFragment、CallButtonFragment、VideoCallFragment等一系列 fragment
  • CallCardPresenter 控制着整个界面的逻辑处理

界面分析

整体图

声明:下图为了说明,通过特别的代码修改故意显示部分在特殊条件下才会显示的图标,请不要被误导。

Android N 通话界面_InCallActivity

布局文件call_card_fragment分析

这个布局文件整体是个 RelativeLayout 布局,可以分成上下两个部分(对应于上图):

上半部分

这部分是一个垂直方向的 LinearLayout 布局,包含一个新的布局文件 primary_call_info 和 CallButtonFragment 界面,这里我们重点看一下 primary_call_info 布局文件信息。

primary_call_info

整体是个垂直方向的 LinearLayout 布局:

  1. 第一行:callSubject,call的主题,通过call.getCallSubject方法拿到并显示的字符串,一般都为空,如果为空则设置为不可见GONE。
  2. 第二行:水平的 LinearLayout 布局,包含多个信息,1.workProfileIcon,工作账户图标,通过call.hasProperty(PROPERTY_ENTERPRISE_CALL); 判读是否有这个属性决定显示和隐藏,显示在这行靠右下方、2.callStateIcon,sim卡图标或者WiFicall 图标,包括connection的状态图标,CallCardPresenter.getCallStateIcon 返回不为null则显示、3.videoCallIcon,video通话图标,如果是video通话则显示(VideoUtils.isVideoCall(videoState))、4.callStateLabel,显示当前call的状态字符串,根据CallCardFragment.getCallStateLabelFromState方法来确定显示的字符串(通过CallCardPresenter.getConnectionLabel来区分手机单卡和双卡显示的不同字符串),一直都会显示,并且动态改变。
  3. 第三行:一个RelativeLayout布局,包含两个控件,1.name,显示对方的名字或者电话号码,一直显示、2.photoSmall,显示对方小头像,显示在这行最右边,当底部大头像显示时,这个小头像不显示CallCardFragment.showContactContext。
  4. 第四行:水平的 LinearLayout 包含了多个控件,1.hdAudioIcon,HD图标,通过call.hasProperty(Details.PROPERTY_HIGH_DEF_AUDIO)判断是否显示、2.forwardIcon,呼叫转接图标,表示当前号码是通过指定号码转接过来的,如果Call.getLastForwardedNumber不为null则显示、3.电话类型label,比如: work,monile,sip等,是保存当前联系人时用户自己指定的、4.显示来电号码phoneNumber,如果当前来电不是已存联系人,则name就显示了电话号码,此处就显示地理位置,CallCardPresenter.getNumberForCall、5.elapsedTime,显示当前电话接通后已经过去的时间,显示在这行的最右边。
  5. 第五行:callTypeLabel,如果当前是SIP phone 的话显示这个textview。
CallButtonFragment

这个在之前的博客中有详细介绍,可以参考:Android N Phone_通话界面_CallButtonFragment 这篇博客。

下半部分

下半部分就包含很多内容了,它们相互并列重叠,大部分通过代码动态控制显示和隐藏。

相关说明如下:
由上到下分别为:

  • answer_and_dialpad_container,是一个FrameLayout,我们的 AnswerFragmentr界面和 DialpadFragment界面通过 InCallActivity.getContainerIdForFragment 方法动态的显示在这个控件上面,它可以覆盖整个下半部分。
  • secondary_call_info,include 了另外一个布局文件,显示在下半部分的最底部,如果当前有 activity 的 call 和 hold 的 call ,则此处显示 hold call 的信息,并且点击会切换 activity 和 hold 状态。
  • manage_conference_call_button,include 了另外一个布局文件,显示在整体的最底部,如果当前是会议电话则显示,最终通过InCallActivity.createNewFragmentForTag去显示ConferenceManagerFragment。
  • floating_end_call_action_button,显示在整体的底部居中,通话的挂断按钮。
  • progressSpinner,ProgressBar进度条,通过 CallCardPresenter.maybeShowProgressSpinner 控制显示和隐藏进度条
  • VideoCallFragment,显示在整个下半部分,布局文件video_call_fragment,通过 ViewStub占位符来加载具体的 layout 布局文件 video_call_views,通过 VideoCallFragment.inflateVideoUi 控制是否 inflate 具体的布局文件,从而控制VideoCallFragment 的显示和隐藏,最终还是通过 call.getVideoState() 获取当前的call是否是 videocall 来确定是否显示的,ViewStub本身是不可见的。
  • photoLarge,显示大头像占满整个下半部分。
  • voiceRecorderIcon,显示录音图标,显示在界面右边。
  • contact_context,包含一个 textview 和一个 listview,显示联系人交互信息,包括商业和个人,当 photoLarge 没有显示时才会显示这些信息。显示在整个下半部分。