去电界面启动分析---之二

来源:互联网 发布:javascript入门经典 5 编辑:程序博客网 时间:2024/06/05 14:26

1.3启动去电界面

在InCallController的onCallAdded方法中有关去电界面的代码如下,

inCallService.addCall(parcelableCall);

通过binder跨进程调用Incall 的InCallService内部类InCallServiceBinder的addCall方法,

public void addCall(ParcelableCall call) {    mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget();}

mHandler的handleMessage对MSG_ADD_CALL消息处理如下,

case MSG_ADD_CALL:    mPhone.internalAddCall((ParcelableCall) msg.obj);    break;

此时实际上运行于dailer进程中, Phone的internalAddCall方法调用流程图如下,


Phone的internalAddCall方法如下,

final void internalAddCall(ParcelableCall parcelableCall) {    Call call = new Call(this, parcelableCall.getId(), mInCallAdapter,             parcelableCall.getState(), parcelableCall.isActive());    mCallByTelecomCallId.put(parcelableCall.getId(), call);    mCalls.add(call);    checkCallTree(parcelableCall);    call.internalUpdate(parcelableCall, mCallByTelecomCallId);    fireCallAdded(call);}

fireCallAdded方法如下,

private void fireCallAdded(Call call) {     for (Listener listener : mListeners) {         listener.onCallAdded(this, call);     }}

Listener监听器是Phone的内部接口,

变量mListeners list中保存着所有注册的监听器,

private final List<Listener> mListeners = new CopyOnWriteArrayList<>();

调用addListener方法添加监听器,

public final void addListener(Listener listener) {     mListeners.add(listener);}

在此,会回调InCallService的匿名Phone.Listener的onCallAdded方法,

是在设置InCallAdapter过程中处理MSG_SET_IN_CALL_ADAPTER消息时注册监听器的,

case MSG_SET_IN_CALL_ADAPTER:    mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj));    mPhone.addListener(mPhoneListener);//注册监听器    onPhoneCreated(mPhone);    break;

Phone.Listener的onCallAdded方法如下,

public void onCallAdded(Phone phone, Call call) {    InCallService.this.onCallAdded(call);}

onCallAdded在子类InCallServiceImpl中实现,如下,

public void onCallAdded(Call call) {      CallList.getInstance().onCallAdded(call);      InCallPresenter.getInstance().onCallAdded(call);}

CallList的onCallAdded方法如下,

public void onCallAdded(android.telecom.Call telecommCall) {     Trace.beginSection("onCallAdded");     Call call = new Call(telecommCall);//构造call对象     Log.d(this, "onCallAdded: callState=" + call.getState());     if (call.getState() == Call.State.INCOMING ||          call.getState() == Call.State.CALL_WAITING) {          onIncoming(call, call.getCannedSmsResponses());//如果是来电     } else {          onUpdate(call);//更新call     }    Trace.endSection();}

notifyGenericListeners方法如下,

private void notifyGenericListeners() {    for (Listener listener : mListeners) {        listener.onCallListChange(this);    }}

Listener 监听器也是CallList的接口,也是在addListener方法中注册,

public void addListener(Listener listener) {     Preconditions.checkNotNull(listener);     mListeners.add(listener);     // Let the listener know about the active calls immediately.    listener.onCallListChange(this);}

InCallPresenter实现了CallList.Listener接口,

public class InCallPresenter implements CallList.Listener,

并且在setUp方法中调用CallList的addListener方法注册监听器,

mCallList.addListener(this);

在InCallPresenter的startOrFinishUi方法中,会进行各种判断,其中,来电的有关代码如下,

if (showCallUi || showAccountPicker || isAutoAnswer) {            Log.i(this, "Start in call UI");    showInCall(false /* showDialpad */, !showAccountPicker /* newOutgoingCall */);

showInCall方法如下,

public void showInCall(final boolean showDialpad, final boolean newOutgoingCall) {    Log.i(this, "Showing InCallActivity");    mContext.startActivity(getInCallIntent(showDialpad, newOutgoingCall));}

getInCallIntent方法如下,

public Intent getInCallIntent(boolean showDialpad, boolean newOutgoingCall) {      final Intent intent = new Intent(Intent.ACTION_MAIN, null);      intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NEW_TASK);      intent.setClass(mContext, InCallActivity.class);      if (showDialpad) {          intent.putExtra(InCallActivity.SHOW_DIALPAD_EXTRA, true);      }      intent.putExtra(InCallActivity.NEW_OUTGOING_CALL_EXTRA, newOutgoingCall);      return intent;}

因此,启动的是InCallActivity来显示来电界面,这样,转了这么久,来电界面终于显示出来了。至于去电界面的具体view在此就不论述了。

Dialer的AndroidManifest.xml有关InCallActivity如下,

<activity android:name="com.android.incallui.InCallActivity"       android:theme="@style/Theme.InCallScreen"       android:label="@string/phoneAppLabel"       android:excludeFromRecents="true"       android:launchMode="singleInstance"       android:configChanges="keyboardHidden"       android:exported="false"       android:screenOrientation="nosensor" ></activity>