短信相关的两个类
2018-08-12 本文已影响0人
dev晴天
//SmsMessage类是用来创建短信的,也只管创建,比如设置短信内容,计算短信长度。
SmsManager类是用来发送短信的。
********************************************
Android开发之SmsManager和SmsMessage
Android的手机功能(通话与短信)都放在android.telephony包中,到了4.4时(也就是API19)android.provider.Telephony及相关类横空出世辅助电话功能以及制定安卓世界手机功能的新秩序。
短信功能用到了SmsManager和SmsMessage两个主要类。
接受短信广播,由Intent解析出短信内容明文, intent中的短信是以pud形式传出的,即byte[][]二位数组,
从Android 4.4开始,SmsMessage不推荐使用createFromPdu(byte[] pdu)
推荐使用createFromPdu(byte[], String)。
createFromPdu(byte[], String)
The message format is passed in the SMS_RECEIVED_ACTION as the format String extra, and will be either "3gpp" for GSM/UMTS/LTE messages in 3GPP format or "3gpp2" for CDMA/LTE messages in 3GPP2 format.
第一个参数:意图为SMS_RECEIVED_ACTION中的PDU信息,是一个byte[]数组
第二个参数:通过上面的那段英文可以知道,第二个参数为"3gpp"(GSM/UMTS/LTE)或者"3gpp2"(CDMA/LTE)。所以第二个参数想要获取,可以通过
String format = intent.getStringExtra("format");
获取到,然后传入到形参中。
发送短信via Intent
万能的intent能够帮我们做很多事,只要你有“意图”它就会满足你。
复制代码
1 private void sendMessageViaSystem() {
2 Uri uri = Uri.parse("smsto:"+etNumber.getText());
3 Intent intent = new Intent(Intent.ACTION_VIEW,uri);
4 intent.putExtra("sms_body",etMessage.getText().toString());
5 startActivity(intent);
6 }
复制代码
发送短信via SmsManager
1 private void sendMessage() {
2 SmsManager smsManager = SmsManager.getDefault();
3 smsManager.sendTextMessage(etNumber.getText().toString(), null,
4 etMessage.getText().toString(), null, null);
5 }
最简单的发送短信条件就是有电话号码和短信内容,调用SmsManager的sendTextMessage方法即可。
监听短信的发送状态
sendTextMessage方法的后两个参数是PendingIntent,函数原型如下:
复制代码
1 * @param sentIntent if not NULL this <code>PendingIntent</code> is
2 * broadcast when the message is successfully sent, or failed.
3 * The result code will be <code>Activity.RESULT_OK</code> for success,
4 * or one of these errors:<br>
5 * <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
6 * <code>RESULT_ERROR_RADIO_OFF</code><br>
7 * <code>RESULT_ERROR_NULL_PDU</code><br>
8 * For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
9 * the extra "errorCode" containing a radio technology specific value,
10 * generally only useful for troubleshooting.<br>
11 * The per-application based SMS control checks sentIntent. If sentIntent
12 * is NULL the caller will be checked against all unknown applications,
13 * which cause smaller number of SMS to be sent in checking period.
14 * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
15 * broadcast when the message is delivered to the recipient. The
16 * raw pdu of the status report is in the extended data ("pdu").
17 public void sendTextMessage(
18 String destinationAddress, String scAddress, String text,
19 PendingIntent sentIntent, PendingIntent deliveryIntent)
复制代码
而我们要监听发送状态就要用到这两个参数。与这个两个PendingIntent联系的是两个Broadcast Receiver,其会接收到发送过程中状态广播。就像上面参数解释的一样。
代码示例如下:
复制代码
1 private String SMS_SEND_ACTIOIN = "SMS_SEND";
2 private String SMS_DELIVERED_ACTION = "SMS_DELIVERED";
3
4 private SmsStatusReceiver mSmsStatusReceiver;
5 private SmsDeliveryStatusReceiver mSmsDeliveryStatusReceiver;
6
7 @Override
8 protected void onResume() {
9 super.onResume();
10 mSmsStatusReceiver = new SmsStatusReceiver();
11 registerReceiver(mSmsStatusReceiver,new IntentFilter(SMS_SEND_ACTIOIN));
12
13 mSmsDeliveryStatusReceiver = new SmsDeliveryStatusReceiver();
14 registerReceiver(mSmsDeliveryStatusReceiver,new IntentFilter(SMS_DELIVERED_ACTION));
15 }
16
17 @Override
18 protected void onPause() {
19 super.onPause();
20 unregisterReceiver(mSmsStatusReceiver);
21 unregisterReceiver(mSmsDeliveryStatusReceiver);
22 }
23
24 private void sendMessage() {
25 SmsManager smsManager = SmsManager.getDefault();
26 PendingIntent sentIntent = PendingIntent.getBroadcast(this, 0, new Intent(SMS_SEND_ACTIOIN), 0);
27 PendingIntent deliveryIntent = PendingIntent.getBroadcast(this, 0,
28 new Intent(SMS_DELIVERED_ACTION), 0);
29 smsManager.sendTextMessage(etNumber.getText().toString(), null,
30 etMessage.getText().toString(), sentIntent, deliveryIntent);
31 Log.d(TAG,"sent message.");
32 }
33
34 public class SmsStatusReceiver extends BroadcastReceiver {
35
36 @Override
37 public void onReceive(Context context, Intent intent) {
38 Log.d(TAG,"SmsStatusReceiver onReceive.");
39 switch(getResultCode()) {
40 case Activity.RESULT_OK:
41 Log.d(TAG, "Activity.RESULT_OK");
42 break;
43 case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
44 Log.d(TAG, "RESULT_ERROR_GENERIC_FAILURE");
45 break;
46 case SmsManager.RESULT_ERROR_NO_SERVICE:
47 Log.d(TAG, "RESULT_ERROR_NO_SERVICE");
48 break;
49 case SmsManager.RESULT_ERROR_NULL_PDU:
50 Log.d(TAG, "RESULT_ERROR_NULL_PDU");
51 break;
52 case SmsManager.RESULT_ERROR_RADIO_OFF:
53 Log.d(TAG, "RESULT_ERROR_RADIO_OFF");
54 break;
55 }
56 }
57 }
58
59 public class SmsDeliveryStatusReceiver extends BroadcastReceiver {
60
61 @Override
62 public void onReceive(Context context, Intent intent) {
63 Log.d(TAG,"SmsDeliveryStatusReceiver onReceive.");
64 switch(getResultCode()) {
65 case Activity.RESULT_OK:
66 Log.i(TAG, "RESULT_OK");
67 break;
68 case Activity.RESULT_CANCELED:
69 Log.i(TAG, "RESULT_CANCELED");
70 break;
71 }
72 }
73 }
复制代码
短信接收
与发送状态监听类似,短信的接收也是用广播接收器。为了一直对短信广播的接收,我采用了在Manifest中注册广播的方法。
android:priority系统默认最大值为1000,但是为了获得最高优先级,可以设置为int的最大值,即2147483647
1 <receiver android:name="com.linc.intercept.SmsReceiver" >
2 <intent-filter android:priority="1000" >
3 <action android:name="android.provider.Telephony.SMS_RECEIVED" />
4 </intent-filter>
5 </receiver>
并且将用一个单独类作为短信接收类(这样的方式是不能将其放到内部类中的)。
复制代码
1 public class SmsReceiver extends BroadcastReceiver {
2 private static final String TAG = "SmsReceiver";
3 public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
4
5 @Override
6 public void onReceive(Context context, Intent intent) {
7 String action = intent.getAction();
8 Log.d(TAG,"action: "+action);
9 if (SMS_RECEIVED_ACTION.equals(action)) {
10 Bundle bundle = intent.getExtras();
11 StringBuffer messageContent = new StringBuffer();
12 if (bundle != null) {
13 Object[] pdus = (Object[]) bundle.get("pdus");
14 for (Object pdu : pdus) {
15 SmsMessage message = SmsMessage.createFromPdu((byte[]) pdu);
16 String sender = message.getOriginatingAddress();
17 Log.d(TAG,"sender: "+sender);
18 if ("10086".equals(sender) || "10010".equals(sender) ||
19 "10001".equals(sender)) {
20 messageContent.append(message.getMessageBody());
21 }
22 }
23 if(!messageContent.toString().isEmpty()) {
24 Log.d(TAG,"send message broadcast.");
25 Intent intentBroadcast = new Intent();
26 intentBroadcast.putExtra("message", messageContent.toString());
27 intentBroadcast.setAction("sms_received");
28 context.sendBroadcast(intentBroadcast);
29 Log.d(TAG, "send broadcast and abort");
30 // abortBroadcast();
31 }
32 }
33 }
34 }
35 }
复制代码
但是这样做的弊端就是,接收到的短信如何显示到界面?路有多条,我最后还是选择了广播。
复制代码
1 private SmsReceiver mSmsReceiver;
2 @Override
3 protected void onResume() {
4 super.onResume();
5 mSmsReceiver = new SmsReceiver();
6 IntentFilter intentFilter = new IntentFilter();
7 intentFilter.addAction("sms_received");
8 registerReceiver(mSmsReceiver, intentFilter);
9 }
10 @Override
11 protected void onPause() {
12 super.onPause();
13 unregisterReceiver(mSmsReceiver);
14 }
15 public class SmsReceiver extends BroadcastReceiver {
16 public static final String SMS_RECEIVED_ACTION = "sms_received";
17
18 @Override
19 public void onReceive(Context context, Intent intent) {
20 String action = intent.getAction();
21 Log.d(TAG,"action: "+action);
22 if (SMS_RECEIVED_ACTION.equals(action)) {
23 Bundle bundle = intent.getExtras();
24
25 String messageContent = bundle.getString("message");
26 tvMessage.setText(messageContent);
27 }
28 }
29 }
复制代码