6、溫故知新之Intent
此系列前面簡單地接受過意圖(Intent),這里再次簡單介紹一下,在短信接收程序和使用Intent發送SMS中我們要用到。android應用程序的三大組件——Activities、Services、Broadcast Receiver,通過消息觸發,這個消息就稱作意圖(Intent)。下面以Acitvity為例,介紹一下Intent。Android用Intent這個特殊的類實現在Activity與Activity之間的切換。 Intent類用于描述應用的功能。在Intent的描述結構中,有兩個最重要的部分:動作和動作對應的數據。 典型的動作類型有MAIN、VIEW、PICK、EDIT等,我們在短信接收程序中就用到從廣播意圖中提取動作類型并判斷是否是" android.provider.Telephony.SMS_RECEIVED ",進而作深一步的處理。而動作對應的數據則以URI的形式表示。例如,要查看一個人的聯系方式,需要創建一個動作為VIEW的Intent,以及表示這個人的URI。
通過解析各種Intent,從一個屏幕導航到另一個屏幕是很簡單的。當向前導航時,Activity將會調用 startActivity("指定一個Intent") 方法。然后,系統會在所有已安裝的應用程序中定義的IntentFilter中查找,找到最匹配的Intent對應的Activity。新的Activity接收到指定的Intent的通知后,開始運行。當 startActivity() 方法被調用時,將觸發解析指定Intent的動作,該機制提供了兩個關鍵的好處:
- Activity能夠重復利用從其他組件中以Intent形式產生的請求。
- Activity可以在任何時候被具有相同IntentFilter的新的Activity取代。
7、準備工作:SmsMessage類
顧名思義,SmsMessage類是一個表示短信的類,為了更好地了解Android的短信機制及以后更好地編寫短信相關程序,這里介紹一下該類的公有方法和常量,及嵌套枚舉、類成員。
公有方法:
-
public
?
static
?
int
[]? calculateLength? (CharSequence? msgBody,?
boolean
?use7bitOnly)
參數 :
msgBody -要封裝的消息、 use7bitOnly -如果為TRUE,不是廣播特定7-比特編碼的部分字符被認為是單個空字符;如果為FALSE,且 msgBody 包含非7-比特可編碼字符,長度計算使用16-比特編碼。
返回值 :
返回一個4個元素的int數組,int[0]表示要求使用的SMS數量、int[1]表示編碼單元已使用的數量、int[2]表示剩余到下個消息的編碼單元數量、int[3]表示編碼單元大小的指示器。 -
public
?
static
?
int
[]? calculateLength? (String? messageBody,?
boolean
?use7bitOnly)
參數 和 返回值 跟上面類似 -
public
?
static
?SmsMessage?? createFromPdu? (
byte
[] pdu)
從原始的PDU(protocol description units)創建一個SmsMessage。這個方法很重要,在我們編寫短信接收程序要用到,它從我們接收到的廣播意圖中獲取的字節創建SmsMessage。 -
public
?String? getDisplayMessageBody()
返回短信消息的主體,或者Email消息主體(如果這個消息來自一個Email網關)。如果消息主體不可用,返回null。這個方法也很重要,在我們編寫短信接收程序也要用到。 -
public
?String?? getDisplayOriginatingAddress? ()
返回信息來源地址,或Email地址(如果消息來自Email網關)。如果消息主體不可用,返回null。這個方法在來電顯示,短信接收程序中經常用到。 -
public
?String?? getEmailBody? ()
如果isEmail為TRUE,即是郵件,返回通過網關發送Email的地址,否則返回null。 -
public
?
int
? getIndexOnIcc? ()
返回消息記錄在ICC上的索引(從1開始的) -
public
?String?? getMessageBody? ()
以一個String返回消息的主體,如果它存在且是基于文本的。 -
public
?SmsMessage.MessageClass?? getMessageClass? ()
返回消息的類。 -
public
?String?? getOriginatingAddress? ()
以String返回SMS信息的來電地址,或不可用時為null。 -
public
?
byte
[]? getPdu? ()
返回消息的原始PDU數據。 -
public
?
int
? getProtocolIdentifier? ()
獲取協議標識符。 - public ?String?? getPseudoSubject? ()
-
public
?String?? getServiceCenterAddress? ()
返回轉播消息SMS服務中心的地址,如果沒有的話為null。 -
public
?
int
? getStatus? ()
GSM:為一個SMS-STATUS-REPORT消息,它返回狀態報告的status字段。這個字段表示之前提交的SMS消息的狀態。
CDMA:為不影響來自GSM的狀態碼,值移動到31-16比特。這個值由一個error類(25-16比特)和一個狀態碼(23-16比特)組成。
如果是0,表示之前發送的消息已經被收到。 -
public
?
int
? getStatusOnIcc? ()
返回消息在ICC上的狀態(已讀、未讀、已發送、未發送)。有下面的幾個值:SmsManager.STATUS_ON_ICC_FREE、SmsManager.STATUS_ON_ICC_READ、SmsManager.STATUS_ON_ICC_UNREAD、SmsManager.STATUS_ON_ICC_SEND、SmsManager.STATUS_ON_ICC_UNSENT這幾個值在 上篇 的SmsManager類介紹有講到。 -
public
?
static
?SmsMessage.SubmitPdu?? getSubmitPdu? (
?????? String? scAddress, String? destinationAddress,?
??????? short ?destinationPort,? byte [] data,?
??????? boolean ?statusReportRequested)
參數 : scAddress? - 服務中心的地址(Sercvice Centre address,為null即使用默認的)、 destinationAddress ?- 消息的目的地址、 destinationPort - 發送消息到目的的端口號、 data ?- 消息數據。
返回值 :一個包含編碼了的SC地址(如果指定了的話)和消息內容的SubmitPdu,否則返回null,如果編碼錯誤。 -
public
?
static
?SmsMessage.SubmitPdu?? getSubmitPdu? (
?????? String? scAddress, String? destinationAddress,
?????? String? message,? boolean ?statusReportRequested)
和上面類似。 -
public
?
static
?
int
? getTPLayerLengthForPDU? (String? pdu)
返回指定SMS-SUBMIT PDU的TP-Layer-Length,長度單位是字節而不是十六進字符。 -
public
?
long
? getTimestampMillis? ()
以currentTimeMillis()格式返回服務中心時間戳。 -
public
?
byte
[]? getUserData? ()
返回用戶數據減去用戶數據頭部(如果有的話) -
public
?
boolean
? isCphsMwiMessage? ()
判斷是否是CPHS MWI消息 -
public
?
boolean
? isEmail? ()
判斷是否是Email,如果消息來自一個Email網關且Email發送者(sender)、主題(subject)、解析主體(parsed body)可用,則返回TRUE。 -
public
?
boolean
? isMWIClearMessage? ()
判斷消息是否是一個CPHS 語音郵件或消息等待MWI清除(clear)消息。 -
public
?
boolean
? isMWISetMessage? ()
判斷消息是否是一個CPHS 語音郵件或消息等待MWI設置(set)消息。 -
public
?
boolean
? isMwiDontStore? ()
如果消息是一個“Message Waiting Indication Group:Discard Message”通知且不應該保存,則返回TRUE,否則返回FALSE。 -
public
?
boolean
? isReplace? ()
判斷是否是一個“replace short message”SMS -
public
?
boolean
? isReplyPathPresent? ()
判斷消息的TP-Reply-Path位是否在消息中設置了。 -
public
?
boolean
? isStatusReportMessage? ()
判斷是否是一個SMS-STATUS-REPORT消息。
常量值:
- public ? static ? final ? int ? ENCODING_16BIT :值為3(0x00000003)
- public ? static ? final ? int ? ENCODING_8BIT :值為2 (0x00000002)
- public ? static ? final ? int ? ENCODING_UNKNOWN :值為0 (0x00000000) ,用戶數據編碼單元的大小。
- public ? static ? final ? int ? MAX_USER_DATA_BYTES :值為140 (0x0000008c),表示每個消息的最大負載字節數。
- public ? static ? final ? int ? MAX_USER_DATA_BYTES_WITH_HEADER :134 (0x00000086),如果一個用戶數據有頭部,該值表示它的最大負載字節數,該值假定頭部僅包含CONCATENATED_8_BIT_REFENENCE元素。
- public ? static ? final ? int ? MAX_USER_DATA_SEPTETS :值為160 (0x000000a0) ,表示每個消息的最大負載septets數。
- public ? static ? final ? int ? MAX_USER_DATA_SEPTETS_WITH_HEADER :值為153 (0x00000099),如果存在用戶數據頭部,則該值表示最大負載septets數該值假定頭部僅包含CONCATENATED_8_BIT_REFENENCE元素。
嵌套枚舉成員SmsMessage.MessageClass的枚舉值:
- public ? static ? final ?SmsMessage.MessageClass?? CLASS_0
- public ? static ? final ?SmsMessage.MessageClass?? CLASS_1
- public ? static ? final ?SmsMessage.MessageClass?? CLASS_2
- public ? static ? final ?SmsMessage.MessageClass?? CLASS_3
- public ? static ? final ?SmsMessage.MessageClass?? CLASS_UNKNOWN
嵌套枚舉成員SmsMessage.MessageClass的公有方法:
- public ? static ?SmsMessage.MessageClass valueOf (String name):返回值的字符串的值
- public ? static ? final ?MessageClass[]?? values? ():返回MessageClass的值數組
嵌套類成員SmsMessage.SubmitPdu的字段:
- public ? byte []? encodedMessage :編碼了的消息
- public ? byte []? encodedScAddress :編碼的服務中心地址
嵌套類成員SmsMessage.SubmitPdu的公有方法:
-
public
?String?? toString? ()
返回一個包含簡單的、可讀的這個對象的描述字符串。鼓勵子類去重寫這個方法,并提供實現對象的類型和數據。默認實現簡單地連接類名、@、十六進制表示的對象哈希碼,即下面的形式: getClass().getName() + '@' + Integer.toHexString(hashCode())
8、SMS接收程序
當一個SMS消息被接收時,一個新的廣播意圖由android.provider.Telepony.SMS_RECEIVED動作觸發。注意:這個一個字符串字面量(string? literal),但是SDK當前并沒有包括這個字符串的引用,因此當要在應用程序中使用它時必須自己顯示的指定它?,F在我們就開始構建一個SMS接收程序:
1)、跟SMS發送程序類似,要在清單文件 AndroidManifest.xml 中指定權限允許接收SMS: < uses - permission ? android : name = "android.permission.RECEIVER_SMS" />
為了能夠回發短信,還應該加上發送的權限。
2)、應用程序監聽SMS意圖廣播,SMS廣播意圖包含了到來的SMS細節。我們要從其中提取出 SmsMessage 對象,這樣就要用到 pdu 鍵提取一個SMS PDUs數組(protocol description units—封裝了一個SMS消息和它的元數據),每個元素表示一個SMS消息。為了將每個PDU byte數組轉化為一個SMS消息對象,需要調用 SmsMessage.createFromPdu 。
每個 SmsMessage 包含SMS消息的詳細信息,包括起始地址(電話號碼)、時間戳、消息體。下面編寫一個接收短信的類SmsReceiver代碼如下:
?
package skynet.com.conblogs.www; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.telephony.SmsManager; import android.telephony.SmsMessage; import android.widget.Toast; public class SmsReceiver extends BroadcastReceiver { @Override public void onReceive(Context _context, Intent _intent) { if (_intent.getAction().equals(SMS_RECEIVER)) { SmsManager sms = SmsManager.getDefault(); Bundle bundle = _intent.getExtras(); if (bundle != null ) { Object[] pdus = (Object[]) bundle.get(" pdus "); SmsMessage[] messages = new SmsMessage[pdus.length]; for ( int i = 0; i < pdus.length; i++) messages[i] = SmsMessage.createFromPdu(( byte []) pdus[i]); for (SmsMessage message : messages) { String msg = message.getMessageBody(); String to = message.getOriginatingAddress(); if (msg.toLowerCase().startsWith(queryString)) { String out = msg.substring(queryString.length()); sms.sendTextMessage(to, null , out, null , null ); Toast.makeText(_context, " success ", Toast.LENGTH_LONG).show(); } } } } } private static final String queryString=" @echo "; private static final String SMS_RECEIVER= " android.provider.Telephony.SMS_RECEIVED "; }
?
上面代碼的功能是從接收到的廣播意圖中提取來電號碼、短信內容,然后將短信加上@echo頭部回發給來電號碼,并在屏幕上顯示一個Toast消息提示成功。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
