无论从拨号盘输入号码、通话记录、联系人拨打电话等,都会进入OutgoingCallBroadcaster类中。该类继承Activity,理所当然开始进入onCreate()中,让我们在onCreate()做什么操作:

1、onCreate():

protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        //获取传入的intent意图
        Intent intent = getIntent();

        if (icicle != null) {
           return;
        }
        processIntent(intent);
}

2、获取到intent后,通过intent获取action和电话号码

private void processIntent(Intent intent) {

      String action = intent.getAction();
      String number = PhoneNumberUtils.getNumberFromIntent(intent, this);

       //在此对号码进行啦一个转换操作:
        //比如输入1-800-GOOG-411 实际为1-800-4664-411
       if (number != null) {
            if (!PhoneNumberUtils.isUriNumber(number)) {
                number = PhoneNumberUtils.convertKeypadLettersToDigits(number);
                number = PhoneNumberUtils.stripSeparators(number);
            }
        } else {
            Log.w(TAG, "The number obtained from Intent is null.");
        }    

}

3、获取到号码后,判断号码是否为紧急号码

final boolean isPotentialEmergencyNumber =
                (number != null) && PhoneNumberUtils.isPotentialLocalEmergencyNumber(number, this);

//在此对紧急号码与非紧急号码设置不同action
if (isPotentialEmergencyNumber) {
     Log.i(TAG, "ACTION_CALL_PRIVILEGED is used while the number is a potential"
                        + " emergency number. Use ACTION_CALL_EMERGENCY as an action instead.");
     action = Intent.ACTION_CALL_EMERGENCY;
} else {
     action = Intent.ACTION_CALL;
}
if (DBG) Log.v(TAG, " - updating action from CALL_PRIVILEGED to " + action);
    intent.setAction(action);
}

//如果为紧急号码则直接进入InCallScreen界面
 if (callNow) { 
   Log.i(TAG, "onCreate(): callNow case! Calling placeCall(): " + intent);
   PhoneGlobals.getInstance().callController.placeCall(intent);
}

 

4、如果不是紧急号码,则通过另一种方式开启InCallScreen():

//发送广播
Intent broadcastIntent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);
        if (number != null) {
            broadcastIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);
        }
        PhoneUtils.checkAndCopyPhoneProviderExtras(intent, broadcastIntent);
        broadcastIntent.putExtra(EXTRA_ALREADY_CALLED, callNow);
        broadcastIntent.putExtra(EXTRA_ORIGINAL_URI, uri.toString());
        // Need to raise foreground in-call UI as soon as possible while allowing 3rd party app
        // to intercept the outgoing call.
        broadcastIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        if (DBG) Log.v(TAG, " - Broadcasting intent: " + broadcastIntent + ".");

        // Set a timer so that we can prepare for unexpected delay introduced by the broadcast.
        // If it takes too much time, the timer will show "waiting" spinner.
        // This message will be removed when OutgoingCallReceiver#onReceive() is called before the
        // timeout.
        mHandler.sendEmptyMessageDelayed(EVENT_OUTGOING_CALL_TIMEOUT,
                OUTGOING_CALL_TIMEOUT_THRESHOLD);
        sendOrderedBroadcastAsUser(broadcastIntent, UserHandle.OWNER,
                PERMISSION, new OutgoingCallReceiver(),
                null,  // scheduler
                Activity.RESULT_OK,  // initialCode
                number,  // initialData: initial value for the result data
                null);  // initialExtras


//接收广播,执行onReceive():
 alreadyCalled = intent.getBooleanExtra( OutgoingCallBroadcaster.EXTRA_ALREADY_CALLED, false);

//如果已经存在InCallScreen,直接finish
 if (alreadyCalled) {
           if (DBG) Log.v(TAG, "CALL already placed -- returning.");
           return;
 }

//获取到number和uri
String number = getResultData();
String originalUri = intent.getStringExtra( OutgoingCallBroadcaster.EXTRA_ORIGINAL_URI);

//开启sip网络通话,在2.2版本好像是直接开启InCallScreen
startSipCallOptionHandler(context, intent, uri, number);

5、通过代码可知,OutgoingCallBroadcaster只做了对number及uri数据传递和紧急号码判断。既然每个去电都必须通过此类,我们可以通过它对同时拨打号码数量的限制。google只允许同时拨打2个电话,大家可以试试,我们先看看google是如何限制的:

CallManager (frameworks)----- canDial():通过修改此类限制----比如三方通话,同时我们也可以在OutgoingCallBroadcaster中onCreate()中拦截。

//判断是否可以拨打
private boolean canDial(Phone phone) {
      
        int serviceState = phone.getServiceState().getState();      
        boolean hasRingingCall = hasActiveRingingCall();//是否响铃
         boolean hasActiveCall = hasActiveFgCall();//是否活动在前台
         boolean hasHoldingCall = hasActiveBgCall();//是否后台
         boolean allLinesTaken = hasActiveCall && hasHoldingCall;
        Call.State fgCallState = getActiveFgCallState();
        boolean result = (serviceState != ServiceState.STATE_POWER_OFF
                                     && !hasRingingCall
                                     && !allLinesTaken
                                     && ((fgCallState == Call.State.ACTIVE)
                                     || (fgCallState == Call.State.IDLE)
                                     || (fgCallState == Call.State.DISCONNECTED)));
        return result;   
}
posted on 2013-09-05 22:46  羞涩的流氓  阅读(1886)  评论(0编辑  收藏  举报