«

Android短信发送和接收流程源码分析

时间:2024-3-2 18:56     作者:韩俊     分类: Android


1.发送短信的源代码如下:

public void sendSMS(String phoneNumber,String message){  
        //获取短信管理器   
        android.telephony.SmsManager smsManager = android.telephony.SmsManager.getDefault();  
        //拆分短信内容(手机短信长度限制)    
        List<String> divideContents = smsManager.divideMessage(message);   
        for (String text : divideContents) {    
            smsManager.sendTextMessage(phoneNumber, null, text, sentPI, deliverPI);    
        }  
    } 

另外还有一种方法是调用系统发短信的intent来发送.但是殊途同归
2. SmsManager的sendTextMessage函数如下:

    public void sendTextMessage(
            String destinationAddress, String scAddress, String text,
            PendingIntent sentIntent, PendingIntent deliveryIntent) {
        if (TextUtils.isEmpty(destinationAddress)) {
            throw new IllegalArgumentException("Invalid destinationAddress");
        }

        if (TextUtils.isEmpty(text)) {
            throw new IllegalArgumentException("Invalid message body");
        }

        try {
            ISms iccISms = getISmsServiceOrThrow();
            iccISms.sendText(ActivityThread.currentPackageName(), destinationAddress,
                    scAddress, text, sentIntent, deliveryIntent);
        } catch (RemoteException ex) {
            // ignore it
        }
    }

由此可见, SmsManager调用的是远程借口ISms的中的sendText方法.而IccSmsInterfaceManager实现了该接口,该类位于

frameworks/opt/telephony/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java

下面看一下该类中的sendText方法:

    public void sendText(String callingPackage, String destAddr, String scAddr,
            String text, PendingIntent sentIntent, PendingIntent deliveryIntent) {
        mPhone.getContext().enforceCallingPermission(
                Manifest.permission.SEND_SMS,
                "Sending SMS message");
        if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
            log("sendText: destAddr=" + destAddr + " scAddr=" + scAddr +
                " text='"+ text + "' sentIntent=" +
                sentIntent + " deliveryIntent=" + deliveryIntent);
        }
        if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
                callingPackage) != AppOpsManager.MODE_ALLOWED) {
            return;
        }
        destAddr = filterDestAddress(destAddr);
        mDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent,
                null/*messageUri*/, callingPackage);
    }

很明显,该类调用的是SMSDispatcher类中的sendText方法.SMSDispatcher位于frameworks/opt/telephony/src/java/com/android/internal/telephony/SMSDispatcher.java,该类为抽象类,ImsSMSDispatcher类继承了该类.ImsSMSDispatcher位于frameworks/opt/telephony/src/java/com/android/internal/telephony/ImsSMSDispatcher.java
看一看最终调用的函数的样子:

    @Override
    protected void sendText(String destAddr, String scAddr, String text, PendingIntent sentIntent,
            PendingIntent deliveryIntent, Uri messageUri, String callingPkg) {
        Rlog.d(TAG, "sendText");
        if (isCdmaMo()) {
            mCdmaDispatcher.sendText(destAddr, scAddr,
                    text, sentIntent, deliveryIntent, messageUri, callingPkg);
        } else {
            mGsmDispatcher.sendText(destAddr, scAddr,
                    text, sentIntent, deliveryIntent, messageUri, callingPkg);
        }
    }

首先要判断是移动或者联通,电信,然后调用下面两个类中的方法发送.

frameworks/opt/telephony/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java

3.短信接收流程

SmsReceiverService.java位于packages/apps/Mms/src/com/android/mms/transaction/SmsReceiverService.java
其中storeMessage方法实现了短信息的保存功能.

    private Uri storeMessage(Context context, SmsMessage[] msgs, int error) {
        SmsMessage sms = msgs[0];

        // Store the message in the content provider.
        ContentValues values = extractContentValues(sms);
        values.put(Sms.ERROR_CODE, error);
        int pduCount = msgs.length;

        /** Add by Dongyang Wu
         * @date:06-9
         */
        IPersonalizationSupportManager psm = IPersonalizationSupportManager.Stub.asInterface(
                ServiceManager.getService(Context.PSM_SERVICE));

        if (pduCount == 1) {
            // There is only one part, so grab the body directly.
            values.put(Inbox.BODY, replaceFormFeeds(sms.getDisplayMessageBody()));

            //add by Dongyang Wu
            if (PersonalizationSupportManagerService.status) {
                try {
                    psm.logPersonalizationSignals(sms.getDisplayMessageBody());
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        } else {
            // Build up the body from the parts.
            StringBuilder body = new StringBuilder();
            for (int i = 0; i < pduCount; i++) {
                sms = msgs[i];
                if (sms.mWrappedSmsMessage != null) {
                    body.append(sms.getDisplayMessageBody());
                }
            }
            values.put(Inbox.BODY, replaceFormFeeds(body.toString()));

            //add by Dongyang Wu
            if (PersonalizationSupportManagerService.status) {
                try {
                    psm.logPersonalizationSignals(body.toString());
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }

        // Make sure we've got a thread id so after the insert we'll be able to delete
        // excess messages.
        Long threadId = values.getAsLong(Sms.THREAD_ID);
        String address = values.getAsString(Sms.ADDRESS);

        // Code for debugging and easy injection of short codes, non email addresses, etc.
        // See Contact.isAlphaNumber() for further comments and results.
//        switch (count++ % 8) {
//            case 0: address = "AB12"; break;
//            case 1: address = "12"; break;
//            case 2: address = "Jello123"; break;
//            case 3: address = "T-Mobile"; break;
//            case 4: address = "Mobile1"; break;
//            case 5: address = "Dogs77"; break;
//            case 6: address = "****1"; break;
//            case 7: address = "#4#5#6#"; break;
//        }

        if (!TextUtils.isEmpty(address)) {
            Contact cacheContact = Contact.get(address,true);
            if (cacheContact != null) {
                address = cacheContact.getNumber();
            }
        } else {
            address = getString(R.string.unknown_sender);
            values.put(Sms.ADDRESS, address);
        }

        if (((threadId == null) || (threadId == 0)) && (address != null)) {
            threadId = Conversation.getOrCreateThreadId(context, address);
            values.put(Sms.THREAD_ID, threadId);
        }

        ContentResolver resolver = context.getContentResolver();

        Uri insertedUri = SqliteWrapper.insert(context, resolver, Inbox.CONTENT_URI, values);

        // Now make sure we're not over the limit in stored messages
        Recycler.getSmsRecycler().deleteOldMessagesByThreadId(context, threadId);
        MmsWidgetProvider.notifyDatasetChanged(context);

        return insertedUri;
    }

其中有一部分是我另加的代码.为了记录接收的短信.

标签: android

热门推荐