Android 正常拨号去电流程

 /**
* @author 江忠锦

*    http://blog.csdn.net/u012913972

*   我的新浪博客: 奋进的江

*/

在DialpadFragment 中执行dialButtonPressed()方法:

    /**
     * Called by the containing Activity to tell this Fragment that the dial button has been
     * pressed.
     */
    public void dialButtonPressed() {
        mHaptic.vibrate();
        handleDialButtonPressed();
    }


震动一下后,开始执行handleDialButtonPressed();

private void handleDialButtonPressed() {
        if (isDigitsEmpty() && (mRecipients == null || !mRecipients.isShown())) {
            // No number entered.
            handleDialButtonClickWithEmptyDigits();
        } else {
            boolean isDigitsShown = mDigits.isShown();
            final String number = isDigitsShown ? mDigits.getText().toString() :
                    mRecipients.getText().toString().trim();
            if (isDigitsShown && isDigitsEmpty()) {
                handleDialButtonClickWithEmptyDigits();
            } else if (mAddParticipant && isDigitsEmpty() && mRecipients.isShown()
                    && isRecipientEmpty()) {
                // mRecipients must be empty
                // TODO add support for conference URI in last number dialed
                // use ErrorDialogFragment instead? also see
                // android.app.AlertDialog
                android.widget.Toast.makeText(getActivity(),
                        "Error: Cannot dial.  Please provide conference recipients.",
                        android.widget.Toast.LENGTH_SHORT).show();
            } else {
                // "persist.radio.otaspdial" is a temporary hack needed for one carrier's automated
                // test equipment.
                // TODO: clean it up.
                if (number != null
                        && !TextUtils.isEmpty(mProhibitedPhoneNumberRegexp)
                        && number.matches(mProhibitedPhoneNumberRegexp)) {
                    Log.i(TAG, "The phone number is prohibited explicitly by a rule.");
                    if (getActivity() != null) {
                        DialogFragment dialogFragment = ErrorDialogFragment.newInstance(
                                R.string.dialog_phone_call_prohibited_message);
                        dialogFragment.show(getFragmentManager(), "phone_prohibited_dialog");
                    }

                    // Clear the digits just in case.
                    clearDialpad();
                } else {
                    final Intent intent = CallUtil.getCallIntent(number,
                            (getActivity() instanceof DialtactsActivity ?
                                    ((DialtactsActivity) getActivity()).getCallOrigin() : null));
                    if (!isDigitsShown) {
                        // must be dial conference add extra
                        intent.putExtra(TelephonyProperties.EXTRA_DIAL_CONFERENCE_URI, true);
                    }
                    intent.putExtra(ADD_PARTICIPANT_KEY, mAddParticipant);
                    DialerUtils.startActivityWithErrorToast(getActivity(), intent);
                    hideAndClearDialpad(false);
                }
            }
        }
    }

上面大部分是处理一些特殊的情况,比如在未按号码就按拨号,或则一些特殊的号码的情况,此刻我只关注最一般的情况就是最后一个else的情况:

 else {
                    final Intent intent = CallUtil.getCallIntent(number,
                            (getActivity() instanceof DialtactsActivity ?
                                    ((DialtactsActivity) getActivity()).getCallOrigin() : null));
                    if (!isDigitsShown) {
                        // must be dial conference add extra
                        intent.putExtra(TelephonyProperties.EXTRA_DIAL_CONFERENCE_URI, true);
                    }
                    intent.putExtra(ADD_PARTICIPANT_KEY, mAddParticipant);
                    DialerUtils.startActivityWithErrorToast(getActivity(), intent);
                    hideAndClearDialpad(false);
                }


在此启动了一个activity,它去了哪里呢?

现看CallUtil  

import com.android.contacts.common.CallUtil;

这个类来自ContactsCommon,在这个类的getCallIntent方法

    /**
     * A variant of {@link #getCallIntent(android.net.Uri)} but also accept a call
     * origin and {@code Account} and {@code VideoCallProfile} state.
     * For more information about call origin, see comments in Phone package (PhoneApp).
     */
    public static Intent getCallIntent(
            Uri uri, String callOrigin, PhoneAccountHandle accountHandle, int videoState) {
        final Intent intent = new Intent(Intent.ACTION_CALL, uri);
        intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, videoState);
        if (callOrigin != null) {
            intent.putExtra(PhoneConstants.EXTRA_CALL_ORIGIN, callOrigin);
        }
        if (accountHandle != null) {
            intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, accountHandle);
        }

        return intent;
    }


获得的是一个ACTION_CALL的intent,而与之对应的Activity是Telephony中的OutgoingCallBroadcaster

AndroidManifest.xml中

        <activity android:name="OutgoingCallBroadcaster"
                android:enabled="false"
                android:theme="@style/OutgoingCallBroadcasterTheme"
                android:permission="android.permission.CALL_PHONE"
                android:screenOrientation="nosensor"
                android:configChanges="orientation|screenSize|keyboardHidden"
                android:excludeFromRecents="true">
            <!-- CALL action intent filters, for the various ways
                 of initiating an outgoing call. -->
            <intent-filter>
                <action android:name="android.intent.action.CALL" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="tel" />
            </intent-filter>
            <intent-filter android:icon="@drawable/ic_launcher_sip_call">
                <action android:name="android.intent.action.CALL" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="sip" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.CALL" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="voicemail" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.CALL" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="vnd.android.cursor.item/phone" />
                <data android:mimeType="vnd.android.cursor.item/phone_v2" />
                <data android:mimeType="vnd.android.cursor.item/person" />
            </intent-filter>
        </activity>


OutgoingCallBroadcaster继承与Activity 是一个没有界面的Activity,起到路由过滤的作用:

在其onCreate中最重要的工作就是执行processIntent(intent);

在此方法中会判断去电是个什么类型,是紧急拨号还是正常去电还是Sip去电等,其中控制正常拨号的流程是通过发送广播出去

        Intent broadcastIntent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);
        if (number != null) {
            broadcastIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);
        }
        CallGatewayManager.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


接收该广播的是它的内部类 OutgoingCallReceiver

发布了7 篇原创文章 · 获赞 0 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/u012913972/article/details/45675127