Android呼出电话流程(原)

        我们从按下拨号开始分析呼出电话的流程。此流程从拨号盘分析到RIL层。

一、应用层的流程


1.1、拨号盘初步处理

    @DialpadFragment.java
    public void dialButtonPressed() {
        //得到号码
        final String number = mDigits.getText().toString();
        //得到拨号的Intent
        final Intent intent = ContactsUtils.getCallIntent(number,
                (getActivity() instanceof DialtactsActivity ?
                        ((DialtactsActivity)getActivity()).getCallOrigin() : null));
        startActivity(intent);
        mClearDigitsOnStop = true;
        getActivity().finish();
    }
        来看上面得到Intent的过程:
    @ContactsUtils.java
    public static Intent getCallIntent(String number, String callOrigin) {
        用号码构建一个类似tel:10086的Uri
        return getCallIntent(getCallUri(number), callOrigin);
    }
    public static Intent getCallIntent(Uri uri, String callOrigin) {
        final Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED, uri);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (callOrigin != null) {
            intent.putExtra(DialtactsActivity.EXTRA_CALL_ORIGIN, callOrigin);
        }
        return intent;
    }
        这个过程可以看出,发出的Intent由一下几个结构组成:
        1、Action为:ACTION_CALL_PRIVILEGED,(android.intent.action.CALL_PRIVILEGED);
        2、Flag为:FLAG_ACTIVITY_NEW_TASK;
        3、号码Uri为:tel:10086

        然后经过startActivity发送出去。那么是那个Activity接受的呢?


1.2、号码初级处理阶段

        这个过程主要针对紧急呼叫处理(OutgoingCallBroadcaster.java)。

        在Phone模块的AndroidManifest.xml文件中有如下描述:
    <activity-alias android:name="PrivilegedOutgoingCallBroadcaster"
            android:targetActivity="OutgoingCallBroadcaster"
            android:screenOrientation="nosensor"
            android:permission="android.permission.CALL_PRIVILEGED">
        <intent-filter>
            <action android:name="android.intent.action.CALL_PRIVILEGED" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="tel" />
        </intent-filter>
    </activity-alias>
        activity-alias说明这个节点描述的Activity是另一个Activity的别名,也就是说,当前的PrivilegedOutgoingCallBroadcaster是指向OutgoingCallBroadcaster的。
    @OutgoingCallBroadcaster.java
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.outgoing_call_broadcaster);
        mWaitingSpinner = (ProgressBar) findViewById(R.id.spinner);

        Intent intent = getIntent();
        processIntent(intent);
    }
        继续往下看:
    private void processIntent(Intent intent) {
        final Configuration configuration = getResources().getConfiguration();

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

        //得到当前的号码
        if (number != null) {
            if (!PhoneNumberUtils.isUriNumber(number)) {
                number = PhoneNumberUtils.convertKeypadLettersToDigits(number);
                number = PhoneNumberUtils.stripSeparators(number);
            }
        } else {
        }

        //判断是否是紧急拨号
        final boolean isExactEmergencyNumber =
                (number != null) && PhoneNumberUtils.isLocalEmergencyNumber(number, this);
        final boolean isPotentialEmergencyNumber =
                (number != null) && PhoneNumberUtils.isPotentialLocalEmergencyNumber(number, this);

        if (Intent.ACTION_CALL_PRIVILEGED.equals(action)) {
            if (isPotentialEmergencyNumber) {
                //紧急拨号的action
                action = Intent.ACTION_CALL_EMERGENCY;
            } else {
                //非紧急拨号的action
                action = Intent.ACTION_CALL;
            }
            //重新设置Action,当前不是紧急呼叫,因此Action改为ACTION_CALL
            intent.setAction(action);
        }

        if (Intent.ACTION_CALL.equals(action)) {
            if (isPotentialEmergencyNumber) {
                //判断不成立
            }
            //当前的callNow为false
            callNow = false;
        } else if (Intent.ACTION_CALL_EMERGENCY.equals(action)) {
            //紧急呼叫的处理
        } else {
        }

        Uri uri = intent.getData();
        String scheme = uri.getScheme();
        if (Constants.SCHEME_SIP.equals(scheme) || PhoneNumberUtils.isUriNumber(number)) {
            //互联网通话的处理
        }

        //重新构建Intent
        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());
        broadcastIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);

        //添加一个2秒的定时器,2秒内Intent没有收到的话,就显示一个进度条
        mHandler.sendEmptyMessageDelayed(EVENT_OUTGOING_CALL_TIMEOUT,
                OUTGOING_CALL_TIMEOUT_THRESHOLD);

        //发送广播,而且指明了接收者是OutgoingCallReceiver
        sendOrderedBroadcastAsUser(broadcastIntent, UserHandle.OWNER,
                PERMISSION, new OutgoingCallReceiver(),
                null,
                Activity.RESULT_OK,
                number,
                null);
    }
        这个过程其实就是对原始的Intent进行解析,对是否紧急呼叫进行不同的处理,对于正常的呼叫,需要重新构建Intent并发送出去。新的Intent构成:
            Intent:ACTION_NEW_OUTGOING_CALL;
            EXTRA_ALREADY_CALLED:false;
            EXTRA_ORIGINAL_URI:号码的Uri;
            发送目标:OutgoingCallReceiver;
        这里所谓的目标 OutgoingCallReceiver其实就是OutgoingCallBroadcaster.java中的内部类,我们直接来看他的接收地方:
    public void onReceive(Context context, Intent intent) {
        //去掉3妙的定时器
        mHandler.removeMessages(EVENT_OUTGOING_CALL_TIMEOUT);
        doReceive(context, intent);
        finish();
    }
    public void doReceive(Context context, Intent intent) {
        //这里的得到的是false
        alreadyCalled = intent.getBooleanE
  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值