1.?拨号界面
1)?Contacts包里面的TwelvekeyDialer.java,为Activity对象。
2)?首先使用onCreate()创建一个Activity,该Activity显示了一个拨号的界面。
3)?按数字键使得onClick()方法被触发,由Riddial拨号键使得onClick()方法调用placeCall()方法。
4)?placeCall()方法中通过Intent跳转到另一个Activity。由代码“Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED,Uri.fromParts("tel", number, null));”可知其参数为Intent.ACTION_CALL_PRIVILEGED。查找文件Intent.java中参数声明,可知ACTION_CALL_PRIVILEGED=android.intent.action.CALL_PRIVILEGED,再通过查找Phone下面的androidmanifest.xml,知道OutgoingCallBroadcaster设置的一项intent-filter的action name为android.intent.action.CALL_PRIVILEGED,故可知下一个跳转的界面为OutgoingCallBroadcaster。
5)?该Acitivity进入onPause()。
2.?界面跳转
1)?OutgoingCallBroadcaster.java,为Activity对象。
2)?使用onCreate()创建一个Activity,该Activity应该为介于拨号界面跟通话界面之间跳转的一个界面。
3)?在onCreate()方法中调用了PhoneApp.getInstance().wakeUpScreen()方法(PhoneApp应该为对通话的在后台做进程管理)。
4)?另外在onCreate()方法中使用Intent跳转到一个BroadcastReceiver。由代码“Intent broadcastIntent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);”可知其参数为Intent.ACTION_NEW_OUTGOING_CALL。查找文件Intent.java中参数声明,可知ACTION_NEW_OUTGOING_CALL=android.intent.action.NEW_OUTGOING_CALL,再通过查找Phone下面的androidmanifest.xml,知道OutgoingCallReceiver设置的一项intent-filter的action name为android.intent.action.NEW_OUTGOING_CALL,故可知OutgoingCallReceiver接收OutgoingCallBroadcaster发过来的信息。
3.?接收广播
1)?OutgoingCallReceiver.java,为BroadcastReceiver对象。
2)?在onRecive()方法中,通过Intent跳转到新的Activity。由代码“Intent newIntent = new Intent(Intent.ACTION_CALL, uri);”可知其参数为Intent.ACTION_CALL。查找文件 Intent.java中参数声明,可知ACTION_CALL=android.intent.action.CALL,通过查找Phone下面的androidmanifest.xml,知道OutgoingCallBroadcaster设置的几项intent-filter的action name为android.intent.action.CALL,OutgoingCallReceiver设置的一项intent-filter的action name为android.intent.action.CALL。
3)?通过代码语句“newIntent.setClass(context, InCallScreen.class);”可知其参数为InCallScreen.class,故当前的Intent切换为InCallScreen。通过代码语句newIntent.startActivity(newIntent)激活InCallScreen Activity,故下一个将跳到InCallScreen界面。
4.?通话界面
1)?InCallScreen.java,为Activity对象。
1.1)?如果是第一次拨打电话,则调用onCreare()方法,该方法会调用initInCallScreen()方法,这样将会创建一个通话界面。
1.2)?在onResume()方法中调用了isBluetoothAudioConnected(),setInCallScreenMode(),并创建了一个PhoneApp实例,调用该对象的updateWakeState()方法。
1.3)?在setInCallScreenMode()方法中调用了updateMenuButtonHint()方法。
1.4)?接下了执行getBitmapAccordingNumber()方法。(该方法或许是在handleMessage()方法下触发的)
1.5)?再接着执行onPhoneStateChanged()方法。(该方法或许是在handleMessage()方法下触发的),在该方法中调用了updateScreen()方法。
1.6)?在updateScreen()方法中顺次调用了dismissMenu(),CallCard的updateState()方法,updateMenuButtonHint()方法。
2)?CallCard.java,为FrameLayout对象。
2.1)?该对象显示了通话对方的信息和通话时间。
2.2)?在1.6)调用的updateState()方法中又实现了updateNoCall()操作。
2.3)?在updateNoCall()中,顺次执行了了displayMainCallStatus(),displayOnHoldCallStatus(),displayOngoingCallStatus()方法。
3)?PhoneApp.java,为Application对象
3.1)?在1.5)执行的onPhoneStateChanged()方法,调用了updateWakeState()方法。
4)?InCallScreen.java
4.1)?onWindowFocusChanged()方法被执行。我不清楚这个是怎么被触发的,可能是由后台控制程序来引发的。
4.2)?接下来执行internalResolveIntent()方法(该方法或许是在handleMessage()方法下触发的),在该方法中调用了placeCall()方法。
4.3)?在4.2)执行的placeCall()方法中调用了checkIfOkToInitiateOutgoingCall()方法,以及isBluetoothAvailable()方法。
4.4)?再下来执行isBluetoothAudioConnected()方法。(该方法或许是在handleMessage()方法下触发的),这里与蓝牙怎么扯上了关系?
4.5)?再接着执行enableSensor()方法。(该方法或许是在onStop(),realFinish(),onClick(),handleMessage()方法下触发的)应该是说有关传感器的功能吧!
4.6)?再接着updateScreen()方法。(该方法或许是在placeCall(),handleMessage(),onDisConnect()方法下触发的)
4.7)?再接着okToDialDTMFTones()方法。(该方法或许是在okToShowDialpad(),handleDialerKeyDown()下触发的)
备注:前面这几步没有明显地调用过程,所以我不知道到底怎么跳转的,或许是在后台程序中控制好的。
5)?PhoneUtils.java,为一个类。
5.1)?在logcat中,显示语句“- okToSwapCalls call state is : SINGLE_ACTIVE”,但是不知道怎么跳到这里的。
6)?InCallScreen.java
6.1)?isBluetoothAvailable()方法被调用,但是不知道是怎么被调用到的。此外我不知道为什么需要调用蓝牙功能,通话与这个功能有什么关系。
6.2)?updateScreen()方法被执行。该方法应该是后台所控制执行的。我猜测既然上面做了很大一部分的变化工作,那么屏幕做一下更新是所必须的。
7)?CallCard.java
7.1)?由6.2)的updateScreen()方法调用,触发了updateState()方法。
7.2)?在7.1)的updateState()方法中,又调用了updateForegroundCall()方法。
7.3)?由7.2)的updateForegroundCall()方法进一步执行了displayMainCallStatus()方法。
7.4)?由7.3)的displayMainCallStatus()方法引发了updateCardTitleWidgets()方法。
7.5)?由7.4)的updateCardTitleWidgets()方法引发了getTitleForCallCard()方法。
7.6)?由7.3)的displayMainCallStatus()方法引发了updateDisplayForPerson()方法。
7.7)?由7.3)的displayMainCallStatus()方法引发了updatePhotoForCallState()方法。
7.8)?由7.2)的updateForegroundCall()方法进一步执行了displayOnHoldCallStatus()方法。
7.9)?由7.2)的updateForegroundCall()方法进一步执行了displayOngoingCallStatus()方法。
8)?InCallScreen.java
8.1)?由6.2)的updateScreen()方法调用,触发了updateMenuButtonHint()方法。
8.2)?在8.1)的updateMenuButtonHint()方法中,又调用了getBitmapAccordingNumber()方法。
9)?CallNotifier.java,为一个Handle对象
9.1)?onPhoneStateChanged()方法被执行。应该是由后台进程来控制执行的。
10)?InCallScreen.java
10.1)?onPhoneStateChanged()方法被执行。应该是由后台进程来控制执行的。
10.2)?由10.1)的onPhoneStateChanged()方法触发了updateScreen()方法,使得开始执行4.6)到8.2)
11)?PhoneApp.java
11.1)?由10.1)的onPhoneStateChanged()方法触发了updateWakeState()方法。
12)?重复执行9)--11)两次。持续对卡信息进行监听。
看来您对PHONE.APK源码了解的很强。我想请教您个问题,
1. InCallScreen是通话界面吗?现在android通话界面全是竖屏,我想改为横屏,
在androidMainfest.xml里 将InCallScreen横竖属性修改就OK了吗?
2. 现在我把源码 androidMainfest.xml修改了,重新编译phone. apk后运行 异常。
错误为add_service Permission denied, java.lang.securityException.
权限异常错误,我后来跟踪了下代码,代码在这句报错:
PhoneFactory.makeDefaultPhones(this);
请问我该如何解决错误啊?