Android平台 短信接送流程剖析(含编码)
//框架层分析: //GsmSMSDispatcher.java /** {@inheritDoc} */ @Override protected int dispatchMessage(SmsMessageBase smsb) { //该函数的返回值会在handleMessage里进行判断是否为Activity.RESULT_OK。要注意该返回值不为Activity.RESULT_OK的情况。 // If sms is null, means there was a parsing error. if (smsb == null) { return Intents.RESULT_SMS_GENERIC_ERROR; } SmsMessage sms = (SmsMessage) smsb; boolean handled = false; if (sms.isTypeZero()) { //0x0100 0000 Short Message Type 0 The MS does not indicate the receipt of the type 0 short message to the user,and the message is not stored in the(U)SIM or ME. // As per 3GPP TS 23.040 9.2.3.9, Type Zero messages should not be // Displayed/Stored/Notified. They should only be acknowledged. Log.d(TAG, "Received short message type 0, Don't display or store it. Send Ack"); return Intents.RESULT_SMS_HANDLED; } if (mSmsReceiveDisabled) { // Device doesn't support SMS service, Log.d(TAG, "Received short message on device which doesn't support " + "SMS service. Ignored."); return Intents.RESULT_SMS_HANDLED; } // Special case the message waiting indicator messages if (sms.isMWISetMessage()) { updateMessageWaitingIndicator(true); handled = sms.isMwiDontStore(); if (Config.LOGD) { Log.d(TAG, "Received voice mail indicator set SMS shouldStore=" + !handled); } } else if (sms.isMWIClearMessage()) { updateMessageWaitingIndicator(false); handled = sms.isMwiDontStore(); if (Config.LOGD) { Log.d(TAG, "Received voice mail indicator clear SMS shouldStore=" + !handled); } } if (handled) { return Intents.RESULT_SMS_HANDLED; } if (!mStorageAvailable && (sms.getMessageClass() != MessageClass.CLASS_0)) { // It's a storable message and there's no storage available. Bail. // (See TS 23.038 for a description of class 0 messages.) return Intents.RESULT_SMS_OUT_OF_MEMORY; } SmsHeader smsHeader = sms.getUserDataHeader(); // See if message is partial or port addressed. if ((smsHeader == null) || (smsHeader.concatRef == null)) { // Message is not partial (not part of concatenated sequence). byte[][] pdus = new byte[1][]; pdus[0] = sms.getPdu(); if (smsHeader != null && smsHeader.portAddrs != null) { if (smsHeader.portAddrs.destPort == SmsHeader.PORT_WAP_PUSH) { return mWapPush.dispatchWapPdu(sms.getUserData()); } else { // The message was sent to a port, so concoct a URI for it. dispatchPortAddressedPdus(pdus, smsHeader.portAddrs.destPort); } } else { // Normal short and non-port-addressed message, dispatch it. dispatchPdus(pdus); //注意该处 } return Activity.RESULT_OK; } else { // Process the message part. return processMessagePart(sms, smsHeader.concatRef, smsHeader.portAddrs); } } //SMSDispatcher.java protected void dispatchPdus(byte[][] pdus) { Intent intent = new Intent(Intents.SMS_RECEIVED_ACTION); intent.putExtra("pdus", pdus); //pdu数据 intent.putExtra("encoding", getEncoding()); dispatch(intent, "android.permission.RECEIVE_SMS"); } //应用层分析: <!-- Require sender permissions to prevent SMS spoofing --> <receiver android:name=".transaction.PrivilegedSmsReceiver" android:permission="android.permission.BROADCAST_SMS"> <intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver> //PrivilegedSmsReceiver类从SmsReceiver派生。在SmsReceiver(extends BroadcastReceiver)类中的onReceiveWithPrivilege 会将服务SmsReceiverService启动,然后在handleSmsReceived函数中对接收的消息进行处理。 //SmsReceiverService.java //入口 private void handleSmsReceived(Intent intent, int error) { SmsMessage[] msgs = Intents.getMessagesFromIntent(intent); //解析intent,获取SmsMessage转①分析 Uri messageUri = insertMessage(this, msgs, error); //插入数据 转②分析 if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) { SmsMessage sms = msgs[0]; Log.v(TAG, "handleSmsReceived" + (sms.isReplace() ? "(replace)" : "") + " messageUri: " + messageUri + ", address: " + sms.getOriginatingAddress() + ", body: " + sms.getMessageBody()); } if (messageUri != null) { // Called off of the UI thread so ok to block. MessagingNotification.blockingUpdateNewMessageIndicator(this, true, false); } } //①分析 //Telephony.java public static final SmsMessage[] getMessagesFromIntent(Intent intent) { Object[] messages = (Object[]) intent.getSerializableExtra("pdus"); byte[][] pduObjs = new byte[messages.length][]; int encoding = intent.getIntExtra("encoding", -1); for (int i = 0; i < messages.length; i++) { pduObjs[i] = (byte[]) messages[i]; } byte[][] pdus = new byte[pduObjs.length][]; int pduCount = pdus.length; SmsMessage[] msgs = new SmsMessage[pduCount]; for (int i = 0; i < pduCount; i++) { pdus[i] = pduObjs[i]; if (-1 != encoding) { msgs[i] = SmsMessage.createFromPdu(pdus[i], encoding); } else { msgs[i] = SmsMessage.createFromPdu(pdus[i]); //创建PDU } } return msgs; } } //②分析: private Uri insertMessage(Context context, SmsMessage[] msgs, int error) { // Build the helper classes to parse the messages. SmsMessage sms = msgs[0]; if (sms.getMessageClass() == SmsMessage.MessageClass.CLASS_0) { displayClassZeroMessage(context, sms); //直接显示 return null; } else if (sms.isReplace()) { return replaceMessage(context, msgs, error); } else { return storeMessage(context, msgs, error);//存储短信 转③分析 } } //③分析 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; if (pduCount == 1) { // There is only one part, so grab the body directly. values.put(Inbox.BODY, replaceFormFeeds(sms.getDisplayMessageBody())); } else { // Build up the body from the parts. StringBuilder body = new StringBuilder(); for (int i = 0; i < pduCount; i++) { sms = msgs[i]; body.append(sms.getDisplayMessageBody()); } values.put(Inbox.BODY, replaceFormFeeds(body.toString())); } // 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); //注意对地址的处理 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 = Threads.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(getApplicationContext(), threadId); return insertedUri; }
发表评论
文章已被作者锁定,不允许评论。
-
资料上传备份
2012-07-02 07:28 0对付对付对付对付 -
Android-sharedUserId数据权限
2012-05-02 10:16 1404Android-sharedUserId数据权限 An ... -
Android Service学习之本地服务
2012-04-18 10:28 794转: Android Service学习之本地服务 htt ... -
match_parent和fill_parent的区别 .
2012-02-18 11:49 1777match_parent和fill_parent的区别 有 ... -
Android中SQLiteOpenHelper类的onUpgrade方法的作用
2012-02-09 11:50 4557Android中SQLiteOpenHelper类的onUpg ... -
Android启动各种系统服务线程
2012-02-09 10:59 1892Android启动各种系统服务 ... -
android
2012-02-08 09:22 0Android数据库内容变化的监听 首先介绍内容监 ... -
在线升级Android应用程序的思路
2012-02-07 11:34 816在线升级Android应用程序的思路 http://www. ... -
Android数据库内容变化的监听
2012-02-07 11:31 5985Android数据库内容变化的监听 首先介绍内容监 ... -
android中的数据库操作
2012-02-07 10:50 1406android中的数据库操作 ... -
SQLiteOpenHelper类与自动升级数据库
2012-02-07 10:31 2233SQLiteOpenHelper类与自动升级数据库 S ... -
SQLite外键的实现
2012-02-07 10:30 1652SQLite外键的实现 SQLite现在的版本还不支持 ... -
Android到处都在使用的回调分析
2011-12-21 15:53 3495Android到处都在使用的回调分析 ... -
android中LayoutInflater的使用
2011-12-21 11:35 1896android中LayoutInflater的使用 ... -
SIM卡满处理流程分析
2011-12-19 15:15 1838SIM卡满处理流程分析 //框架层分析 // SMSD ... -
短信发送状态报告流程分析
2011-12-19 15:07 2347短信发送状态报告流程分析 //应用层分析: //Sms ... -
修改语言环境方法
2011-12-16 15:20 990修改语言环境方法 private void se ... -
Android平台 短信发送流程剖析(含编码)
2011-12-12 17:12 4256Android平台 短信发送流程剖析(含编码) 本文对A ... -
Android 应用程序签名
2011-11-27 11:34 1599Android 应用程序签名 转:http://www ... -
理解Android 上的安全性
2011-11-27 11:18 1418理解 Android 上的安全性 ...
相关推荐
“平安宝宝”幼儿学生接送管理系统由珠海盛远信息技术公司与多位知名幼教专家经过多年紧密合作潜心研发而成,该系统采用IC射频卡取代纸卡,利用接送机、控制主机与电脑管理软件组成一个智能接送管理系统,通过刷卡...
迪安幼儿园接送系统提供全面的儿童信息记录,幼儿毕业、升级、调班、退学等过程信息可以得到完整的记录。 提供园长查询专栏,可查询幼儿接送记录、幼儿出勤率、日出勤月出勤统计, 可查询教师刷卡记录、日出勤、月...
幼儿园安全进出接送管理系统有利于校园的安全算法分析
幼儿园接送管理系统,形象,有趣,科学,是幼儿园管理的好帮手!
烟台威尔公司幼儿接送安全智能化管理系统,是为改善幼儿园安全环境而专门研发的产品。本系统针对幼儿园日常接送人员身份确认的盲点与当前局势下各种安全管理需求而设计,融合了安全接送、人员识别、语音呼叫、教师...
加强幼儿接送安全管理是幼儿园管理的重中之重!
幼儿固定接送人登记表.docx
幼儿园人脸识别接送安全系统.pdf幼儿园人脸识别接送安全系统.pdf幼儿园人脸识别接送安全系统.pdf幼儿园人脸识别接送安全系统.pdf幼儿园人脸识别接送安全系统.pdf幼儿园人脸识别接送安全系统.pdf幼儿园人脸识别接送...
接送学生车辆安全预案精选.doc
所以app首先需要去注册一个关于接送开机启动的广播(android.intent.action.BOOT_COMPLETED);而且必须要注意的一点是:这个广播必须的静态注册的,不能是动态注册的广播(这种接受开机广播的,一定要静态注册,...
接送(教育)APP,定位,天气,学校,轨迹,家长,。。。。。非常好的一个资源
android 蓝牙4.0开发,包括了数据的发送跟接送,代码是基于网上demo改的
针对幼儿园安全设计了一种采用GPS技术进行校车定位的幼儿园接送系统,通过幼儿园出入刷卡接送(门禁)...通过采用PC-服务器-Android相结合的实验,既为幼儿园提供了安全保障,也为家长实时查看最新的信息提供了平台。
免费发送短信!不要一分钱!操作很简单!只有输入接送号码,短信文字和验证码!就可以了
论文研究-基于集划分的精确算法求解机场接送车辆调度问题.pdf, ... 最后通过一系列实例的计算分析, 验证了该算法用于求解免费接送机场服务车辆调度问题的有效性和适用性.
Flexsim机场出租车接送模型 简介: 大多数乘客下飞机后要去市区(或周边)的目的地,出租车是主要的交通工具之一。国内多数机场都是将送客(出发)与接客(到达)通道分开的。 建立模型机场出租车接送模型,解决问题
智慧方案
行业文档-设计装置-一种接送货平台的开门、抬升及稳定联合机构.zip
行业文档-设计装置-用于售货机接送货平台的辊轮滑块推力机构的导向型材.zip
管理制度-幼儿园幼儿接送规定-幼儿园接送学生管理制度.pdf