android: 接收和發送短信

8.2    接收和發送短信android

 

收發短信應該是每一個手機最基本的功能之一了,即便是許多年前的老手機也都會具有這 項功能,而 Android 做爲出色的智能手機操做系統,天然也少不了在這方面的支持。每一個 Android 手機都會內置一個短信應用程序,使用它就能夠輕鬆地完成收發短信的操做,如 圖 8.4 所示。數組

圖   8.4ide

 

不過做爲一名開發者,僅僅知足於此顯然是不夠的。你要知道,Android 還提供了一系 列的 API,使得咱們甚至能夠在本身的應用程序裏接收和發送短信。也就是說,只要你有足 夠的信心,徹底能夠本身實現一個短信應用來替換掉 Android 系統自帶的短信應用。那麼下 面咱們就來看一看,如何才能在本身的應用程序裏接收和發送短信。佈局

 

8.2.1    接收短信學習

 

其實接收短信主要是利用了咱們在第 5 章學習過的廣播機制。當手機接收到一條短信的 時候,系統會發出一條值爲 android.provider.Telephony.SMS_RECEIVED 的廣播,這條廣播裏 攜帶着與短信相關的全部數據。每一個應用程序均可以在廣播接收器裏對它進行監聽,收到廣 播時再從中解析出短信的內容便可。this

讓咱們經過一個具體的例子來實踐一下吧,新建一個 SMSTest 項目,首先修改 activity_操作系統

main.xml 中的代碼,以下所示:3d

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"xml

android:orientation="vertical" >對象

 

 

<LinearLayout android:layout_width="match_parent"

 

 

 

android:layout_height="50dp" >

 

 

<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:padding="10dp" android:text="From:" />

 

<TextView android:id="@+id/sender" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" />

</LinearLayout>

 

 

<LinearLayout android:layout_width="match_parent" android:layout_height="50dp" >

 

<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:padding="10dp" android:text="Content:" />

 

<TextView android:id="@+id/content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" />

</LinearLayout>

 

 

</LinearLayout>

這個佈局文件裏,咱們在根元素下面放置了兩個 LinearLayout,用於顯示兩行數據。第 一個 LinearLayout 中有兩個 TextView,用於顯示短信的發送方。第二個 LinearLayout 中也有 兩個 TextView,用於顯示短信的內容。

接着修改 MainActivity 中的代碼,在 onCreate()方法中獲取到兩個 TextView 的實例,以下所示:

 

public class MainActivity extends Activity {

 

 

private TextView sender;

 

 

private TextView content;

 

 

@Override

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);

sender = (TextView) findViewById(R.id.sender);

content = (TextView) findViewById(R.id.content);

}

 

 

}

而後咱們須要建立一個廣播接收器來接收系統發出的短信廣播。在 MainActivity 中新建 MessageReceiver 內部類繼承自 BroadcastReceiver,並在 onReceive()方法中編寫獲取短信數 據的邏輯,代碼以下所示:

 

public class MainActivity extends Activity {

 

……

 

 

class MessageReceiver extends BroadcastReceiver {

 

 

@Override

public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras();

Object[] pdus = (Object[]) bundle.get("pdus"); // 提取短信消息

SmsMessage[] messages = new SmsMessage[pdus.length];

for (int i = 0; i < messages.length; i++) {

messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);

 

 

 

 

送方號碼


}

String address = messages[0].getOriginatingAddress(); // 獲取發

 

 

String fullMessage = "";

for (SmsMessage message : messages) {

fullMessage += message.getMessageBody(); // 獲取短信內容

 

} sender.setText(address); content.setText(fullMessage);

}

 

}

}

能夠看到,首先咱們從 Intent 參數中取出了一個 Bundle 對象,而後使用 pdu 密鑰來提取 一個 SMS pdus 數組,其中每個 pdu 都表示一條短信消息。接着使用 SmsMessage 的 createFromPdu() 方法將每個 pdu 字節數組轉換爲 SmsMessage 對象,調用這個對象的 getOriginatingAddress()方法就能夠獲取到短信的發送方號碼,調用 getMessageBody()方法就 能夠獲取到短信的內容,而後將每個 SmsMessage 對象中的短信內容拼接起來,就組成了 一條完整的短信。最後將獲取到的發送方號碼和短信內容顯示在 TextView 上。

完成了 MessageReceiver 以後,咱們還須要對它進行註冊才能讓它接收到短信廣播,代 碼以下所示:

 public class MainActivity extends Activity {

 

private TextView sender;

 

 

private TextView content;

 

 

private IntentFilter receiveFilter;

 

 

private MessageReceiver messageReceiver;

 

 

@Override

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);

sender = (TextView) findViewById(R.id.sender); content = (TextView) findViewById(R.id.content); receiveFilter = new IntentFilter();

receiveFilter.addAction("android.provider.Telephony.SMS_RECEIVED");

messageReceiver = new MessageReceiver();

registerReceiver(messageReceiver, receiveFilter);

}

 

 

@Override

 

 

 

protected void onDestroy() {

super.onDestroy();

unregisterReceiver(messageReceiver);

}

……

}

這些代碼你應該都已經很是熟悉了,使用的就是動態註冊廣播的技術。在 onCreate()方 法中對 MessageReceiver 進行註冊,在 onDestroy()方法中再對它取消註冊。

代碼到這裏就已經完成得差很少了,不過最後咱們還須要給程序聲明一個接收短信的權 限才行,修改 AndroidManifest.xml 中的代碼,以下所示:

 

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.smstest"

android:versionCode="1" android:versionName="1.0" >

<uses-permission android:name="android.permission.RECEIVE_SMS" />

……

</manifest>

如今能夠來運行一下程序了,界面如圖 8.5 所示。

圖   8.5

 

當有短信到來時,短信的發送方和內容就會顯示在界面上。不過話說回來,咱們使用的是模擬器,模擬器上怎麼可能會收穫得短信呢?不用擔憂,DDMS 提供了很是充分的模擬環

境,使得咱們不須要支付真正的短信費用也能夠模擬收發短信的場景。將 Eclipse 切換到 DDMS 視圖下,而後點擊 Emulator Control 切換卡,在這裏就能夠向模擬器發送短信了,如 圖 8.6 所示。

 

圖   8.6

 

能夠看到,咱們指定發送方的號碼是 556677,並填寫了一段短信內容,而後點擊 Send按鈕,這樣短信就發送成功了。接着咱們立馬查看一下 SMSTest 這個程序,結果如圖 8.7 所示。

 

圖   8.7

 

能夠看到,短信的發送方號碼和短信內容都顯示到界面上了,說明接收短信的功能成功 實現了。

 

8.2.2    攔截短信

 

仔細觀察圖 8.7,你會發如今系統狀態欄出現了一個通知圖標,這個通知圖標是由 Android 自帶的短信程序產生的。也就是說當短信到來時,不只咱們的程序會接收到這條短信,系統 的短信程序一樣也會收到。一樣一條短信被重複接收兩遍就會形成比較差的用戶體驗,那麼 有沒有什麼辦法能夠屏蔽系統短信程序的接收功能呢?

在前面 5.3.2 節學習有序廣播的時候咱們就已經知道,有序廣播的傳遞是能夠截斷的, 而系統發出的短信廣播正是一條有序廣播,所以這裏咱們的答案是確定的。修改 MainActivity 中的代碼,以下所示:

 

public class MainActivity extends Activity {

……

@Override

protected void onCreate(Bundle savedInstanceState) {

……

receiveFilter = new IntentFilter(); receiveFilter.addAction("android.provider.Telephony.SMS_RECEIVED"); receiveFilter.setPriority(100);

messageReceiver = new MessageReceiver();

registerReceiver(messageReceiver, receiveFilter);

}

……

class MessageReceiver extends BroadcastReceiver {

 

 

@Override

public void onReceive(Context context, Intent intent) {

……

abortBroadcast();

}

 

}

}

能夠看到,關鍵性的步驟只有兩步。一是提升 MessageReceiver 的優先級,讓它可以先 於系統短信程序接收到短信廣播。二是在 onReceive()方法中調用 abortBroadcast()方法,停止掉廣播的繼續傳遞。

如今從新運行程序,再向模擬器發送一條短信,這時只有咱們本身的程序才能收到這條 短信了。按下 Back 鍵將程序關閉後,系統的短信程序又會從新擁有接收短信的功能。

注意這個功能必定要慎用,隨意攔截短信有可能會形成重要數據的丟失,因此你在攔截 以前必定要先想清楚這種功能是否是你想要的。

 

8.2.3    發送短信

 

下面咱們繼續對 SMSTest 項目進行擴展,給它加上發送短信的功能。那麼仍是先來編寫 一下佈局文件吧,修改 activity_main.xml 中的代碼,以下所示:

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"

android:orientation="vertical" >

……

<LinearLayout android:layout_width="match_parent" android:layout_height="50dp" >

<TextView

android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:padding="10dp"

android:text="To:" />

 

 

<EditText android:id="@+id/to" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_weight="1" />

</LinearLayout>

 

 

<LinearLayout android:layout_width="match_parent" android:layout_height="50dp" >

<EditText

android:id="@+id/msg_input" android:layout_width="0dp"

 

 

 

android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_weight="1" />

 

<Button android:id="@+id/send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:text="Send" />

</LinearLayout>

 

 

</LinearLayout>

這裏咱們又新增了兩個 LinearLayout,分別處於第三和第四行的位置。第三行中放置了 一個 EditText,用於輸入接收方的手機號碼。第四行中放置了一個 EditText 和一個 Button, 分別用於輸入短信內容和發送短信。

而後修改 MainActivity 中的代碼,在裏面加入發送短信的處理邏輯,代碼以下所示:

 

public class MainActivity extends Activity {

……

private EditText to; private EditText msgInput; private Button send;

@Override

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);

……

to = (EditText) findViewById(R.id.to);

msgInput = (EditText) findViewById(R.id.msg_input); send = (Button) findViewById(R.id.send); send.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

SmsManager smsManager = SmsManager.getDefault();

smsManager.sendTextMessage(to.getText().toString(), null,

 

 

}

});

}

……

}


msgInput.getText().toString(), null, null);

 

能夠看到,首先咱們獲取到了佈局文件中新增控件的實例,而後在 Send 按鈕的點擊事 件裏面處理了發送短信的具體邏輯。當 Send 按鈕被點擊時,會先調用 SmsManager 的 getDefault()方法獲取到 SmsManager 的實例,而後再調用它的 sendTextMessage()方法就能夠 去發送短信了。sendTextMessage()方法接收五個參數,其中第一個參數用於指定接收人的手 機號碼,第三個參數用於指定短信的內容,其餘的幾個參數咱們暫時用不到,直接傳入 null 就能夠了。

接下來也許你已經猜到了,發送短信也是須要聲明權限的,所以修改 AndroidManifest.xml中的代碼,以下所示:

 

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.smstest"

android:versionCode="1"

android:versionName="1.0" >

<uses-permission android:name="android.permission.RECEIVE_SMS" />

<uses-permission android:name="android.permission. SEND_SMS" />

……

</manifest>

如今從新運行程序以後,SMSTest 就擁有了發送短信的能力。不過點擊 Send 按鈕雖然 能夠將短信發送出去,可是咱們並不知道到底發送成功了沒有,這個時候就能夠利用 sendTextMessage()方法的第四個參數來對短信的發送狀態進行監控。修改 MainActivity 中的 代碼,以下所示:

 

public class MainActivity extends Activity {

……

private IntentFilter sendFilter;

 

 

private SendStatusReceiver sendStatusReceiver;

 

 

@Override

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);

 

 

 

……

sendFilter = new IntentFilter(); sendFilter.addAction("SENT_SMS_ACTION"); sendStatusReceiver = new SendStatusReceiver(); registerReceiver(sendStatusReceiver, sendFilter); send.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

SmsManager smsManager = SmsManager.getDefault(); Intent sentIntent = new Intent("SENT_SMS_ACTION"); PendingIntent pi = PendingIntent.getBroadcast

(MainActivity.this, 0, sentIntent, 0);

smsManager.sendTextMessage(to.getText().toString(), null, msgInput.getText().toString(), pi, null);

}

});

}

 

@Override

protected void onDestroy() { super.onDestroy(); unregisterReceiver(messageReceiver);

unregisterReceiver(sendStatusReceiver);

}

……

class SendStatusReceiver extends BroadcastReceiver {

 

 

@Override

public void onReceive(Context context, Intent intent) {

if (getResultCode() == RESULT_OK) {

// 短信發送成功

Toast.makeText(context, "Send succeeded", Toast.LENGTH_LONG).show();

} else {

// 短信發送失敗

Toast.makeText(context, "Send failed", Toast.LENGTH_LONG).show();

}

}

 

 

 

}

}

能夠看到,在 Send 按鈕的點擊事件裏面咱們調用了 PendingIntent 的 getBroadcast()方法 獲取到了一個 PendingIntent 對象,並將它做爲第四個參數傳遞到 sendTextMessage()方法中。 而後又註冊了一個新的廣播接收器 SendStatusReceiver,這個廣播接收器就是專門用於監聽 短信發送狀態的,當 getResultCode()的值等於 RESULT_OK 就會提示發送成功,不然提示發 送失敗。

如今從新運行一下程序,在文本輸入框裏輸入接收方的手機號碼以及短信內容,而後點 擊 Send 按鈕,結果如圖 8.8 所示。

 

圖   8.8

 

注意,這裏雖然提示發送成功了,但實際上使用模擬器來發送短信對方是不可能收穫得 的,只有把這個項目運行在手機上,才能真正地實現發送短信的功能。

另外,根據國際標準,每條短信的長度不得超過 160 個字符,若是想要發送超出這個長 度的短信,則須要將這條短信分割成多條短信來發送,使用 SmsManager 的 sendMultipart- TextMessage()方法就能夠實現上述功能。它的用法和 sendTextMessage()方法也基本相似,感 興趣的話你能夠本身研究一下,這裏就再也不展開講解了。

相關文章
相關標籤/搜索