由于Google 默认设计中来电铃声一路和UI启动一路是分开跑,通常情形下UI一路的启动要比响铃更耗时间;所以会存在来电界面起来比铃声稍晚的用户体验,尤其是在灭屏时候的来电。下面的Workround方法给出了L版本上对于此问题的优化方案。
Telecom将来电响铃的逻辑屏蔽,InCallPresenter在收到来电消息时,判断当前是否是亮屏状态,如果是亮屏状态,InCall调用底层的方法进行响铃.
如果是黑屏,在收到来电消息的时候,不做响铃操作,在进入到InCallActivity(通话界面)的onResume方法中,调用响铃的方法。
在InCallPresenter.java中,进行以下修改:
a.增加以下引用
import android.os.PowerManager;// Add For synchronize ringer and UI
b. 增加成员
private PowerManager pm = null;
private boolean isInCallActivityStop = false;
c. 增加方法 playIncomingCallRingtone(android.telecom.Call call)
/**
* Add For synchronize ringer and UI
*
* @param call
*/
public void playIncomingCallRingtone(android.telecom.Call call){
Log.i(this, "playIncomingCallRingtone()");
TelecomAdapter.getInstance().playIncomingCallRingtone(call);
}
d.增加getPowerManager方法
public PowerManager getPowerManager(){
if(pm == null){
pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
}
return pm;
}
e. 修改onIncomingCall(Call call)方法
public void onIncomingCall(Call call) {
Log.i(this, " onIncomingCall set isInCallActivityStop = false ");
isInCallActivityStop = false;
InCallState newState = startOrFinishUi(InCallState.INCOMING);
InCallState oldState = mInCallState
Log.i(this, "Phone switching state: " + oldState + " -> " + newState);
mInCallState = newState;
//begin Add For synchronize ringer and UI
Log.d(this, "onIncomingCall the screen is on ? ----- " + getPowerManager().isScreenOn());
if(getPowerManager().isScreenOn()){
Log.d(this, "onIncomingCall the screen is on!");
playIncomingCallRingtone(call.getTelecommCall());
}
//end Add For synchronize ringer and UI
for (IncomingCallListener listener : mIncomingCallListeners) {
listener.onIncomingCall(oldState, mInCallState, call);
}
}
f.
public void setInCallActivityStop (boolean isStop ){
Log.d(this, " setInCallActivityStop : " + isStop);
isInCallActivityStop = isStop;
}
g.
public boolean getInCallActivityStop ( ){
Log.d(this, " getInCallActivityStop: " + isInCallActivityStop);
return: isInCallActivityStop;
}
2.TelecomAdapter.java中增加方法playIncomingCallRingtone(android.telecom.Call call)
//Add For synchronize ringer and UI
void playIncomingCallRingtone(android.telecom.Call call) {
if (mPhone != null) {
Log.d(this, "playIncomingCallRingtone() Call:" + call);
if (call != null) {
call.playIncomingCallRingtone();
} else {
Log.e(this, "error playIncomingCallRingtone, call is null");
}
} else {
Log.e(this, "error playIncomingCallRingtone, mPhone is null");
}
}
3.Call.java(frameworks\base\telecomm\java\android\telecom)增加方法playIncomingCallRingtone():
//Add For synchronize ringer and UI
public void playIncomingCallRingtone() {
mInCallAdapter.playIncomingCallRingtone();
}
4.InCallAdapter.java(frameworks\base\telecomm\java\android\telecom)增加方法playIncomingCallRingtone():
/**
* Add For synchronize ringer and UI
*
*/
public void playIncomingCallRingtone() {
try {
mAdapter.playIncomingCallRingtone();
} catch (RemoteException e) {
}
}
5.IInCallAdapter.aidl(frameworks\base\telecomm\java\com\android\internal\telecom)文件中增加接口:void playIncomingCallRingtone();
6.InCallAdapter.java(packages\services\telecomm\src\com\android\server\telecom)
1> 增加静态成员:
//Add For synchronize ringer and UI
private static final int MSG_PLAY_INCOMING_RINGTONE = 1008;
2> InCallAdapterHandler的handleMessage()方法的最后添加:
case MSG_PLAY_INCOMING_RINGTONE:
mCallsManager.playIncomingCallRingtone();
break;
3> 添加成员方法:
@Override
public void playIncomingCallRingtone() {
mHandler.obtainMessage(MSG_PLAY_INCOMING_RINGTONE).sendToTarget();
}
7.CallsManager.java 中增加方法playIncomingCallRingtone()
//Add For synchronize ringer and UI
public void playIncomingCallRingtone(){
Log.v(this, "playIncomingCallRingtone()");
// check whether exist RINGING call.
for(Call call : mCalls) {
if(call.getState() == CallState.RINGING) {
mRinger.startRingingOrCallWaiting();//修改该方法为Public
break;
}
}
}
8.Ringer.java(packages\services\telecomm\src\com\android\server\telecom)中修改onForegroundCallChanged()方法如下:
@Override
public void onForegroundCallChanged(Call oldForegroundCall, Call newForegroundCall) {
if (mRingingCalls.contains(oldForegroundCall) ||
mRingingCalls.contains(newForegroundCall)) {
// Add For synchronize ringer and UI
Log.v(this, "synchronize onForegroundCallChanged() ");
//End
//Original code
//updateRinging();
}
}
9.InCallactivity.java
a. 增加以下引用
import android.os.PowerManager;// Add For synchronize ringer and UI
b.
protected void onCreate(Bundle icicle) {
Log.d(this, "onCreate()... this = " + this);
super.onCreate(icicle);
......
//begin Add For synchronize ringer and UI
Log.d(this, "AAAscreen is on ? ----- " +InCallPresenter.getInstance().getPowerManager().isScreenOn());
//end Add For synchronize ringer and UI
Log.d(this, "onCreate(): exit");
}
c.
protected void onResume() {
......
InCallPresenter.getInstance().lightOnScreenForSmartBook();
//begin Add For synchronize ringer and UI
final PowerManager pm = InCallPresenter.getInstance().getPowerManager();
final Call call = CallList.getInstance().getIncomingCall();
Log.d(this, "onResum:call: " + call);
if(call != null){
boolean isInCallActivityStop = InCallPresenter.getInstance().getInCallActivityStop();
Log.d(this, "BBBscreen is on ? ----- " + pm.isScreenOn());
Log.d(this, "BBBscreen call.getState(): " + call.getState() + " isInCallActivityStop: " + isInCallActivityStop);
if((call.getState() == Call.State.CALL_WAITING)
||((call.getState() == Call.State.INCOMING)&&(pm.isScreenOn() && isInCallActivityStop))){
InCallPresenter.getInstance().playIncomingCallRingtone(call.getTelecommCall());
InCallPresenter.getInstance().setInCallActivityStop(false);
}
}
//end Add For synchronize ringer and UI
}
d.
protected void onStop() {
Log.d(this, "onStop()...");
……………
super.onStop();
InCallPresenter.getInstance().setInCallActivityStop(true);
}