如何在无线网络接收器到 apn 的时候获取 apn 消息内容并进行跳转或做出响应处理

查看: 3773|回复: 2
android 新建一个Apn后的数据连接的调试过程
主题帖子e币
没有eoe的账号,级别还太低,出门如何吹牛逼?
才可以下载或查看,没有帐号?
当我新建了一个APN 保存信息后,系统发现APN发生了改变就会去进行数据连接. 我查看调试信息发现第一次发送 setup_data_call 请求后,底层做出了响应,数据连接成功了状态为 CONNECTED, 却出现了PREFERED APN is null, 然后又监听到了 Apn 发生了改变,所以就将状态改变为 DISCONNECTING ,接着就发送一个DEACTIVATE_DATA_CALL&&的请求要求断开数据连接,然后又发送一个 setup_data_call 去进行数据连接,第二次就连接成功了并在屏幕上显示出来了 G 标志.
其中让我非常纳闷的是: 为什么检测到两次APN 发生了改变? 当第一次连接状态已经为 CONNECTED 了却又监听到了 APN 发生了改变.
主题帖子e币
请问如何建一个APN信息,楼主能否指点一下,我建立的时候总是出错。还有就是建立好APN后,它会自动去连接网络吗?
主题帖子e币
这上面有关于配置APN 的信息
推荐阅读热门话题
624612454203019351808177914701282975903768761697688715
半小时前半小时前半小时前半小时前1&小时前1&小时前1&小时前1&小时前1&小时前1&小时前1&小时前1&小时前1&小时前1&小时前
特别关注 /4
从基础入门到熟练精通,9个阶段知识体系图指引你逐步提升~还有技术问答+讲师互动,最新实战教程每日更新!
想学Android开发,但没有Java基础?Java体系庞大,不知道从哪学起?专门针对Android开发所需的Java基础教程,学这些,就够了!
eoe联合听云年终征文送豪礼,魅蓝手机,机械键盘,Android书籍,极客学院月VIP学习权限(注册即送)……众多大奖拿到手软,抓紧来参与吧
本期eoe特邀代码家-小林跟大家一起讨论和交流Android自定义组件方面的知识
活动时间:1月26日——2月1日
Powered by
扫一扫 关注eoe官方微信58cv网址导航android&彩信接收到附件的下载原理分析
首先,了解下彩信收发的宏观步骤:
a、 终端A向彩信中心(MMSC)发送一条彩信,通过WAP网关POST到MMSC
b、 MMSC通过PushProxy网关,向SMSC(短信中心)发送PUSH消息,SMSC转发到终端B
c、 终端B通过WAP网关利用GET方法从MMSC获取一条彩信
d、 MMSC通过PushProxy网关和SNSC向终端A发送一条传送报告(delivery report)
从上面这个步骤可以看出,彩信的接收分两个步骤:
1、接收到短信。
2、分析短信然后通过http来获取彩信附件。
(续我的另一篇博客:)
因此彩信第一步跟短信的接收流程一样,在RILReceiver
接收到短信转到processUnsolicited进行处理。
GSM 方式(最近才知道短信的收发有两种,一种就是通过GSM,另一种是通过CDMA):
GSM其事件类型为
RIL_UNSOL_RESPONSE_NEW_SMS。先调用responseString从Parcel中获取数据,再使用
newFromCMT方法获取SmsMessage对象,最后调用mSMSRegistrant的notifyRegistrant方法设置消息类型
(what属性为EVENT_NEW_SMS)并转到SMSDispatcher进行处理。这个时候就会调用子类(GsmSMSDispatcher)的
dispatchMessage方法处理。
protected int dispatchMessage(SmsMessageBase smsb) {
&&& // If sms is
null, means there was a parsing error.
if (smsb == null) {
return Intents.RESULT_SMS_GENERIC_ERROR;
SmsMessage sms = (SmsMessage)
boolean handled =
if (sms.isTypeZero()) {
// As per 3GPP TS 23.040 9.2.3.9, Type Zero messages should not
// Displayed/Stored/Notified. They should only be
acknowledged.
Log.d(TAG, "Received short message type 0, Dont display or store
it. Send Ack");
return Intents.RESULT_SMS_HANDLED;
// Special case the message waiting indicator messages
if (sms.isMWISetMessage()) {
mGsmPhone.updateMessageWaitingIndicator(true);
handled = sms.isMwiDontStore();
if (Config.LOGD) {
Log.d(TAG, "Received voice mail indicator set SMS shouldStore=" +
!handled);
} else if (sms.isMWIClearMessage()) {
mGsmPhone.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)) {
// Its a storable message and theres no storage available.
// (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());
// The message was sent to a port, so concoct a URI for it.
dispatchPortAddressedPdus(pdus,
smsHeader.portAddrs.destPort);
// Normal short and non-port-addressed message, dispatch it.
dispatchPdus(pdus);
return Activity.RESULT_OK;
// Process the message part.
return processMessagePart(sms, smsHeader.concatRef,
smsHeader.portAddrs);
在这个方法里,将会判断接收到的短信是否长短信、是否彩信、是否普通短信。
首先获取SmsHeader,
如果SmsHeader或SmsHeader.concatRef均不为空,说明是长短信,则调用processMessagePart将短信分段存入
raw表,待所有分段都收到后,将其组装。然后根据端口的不同,按照彩信通知(WapPushOverSms的dispatchWapPdu方法)、指定端口的彩信(dispatchPortAddressedPdus)、长短信(dispatchPdus)进行分发处理。
继续分析彩信,如果是彩信就调用WapPushOverSms类dispatchWapPdu的方法。(该类的位置)
&&& public int
dispatchWapPdu(byte[] pdu) {
if (Config.LOGD) Log.d(LOG_TAG, "Rx: " +
IccUtils.bytesToHexString(pdu));
int index = 0;
int transactionId = pdu[index++] &
int pduType = pdu[index++] & 0xFF;
int headerLength = 0;
if ((pduType != WspTypeDecoder.PDU_TYPE_PUSH)
&&&&&&&&&&&&&&&
(pduType != WspTypeDecoder.PDU_TYPE_CONFIRMED_PUSH)) {
&&&&&&&&&&&
if (Config.LOGD) Log.w(LOG_TAG, "Received non-PUSH WAP PDU. Type =
" + pduType);
&&&&&&&&&&&
return Intents.RESULT_SMS_HANDLED;
pduDecoder = new WspTypeDecoder(pdu);
if (pduDecoder.decodeUintvarInteger(index) == false) {
&&&&&&&&&&&
if (Config.LOGD) Log.w(LOG_TAG, "Received PDU. Header Length
&&&&&&&&&&&
return Intents.RESULT_SMS_GENERIC_ERROR;
headerLength = (int)pduDecoder.getValue32();
index += pduDecoder.getDecodedDataLength();
int headerStartIndex =
if (pduDecoder.decodeContentType(index) == false) {
&&&&&&&&&&&
if (Config.LOGD) Log.w(LOG_TAG, "Received PDU. Header Content-Type
&&&&&&&&&&&
return Intents.RESULT_SMS_GENERIC_ERROR;
int binaryContentT
String mimeType = pduDecoder.getValueString();
if (mimeType == null) {
&&&&&&&&&&&
binaryContentType = (int)pduDecoder.getValue32();
&&&&&&&&&&&
// TODO we should have more generic way to map binaryContentType
code to mimeType.
&&&&&&&&&&&
switch (binaryContentType) {
&&&&&&&&&&&&&&&
case WspTypeDecoder.CONTENT_TYPE_B_DRM_RIGHTS_XML:
&&&&&&&&&&&&&&&&&&&
mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_DRM_RIGHTS_XML;
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
case WspTypeDecoder.CONTENT_TYPE_B_DRM_RIGHTS_WBXML:
&&&&&&&&&&&&&&&&&&&
mimeType =
WspTypeDecoder.CONTENT_MIME_TYPE_B_DRM_RIGHTS_WBXML;
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
case WspTypeDecoder.CONTENT_TYPE_B_PUSH_SI:
&&&&&&&&&&&&&&&&&&&
mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_SI;
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
case WspTypeDecoder.CONTENT_TYPE_B_PUSH_SL:
&&&&&&&&&&&&&&&&&&&
mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_SL;
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
case WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO:
&&&&&&&&&&&&&&&&&&&
mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_CO;
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
case WspTypeDecoder.CONTENT_TYPE_B_MMS:
&&&&&&&&&&&&&&&&&&&
mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_MMS;
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
case WspTypeDecoder.CONTENT_TYPE_B_VND_DOCOMO_PF:
&&&&&&&&&&&&&&&&&&&
mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_VND_DOCOMO_PF;
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
if (Config.LOGD) {
&&&&&&&&&&&&&&&&&&&&&&&
Log.w(LOG_TAG,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
"Received PDU. Unsupported Content-Type = " +
binaryContentType);
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
return Intents.RESULT_SMS_HANDLED;
&&&&&&&&&&&
&&&&&&&&&&&
(mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_DRM_RIGHTS_XML))
&&&&&&&&&&&&&&&
binaryContentType =
WspTypeDecoder.CONTENT_TYPE_B_DRM_RIGHTS_XML;
&&&&&&&&&&&
(mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_DRM_RIGHTS_WBXML))
&&&&&&&&&&&&&&&
binaryContentType =
WspTypeDecoder.CONTENT_TYPE_B_DRM_RIGHTS_WBXML;
&&&&&&&&&&&
(mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_SI))
&&&&&&&&&&&&&&&
binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_PUSH_SI;
&&&&&&&&&&&
(mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_SL))
&&&&&&&&&&&&&&&
binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_PUSH_SL;
&&&&&&&&&&&
(mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_CO))
&&&&&&&&&&&&&&&
binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO;
&&&&&&&&&&&
// 彩信类型 CONTENT_MIME_TYPE_B_MMS=“application/vnd.wap.mms-message”
&&&&&&&&&&
} else if (mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_MMS))
&&&&&&&&&&&&&&&
binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_MMS;
&&&&&&&&&&&
(mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_VND_DOCOMO_PF))
&&&&&&&&&&&&&&&
binaryContentType =
WspTypeDecoder.CONTENT_TYPE_B_VND_DOCOMO_PF;
&&&&&&&&&&&
&&&&&&&&&&&&&&&
if (Config.LOGD) Log.w(LOG_TAG, "Received PDU. Unknown Content-Type
= " + mimeType);
&&&&&&&&&&&&&&&
return Intents.RESULT_SMS_HANDLED;
&&&&&&&&&&&
index += pduDecoder.getDecodedDataLength();
boolean dispatchedByApplication =
switch (binaryContentType) {
&&&&&&&&&&&
case WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO:
&&&&&&&&&&&&&&&
dispatchWapPdu_PushCO(pdu, transactionId, pduType,
headerStartIndex, headerLength);
&&&&&&&&&&&&&&&
dispatchedByApplication =
&&&&&&&&&&&&&&&
&&&&&&&&&&&
//处理短信方法
&&&&&&&&&&&
case WspTypeDecoder.CONTENT_TYPE_B_MMS:
&&&&&&&&&&&&&&&
dispatchWapPdu_MMS(pdu, transactionId, pduType, headerStartIndex,
headerLength);
&&&&&&&&&&&&&&&
dispatchedByApplication =
&&&&&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&&&&&&&&&&
if (dispatchedByApplication == false) {
&&&&&&&&&&&
dispatchWapPdu_default(pdu,
transactionId, pduType, mimeType,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
headerStartIndex, headerLength);
return Activity.RESULT_OK;
&& private void dispatchWapPdu_MMS(byte[]
pdu, int transactionId, int pduType,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
int headerStartIndex, int headerLength) {
byte[] header = new byte[headerLength];
System.arraycopy(pdu, headerStartIndex, header, 0,
header.length);
int dataIndex = headerStartIndex + headerL
byte[] data = new byte[pdu.length - dataIndex];
System.arraycopy(pdu, dataIndex, data, 0, data.length);
Intent intent = new
Intent(Intents.WAP_PUSH_RECEIVED_ACTION);
intent.setType(WspTypeDecoder.CONTENT_MIME_TYPE_B_MMS);
intent.putExtra("transactionId", transactionId);
intent.putExtra("pduType", pduType);
intent.putExtra("header", header);
intent.putExtra("data", data);
mSmsDispatcher.dispatch(intent,
"android.permission.RECEIVE_MMS");
该方法比较长,我们直接看到:调用父类的dispatch将信息广播出去。
应用层package
com.android.gzs.mms.transaction.PushReceiver类的onReceive将被调用,
让屏幕亮5秒,
//接收彩信事件
&&& public void
onReceive(Context context, Intent intent) {
(intent.getAction().equals(WAP_PUSH_RECEIVED_ACTION)
&&&&&&&&&&&&&&&
ContentType.MMS_MESSAGE.equals(intent.getType())) {
&&&&&&&&&&&
if (LOCAL_LOGV) {
&&&&&&&&&&&&&&&
Log.v(TAG, "Received PUSH Intent: " + intent);
&&&&&&&&&&&
&&&&&&&&&&&
// Hold a wake lock for 5 seconds, enough to give any
&&&&&&&&&&&
// services we start time to take their own wake locks.
&&&&&&&&&&&
//让屏幕亮5秒,然后创建一个ReceivePushTask并使用它的execute方法。
&&&&&&&&&&&PowerManager
(PowerManager)context.getSystemService(Context.POWER_SERVICE);
&&&&&&&&&&&
PowerManager.WakeLock wl =
pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
"MMS PushReceiver");
&&&&&&&&&&&
wl.acquire(5000);
&&&&&&&&&&&
new ReceivePushTask(context).execute(intent);
}然后创建一个ReceivePushTask并使用它的execute方法。ReceivePushTask是一个AsyncTask,实现了doInBackground方法。当传入intent后,会在doInBackground中将其中的数据转成GenericPdu,并根据其消息
类型做出不同的操作。&
& private class ReceivePushTask extends
AsyncTask&Intent,Void,Void& {
private Context mC
public ReceivePushTask(Context context) {
&&&&&&&&&&&
mContext =
protected Void doInBackground(Intent... intents) {
&&&&&&&&&&&
Intent intent = intents[0];
&&&&&&&&&&&
// 获取push-data&
&&&&&&&&&&&
//Get raw PDU push-data from the message and parse it
&&&&&&&&&&&
byte[] pushData =
intent.getByteArrayExtra("data");
&&&&&&&&&&&
PduParser parser = new PduParser(pushData);
&&&&&&&&&&&
GenericPdu pdu = parser.parse();
&&&&&&&&&&&
if (null == pdu) {
&&&&&&&&&&&&&&&
Log.e(TAG, "Invalid PUSH data");
&&&&&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&&&&&&
PduPersister p = PduPersister.getPduPersister(mContext);
&&&&&&&&&&&
ContentResolver cr = mContext.getContentResolver();
&&&&&&&&&&&
int type = pdu.getMessageType();
&&&&&&&&&&&
long threadId = -1;
&&&&&&&&&&&
&&&&&&&&&&&&&&&
switch (type) {
&&&&&&&&&&&&&&&
//如果是发送报告或已读报告,将其存入数据库。
&&&&&&&&&&&&&&&&&&&
case MESSAGE_TYPE_DELIVERY_IND:
&&&&&&&&&&&&&&&&&&&
case MESSAGE_TYPE_READ_ORIG_IND: {
&&&&&&&&&&&&&&&&&&&&&&&
threadId = findThreadId(mContext, pdu, type);
&&&&&&&&&&&&&&&&&&&&&&&
if (threadId == -1) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
// The associated SendReq isn't found, therefore skip
&&&&&&&&&&&&&&&&&&&&&&&&&&&
// processing this PDU.
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
Uri uri = p.persist(pdu, Inbox.CONTENT_URI);
&&&&&&&&&&&&&&&&&&&&&&&
// Update thread ID for ReadOrigInd &
DeliveryInd.
&&&&&&&&&&&&&&&&&&&&&&&
ContentValues values = new ContentValues(1);
&&&&&&&&&&&&&&&&&&&&&&&
values.put(Mms.THREAD_ID, threadId);
&&&&&&&&&&&&&&&&&&&&&&&
SqliteWrapper.update(mContext, cr, uri, values, null, null);
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
//彩信通知
&&&&&&&&&&&&&&&&&&&
case MESSAGE_TYPE_NOTIFICATION_IND: {
&&&&&&&&&&&&&&&&&&&&&&&
NotificationInd nInd = (NotificationInd)
&&&&&&&&&&&&&&&&&&&&&&&
//是否将TransactionID添加到URl的后面,
&&&&&&&&&&&&&&&&&&&&&&&
//TransactionId
交易标识,用以识别一对M-Notification.ind及后续的M-NotifyResp.ind消息
&&&&&&&&&&&&&&&&&&&&&&&
if (MmsConfig.getTransIdEnabled()) {
&&&&&&&&&&&&&&&&&&&&&&&
//下载URI地址Content-location-value
&&&&&&&&&&&&&&&&&&&&&&&
&&& byte []
contentLocation = nInd.getContentLocation();
&&&&&&&&&&&&&&&&&&&&&&&&&&&
if ('=' == contentLocation[contentLocation.length - 1]) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
byte [] transactionId = nInd.getTransactionId();
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
byte [] contentLocationWithId = new byte
[contentLocation.length
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+ transactionId.length];
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
System.arraycopy(contentLocation, 0, contentLocationWithId,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
0, contentLocation.length);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
System.arraycopy(transactionId, 0, contentLocationWithId,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
contentLocation.length, transactionId.length);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
nInd.setContentLocation(contentLocationWithId);
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
if (!isDuplicateNotification(mContext, nInd)) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
Uri uri = p.persist(pdu, Inbox.CONTENT_URI);
&&&&&&&&&&&&&&&&&&&&&
// 启动TransactionService服务,在onStartCommand中调用launchTransaction方法。
&&&&&&&&&&&&&&&&&&&&&&&&&&&
Intent svc = new Intent(mContext,
TransactionService.class);
&&&&&&&&&&&&&&&&&&&&&&&&&&&
svc.putExtra(TransactionBundle.URI,
uri.toString());
&&&&&&&&&&&&&&&&&&&&&&&&&&&
svc.putExtra(TransactionBundle.TRANSACTION_TYPE,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
Transaction.NOTIFICATION_TRANSACTION);
&&&&&&&&&&&&&&&&&&&&&&&&&&&
mContext.startService(svc);
&&&&&&&&&&&&&&&&&&&&&&&
} else if (LOCAL_LOGV) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "Skip downloading duplicate message: "
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
+ new String(nInd.getContentLocation()));
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
Log.e(TAG, "Received unrecognized PDU.");
&&&&&&&&&&&&&&&
&&&&&&&&&&&
} catch (MmsException e) {
&&&&&&&&&&&&&&&
Log.e(TAG, "Failed to save the data from PUSH: type=" + type,
&&&&&&&&&&&
} catch (RuntimeException e) {
&&&&&&&&&&&&&&&
Log.e(TAG, "Unexpected RuntimeException.", e);
&&&&&&&&&&&
&&&&&&&&&&&
if (LOCAL_LOGV) {
&&&&&&&&&&&&&&&
Log.v(TAG, "PUSH Intent processed.");
&&&&&&&&&&&
&&&&&&&&&&&
如果是发送报告或已读报告,将其存入数据库。
如果是彩信通知,若已存在,则不处理。否则将其存入数据库。启动TransactionService进行处理。
启动TransactionService服务,在onStartCommand中调用launchTransaction方法。
&&& public int
onStartCommand(Intent intent, int flags, int startId) {
if (intent == null) {
&&&&&&&&&&&
return Service.START_NOT_STICKY;
mConnMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
boolean noNetwork = !isNetworkAvailable();
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
&&&&&&&&&&&
Log.v(TAG, "onStart: #" + startId + ": " + intent.getExtras() + "
intent=" + intent);
&&&&&&&&&&&
Log.v(TAG, "&&&
networkAvailable=" + !noNetwork);
if (ACTION_ONALARM.equals(intent.getAction()) ||
(intent.getExtras() == null)) {
&&&&&&&&&&&
// Scan database to find all pending operations.
&&&&&&&&&&&
Cursor cursor =
PduPersister.getPduPersister(this).getPendingMessages(
&&&&&&&&&&&&&&&&&&&
System.currentTimeMillis());
&&&&&&&&&&&
if (cursor != null) {
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
int count = cursor.getCount();
&&&&&&&&&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
&&&&&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "onStart: cursor.count=" + count);
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
if (count == 0) {
&&&&&&&&&&&&&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "onStart: no pending messages. Stopping
service.");
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
RetryScheduler.setRetryAlarm(this);
&&&&&&&&&&&&&&&&&&&&&&&
stopSelfIfIdle(startId);
&&&&&&&&&&&&&&&&&&&&&&&
return Service.START_NOT_STICKY;
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
int columnIndexOfMsgId =
cursor.getColumnIndexOrThrow(PendingMessages.MSG_ID);
&&&&&&&&&&&&&&&&&&&
int columnIndexOfMsgType = cursor.getColumnIndexOrThrow(
&&&&&&&&&&&&&&&&&&&&&&&&&&&
PendingMessages.MSG_TYPE);
&&&&&&&&&&&&&&&&&&&
if (noNetwork) {
&&&&&&&&&&&&&&&&&&&&&&&
// Make sure we register for connection state changes.
&&&&&&&&&&&&&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "onStart: registerForConnectionStateChanges");
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
MmsSystemEventReceiver.registerForConnectionStateChanges(
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
getApplicationContext());
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
while (cursor.moveToNext()) {
&&&&&&&&&&&&&&&&&&&&&&&
int msgType = cursor.getInt(columnIndexOfMsgType);
&&&&&&&&&&&&&&&&&&&&&&&
int transactionType = getTransactionType(msgType);
&&&&&&&&&&&&&&&&&&&&&&&
if (noNetwork) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
onNetworkUnavailable(startId, transactionType);
&&&&&&&&&&&&&&&&&&&&&&&&&&&
return Service.START_NOT_STICKY;
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
switch (transactionType) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&
case Transaction.RETRIEVE_TRANSACTION:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// If it's a transiently failed transaction,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// we should retry it in spite of current
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// downloading mode.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
int failureType = cursor.getInt(
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
cursor.getColumnIndexOrThrow(
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
PendingMessages.ERROR_TYPE));
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
if (!isTransientFailure(failureType)) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// fall-through
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
Uri uri = ContentUris.withAppendedId(
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
Mms.CONTENT_URI,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
cursor.getLong(columnIndexOfMsgId));
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
TransactionBundle args = new TransactionBundle(
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
transactionType, uri.toString());
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// FIXME: We use the same startId for all MMs.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
launchTransaction(startId, args, false);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
} finally {
&&&&&&&&&&&&&&&&&&&
cursor.close();
&&&&&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "onStart: no pending messages. Stopping
service.");
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
RetryScheduler.setRetryAlarm(this);
&&&&&&&&&&&&&&&
stopSelfIfIdle(startId);
&&&&&&&&&&&
&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE))
&&&&&&&&&&&&&&&
Log.v(TAG, "onStart: launch transaction...");
&&&&&&&&&&&
&&&&&&&&&&&
// For launching NotificationTransaction and test
&&&&&&&&&&&
TransactionBundle args = new
TransactionBundle(intent.getExtras());
&&&&&&&&&&&
launchTransaction(startId, args, noNetwork);
return Service.START_NOT_STICKY;
private void launchTransaction(int serviceId, TransactionBundle
txnBundle, boolean noNetwork) {
if (noNetwork) {
&&&&&&&&&&&
Log.w(TAG, "launchTransaction: no network error!");
&&&&&&&&&&&
onNetworkUnavailable(serviceId,
txnBundle.getTransactionType());
&&&&&&&&&&&
&&&&&&&Message
msg = mServiceHandler.obtainMessage(EVENT_TRANSACTION_REQUEST);
msg.arg1 = serviceId;
msg.obj = txnB
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
&&&&&&&&&&&
Log.v(TAG, "launchTransaction: sending message " + msg);
mServiceHandler.sendMessage(msg);
接着以what=
EVENT_TRANSACTION_REQUEST的参数运行mServiceHandler,在mServiceHandler的处理中将创建
NotificationTransaction类的对象,经一系列的判断最后将调用processTransaction方法处理
NotificationTransaction对象。
ServiceHandler mServiceH
handMessage()方法处理:
&public void handleMessage(Message msg)
&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE))
&&&&&&&&&&&&&&&
Log.v(TAG, "Handling incoming message: " + msg);
&&&&&&&&&&&
&&&&&&&&&&&
Transaction transaction =
&&&&&&&&&&&
switch (msg.what) {
&&&&&&&&&&&&&&&
case EVENT_QUIT:
&&&&&&&&&&&&&&&&&&&
getLooper().quit();
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
case EVENT_CONTINUE_MMS_CONNECTIVITY:
&&&&&&&&&&&&&&&&&&&
synchronized (mProcessing) {
&&&&&&&&&&&&&&&&&&&&&&&
if (mProcessing.isEmpty()) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE))
&&&&&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "handle EVENT_CONTINUE_MMS_CONNECTIVITY
event...");
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
int result = beginMmsConnectivity();
&&&&&&&&&&&&&&&&&&&&&&&
if (result != Phone.APN_ALREADY_ACTIVE) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "Extending MMS connectivity returned " + result
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
" instead of APN_ALREADY_ACTIVE");
&&&&&&&&&&&&&&&&&&&&&&&&&&&
// Just wait for connectivity startup without
&&&&&&&&&&&&&&&&&&&&&&&&&&&
// any new request of APN switch.
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
} catch (IOException e) {
&&&&&&&&&&&&&&&&&&&&&&&
Log.w(TAG, "Attempt to extend use of MMS connectivity
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
// Restart timer
&&&&&&&&&&&&&&&&&&&
sendMessageDelayed(obtainMessage(EVENT_CONTINUE_MMS_CONNECTIVITY),
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
APN_EXTENSION_WAIT);
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
case EVENT_DATA_STATE_CHANGED:
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
if (mConnectivityListener == null) {
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
NetworkInfo info =
mConnectivityListener.getNetworkInfo();
&&&&&&&&&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE))
&&&&&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "Handle DATA_STATE_CHANGED event: " +
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
// Check availability of the mobile network.
&&&&&&&&&&&&&&&&&&&
if ((info == null) || (info.getType() !=
&&&&&&&&&&&&&&&&&&&&&&&&&&&
ConnectivityManager.TYPE_MOBILE_MMS)) {
&&&&&&&&&&&&&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE))
&&&&&&&&&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "&& type is not
TYPE_MOBILE_MMS, bail");
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
if (!info.isConnected()) {
&&&&&&&&&&&&&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE))
&&&&&&&&&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "&& TYPE_MOBILE_MMS
not connected, bail");
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
TransactionSettings settings = new
TransactionSettings(
&&&&&&&&&&&&&&&&&&&&&&&&&&&
TransactionService.this, info.getExtraInfo());
&&&&&&&&&&&&&&&&&&&
// If this APN doesn't have an MMSC, wait for one that
&&&&&&&&&&&&&&&&&&&
if (TextUtils.isEmpty(settings.getMmscUrl())) {
&&&&&&&&&&&&&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE))
&&&&&&&&&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "&& empty MMSC url,
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
// Set a timer to keep renewing our "lease" on the MMS
connection
&&&&&&&&&&&&&&&&&&&
sendMessageDelayed(obtainMessage(EVENT_CONTINUE_MMS_CONNECTIVITY),
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
APN_EXTENSION_WAIT);
&&&&&&&&&&&&&&&&&&&
processPendingTransaction(transaction, settings);
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
case EVENT_TRANSACTION_REQUEST:
&&&&&&&&&&&&&&&&&&&
int serviceId = msg.arg1;
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
TransactionBundle args = (TransactionBundle)
&&&&&&&&&&&&&&&&&&&&&&&
TransactionSettings transactionS
&&&&&&&&&&&&&&&&&&&&&&&
// Set the connection settings for this
transaction.
&&&&&&&&&&&&&&&&&&&&&&&
// If these have not been set in args, load the default
&&&&&&&&&&&&&&&&&&&&&&&
String mmsc = args.getMmscUrl();
&&&&&&&&&&&&&&&&&&&&&&&
if (mmsc != null) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
transactionSettings = new TransactionSettings(
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
mmsc, args.getProxyAddress(),
args.getProxyPort());
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&
transactionSettings = new TransactionSettings(
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
TransactionService.this, null);
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
int transactionType = args.getTransactionType();
&&&&&&&&&&&&&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE))
&&&&&&&&&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "handle EVENT_TRANSACTION_REQUEST: transactionType="
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
transactionType);
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
// Create appropriate transaction
&&&&&&&&&&&&&&&&&&&&&&&
switch (transactionType) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
case Transaction.NOTIFICATION_TRANSACTION:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
String uri = args.getUri();
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
if (uri != null) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
transaction = new
NotificationTransaction(
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
TransactionService.this, serviceId,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
transactionSettings, uri);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// Now it's only used for test purpose.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
byte[] pushData = args.getPushData();
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
PduParser parser = new PduParser(pushData);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
GenericPdu ind = parser.parse();
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
int type =
PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
if ((ind != null) &&
(ind.getMessageType() == type)) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
transaction = new NotificationTransaction(
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
TransactionService.this, serviceId,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
transactionSettings, (NotificationInd) ind);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
Log.e(TAG, "Invalid PUSH data.");
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
transaction =
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&
case Transaction.RETRIEVE_TRANSACTION:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
transaction = new RetrieveTransaction(
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
TransactionService.this, serviceId,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
transactionSettings, args.getUri());
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&
case Transaction.SEND_TRANSACTION:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
transaction = new SendTransaction(
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
TransactionService.this, serviceId,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
transactionSettings, args.getUri());
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&
case Transaction.READREC_TRANSACTION:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
transaction = new ReadRecTransaction(
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
TransactionService.this, serviceId,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
transactionSettings, args.getUri());
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
Log.w(TAG, "Invalid transaction type: " +
serviceId);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
transaction =
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
if (!processTransaction(transaction)) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
transaction =
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE))
&&&&&&&&&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "Started processing of incoming message: " +
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
} catch (Exception ex) {
&&&&&&&&&&&&&&&&&&&&&&&
Log.w(TAG, "Exception occurred while handling message: " + msg,
&&&&&&&&&&&&&&&&&&&&&&&
if (transaction != null) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
transaction.detach(TransactionService.this);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
if (mProcessing.contains(transaction)) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
synchronized (mProcessing) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
mProcessing.remove(transaction);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&
} catch (Throwable t) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
Log.e(TAG, "Unexpected Throwable.", t);
&&&&&&&&&&&&&&&&&&&&&&&&&&&
} finally {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// Set transaction to null to allow stopping the
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// transaction service.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
transaction =
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
} finally {
&&&&&&&&&&&&&&&&&&&&&&&
if (transaction == null) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE))
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "Transaction was null. Stopping self: " +
serviceId);
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&
endMmsConnectivity();
&&&&&&&&&&&&&&&&&&&&&&&&&&&
stopSelf(serviceId);
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
case EVENT_HANDLE_NEXT_PENDING_TRANSACTION:
&&&&&&&&&&&&&&&&&&&
processPendingTransaction(transaction, (TransactionSettings)
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
Log.w(TAG, "what=" + msg.what);
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&
接着以what=
EVENT_TRANSACTION_REQUEST的参数运行mServiceHandler,在mServiceHandler的处理中将创建
NotificationTransaction类的对象,经一系列的判断最后将调用processTransaction方法处理
NotificationTransaction对象。
private boolean processTransaction(Transaction transaction) throws
IOException {
&&&&&&&&&&&
// Check if transaction already processing
&&&&&&&&&&&
synchronized (mProcessing) {
&&&&&&&&&&&&&&&
for (Transaction t : mPending) {
&&&&&&&&&&&&&&&&&&&
if (t.isEquivalent(transaction)) {
&&&&&&&&&&&&&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "Transaction already pending: " +
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
transaction.getServiceId());
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
for (Transaction t : mProcessing) {
&&&&&&&&&&&&&&&&&&&
if (t.isEquivalent(transaction)) {
&&&&&&&&&&&&&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "Duplicated transaction: " +
transaction.getServiceId());
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "processTransaction: call
beginMmsConnectivity...");
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
int connectivityResult = beginMmsConnectivity();
&&&&&&&&&&&&&&&
if (connectivityResult == Phone.APN_REQUEST_STARTED) {
&&&&&&&&&&&&&&&&&&&
mPending.add(transaction);
&&&&&&&&&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
&&&&&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "processTransaction: connResult=APN_REQUEST_STARTED, "
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
"defer transaction pending MMS connectivity");
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
&&&&&&&&&&&&&&&&&&&
Log.v(TAG, "Adding transaction to 'mProcessing' list: " +
transaction);
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
mProcessing.add(transaction);
&&&&&&&&&&&
&&&&&&&&&&&
// Set a timer to keep renewing our "lease" on the MMS
connection
&&&&&&&&&&&
sendMessageDelayed(obtainMessage(EVENT_CONTINUE_MMS_CONNECTIVITY),
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
APN_EXTENSION_WAIT);
&&&&&&&&&&&
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
&&&&&&&&&&&&&&&
Log.v(TAG, "processTransaction: starting transaction " +
transaction);
&&&&&&&&&&&
&&&&&&&&&&&
// Attach to transaction and process it
&&&&&&&&&&&
transaction.attach(TransactionService.this);
&&&&&&&&&&&
transaction.process();
&&&&&&&&&&&
该方法首先会先判断该Transaction对象是否存在
mPending或mProcessing队列中,如果没有则将对象加入到mProcessing中,并将TransactionService本身加入
到NotificationTransaction对象的观察者列表(这样做的目的是为了后面下载完成后通知该服务TransactionService
的mProcessing移除掉NotificationTransaction对象并发送完成下载的广播)。最后将调用
NotificationTransaction的process方法。
& @Override
&&& public void
process() {
new Thread(this).start();
&&& public void
DownloadManager downloadManager =
DownloadManager.getInstance();
//是否自动下载彩信
boolean autoDownload = downloadManager.isAuto();
//是否延迟接收
boolean dataSuspended =
(MmsApp.getApplication().getTelephonyManager().getDataState()
&&&&&&&&&&&&&&&
TelephonyManager.DATA_SUSPENDED);
&&&&&&&&&&&
if (LOCAL_LOGV) {
&&&&&&&&&&&&&&&
Log.v(TAG, "Notification transaction launched: " + this);
&&&&&&&&&&&
&&&&&&&&&&&
// By default, we set status to STATUS_DEFERRED because we
&&&&&&&&&&&
// should response MMSC with STATUS_DEFERRED when we cannot
&&&&&&&&&&&
// download a MM immediately.
&&&&&&&&&&&
int status = STATUS_DEFERRED;//延缓状态
&&&&&&&&&&&
//只有彩信的设置是自动获取(“auto retrieve”)时,它才会去下载彩信,否则,它只处理彩信通知(Notification
Indication),而不去下载彩信。
&&&&&&&&&&&
// Don't try to download when data is suspended, as it will fail,
so defer download
&&&&&&&&&&&
if (!autoDownload || dataSuspended) {
&&&&&&&&&&&&&&&
//标记短信状态【延迟下载】
&&&&&&&&&&&
downloadManager.markState(mUri,
DownloadManager.STATE_UNSTARTED);
&&&&&&&&&&&&&&&
//发送回执信息
&&&&&&&&&&&&&&&
sendNotifyRespInd(status);
&&&&&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&&&&&&
//【已下载】
&&&&&&&&&&&
downloadManager.markState(mUri,
DownloadManager.STATE_DOWNLOADING);
&&&&&&&&&&&
if (LOCAL_LOGV) {
&&&&&&&&&&&&&&&
Log.v(TAG, "Content-Location: " + mContentLocation);
&&&&&&&&&&&
&&&&&&&&&&&
byte[] retrieveConfData =
&&&&&&&&&&&
// We should catch exceptions here to response MMSC
&&&&&&&&&&&
// with STATUS_DEFERRED.
&&&&&&&&&&&
&&&&&&&&&&&
&&& // 接收PDU 数据
retrieve a PDU from MMSC.
&&&&&&&&&&&&&&&
retrieveConfData = getPdu(mContentLocation);
&&&&&&&&&&&
} catch (IOException e) {
&&&&&&&&&&&&&&&
mTransactionState.setState(FAILED);
&&&&&&&&&&&
&&&&&&&&&&&
if (retrieveConfData != null) {
&&&&&&&&&&&&&&&
GenericPdu pdu = new PduParser(retrieveConfData).parse();
&&&&&&&&&&&&&&&
if ((pdu == null) || (pdu.getMessageType() !=
MESSAGE_TYPE_RETRIEVE_CONF)) {
&&&&&&&&&&&&&&&&&&&
Log.e(TAG, "Invalid M-RETRIEVE.CONF PDU.");
&&&&&&&&&&&&&&&&&&&
mTransactionState.setState(FAILED);
&&&&&&&&&&&&&&&&&&&
status = STATUS_UNRECOGNIZED;
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
// Save the received PDU (must be a M-RETRIEVE.CONF).
&&&&&&&&&&&&&&&&&&&
PduPersister p = PduPersister.getPduPersister(mContext);
&&&&&&&&&&&&&&&&&&&
Uri uri = p.persist(pdu, Inbox.CONTENT_URI);
&&&&&&&&&&&&&&&&&&&
// We have successfully downloaded the new MM. Delete the
&&&&&&&&&&&&&&&&&&&
// M-NotifyResp.ind from Inbox.
&&&&&&&&&&&&&&&&&&&
SqliteWrapper.delete(mContext, mContext.getContentResolver(),
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
mUri, null, null);
&&&&&&&&&&&&&&&&&&&
// Notify observers with newly received MM.
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
status = STATUS_RETRIEVED;
&&&&&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&&&&&&
if (LOCAL_LOGV) {
&&&&&&&&&&&&&&&
Log.v(TAG, "status=0x" + Integer.toHexString(status));
&&&&&&&&&&&
&&&&&&&&&&&
// Check the status and update the result state of this
Transaction.
&&&&&&&&&&&
switch (status) {
&&&&&&&&&&&&&&&
case STATUS_RETRIEVED:
&&&&&&&&&&&&&&&&&&&
mTransactionState.setState(SUCCESS);
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
case STATUS_DEFERRED:
&&&&&&&&&&&&&&&&&&&
// STATUS_DEFERRED, may be a failed immediate retrieval.
&&&&&&&&&&&&&&&&&&&
if (mTransactionState.getState() == INITIALIZED) {
&&&&&&&&&&&&&&&&&&&&&&&
mTransactionState.setState(SUCCESS);
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&&&&&&
sendNotifyRespInd(status);
&&&&&&&&&&&
// Make sure this thread isn't over the limits in message
&&&&&&&&&&&
Recycler.getMmsRecycler().deleteOldMessagesInSameThreadAsMessage(mContext,
} catch (Throwable t) {
&&&&&&&&&&&
Log.e(TAG, Log.getStackTraceString(t));
} finally {
&&&&&&&&&&&
mTransactionState.setContentUri(mUri);
&&&&&&&&&&&
if (!autoDownload || dataSuspended) {
&&&&&&&&&&&&&&&
// Always mark the transaction successful for deferred
&&&&&&&&&&&&&&&
// download since any error here doesn't make sense.
&&&&&&&&&&&&&&&
mTransactionState.setState(SUCCESS);
&&&&&&&&&&&
&&&&&&&&&&&
if (mTransactionState.getState() != SUCCESS) {
&&&&&&&&&&&&&&&
mTransactionState.setState(FAILED);
&&&&&&&&&&&&&&&
Log.e(TAG, "NotificationTransaction failed.");
&&&&&&&&&&&
&&&&&&&&&&&
notifyObservers();
NotificationTransaction
的process方法将下载相应彩信,首先删除彩信通知,通知mmsc,删除超过容量限制的彩信,彩信附件的获取最终是通过getPdu(mContentLocation)来请求附件的流,返回byte[]类型。最后将notifyObservers()通知
TransactionService处理其余待发送的彩信和发送下载完成的广播。
看图比较容易理解:(网上窃的一副妙图~~,不过里面最后那里好像有一个小错误,不过没关系~~)
(彩信接收主要大概涉及到的类的类图,这是原创滴,原创就是简陋)
到SMSDispatch中间其实涉及很多步骤,这里就简明一点,抽丝剥茧,让大家对彩信接收涉及到的类的分布和以及它们的作用有个大概的蓝图。短信来后发现自己属于GsmSMSDispatch类,WapPushOverSms实例调用dispatchWapPdu发送广播,PushReceive接收到广播后启动TransactionService服务,TransactionService将自己attach到mObservers的观察列表中,
然后调用NotificationTransaction对象的process方法,该方法将通过getPdu来获取附件内容,最后将调用
notifyObservers通知所有添加到观察列表的对象调用update方法实现更新。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 小锅卫星电视接收器 的文章

 

随机推荐