5min接收短信并小心AS发短信的坑

收发短信应该是每个手机最基本的功能之一了,即使是许多年前的老手机也都会具备这项功能,而Android 作为出色的智能手机操作系统,自然也少不了在这方面的支持。每个Android 手机都会内置一个短信应用程序,使用它就可以轻松地完成收发短信的操作。

不过作为一名开发者,仅仅满足于此显然是不够的。你要知道,Android 还提供了一系列的API,使得我们甚至可以在自己的应用程序里接收和发送短信。也就是说,只要你有足够的信心,完全可以自己实现一个短信应用来替换掉Android 系统自带的短信应用。那么下面我们就来看一看,如何才能在自己的应用程序里接收和发送短信。
接收短信
其实接收短信主要是利用了我们学习过的广播机制。当手机接收到一条短信的时候,系统会发出一条值为android.provider.Telephony.SMS_RECEIVED 的广播,这条广播里携带着与短信相关的所有数据。每个应用程序都可以在广播接收器里对它进行监听,收到广播时再从中解析出短信的内容即可。
让我们通过一个具体的例子来实践一下吧,新建Module,首先修改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="From:" />

        <TextView
            android:id="@+id/sender_tv_main"
            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_tv_maiin"
            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 的实例,如下:

    private TextView sender_tv_main;

    private TextView content_tv_maiin;
```
    sender_tv_main = (TextView) findViewById(R.id.sender_tv_main);
    content_tv_maiin = (TextView) findViewById(R.id.content_tv_maiin);


然后我们需要创建一个广播接收器来接收系统发出的短信广播。在MainActivity 中新建MessageReceiver 内部类继承自BroadcastReceiver,并在onReceive()方法中编写获取短信数据的逻辑,代码如下所示:

    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_tv_main.setText(address);
            content_tv_maiin.setText(fullMessage);
            //abortBroadcast();
        }

    }

可以看到,首先我们从Intent 参数中取出了一个Bundle 对象,然后使用pdu 密钥来提取一个SMS pdus 数组,其中每一个pdu 都表示一条短信消息。接着使用SmsMessage 的createFromPdu()方法将每一个pdu 字节数组转换为SmsMessage 对象,调用这个对象的getOriginatingAddress()方法就可以获取到短信的发送方号码,调用getMessageBody()方法就可以获取到短信的内容,然后将每一个SmsMessage 对象中的短信内容拼接起来,就组成了一条完整的短信。最后将获取到的发送方号码和短信内容显示在TextView 上。完成了MessageReceiver 之后,我们还需要对它进行注册才能让它接收到短信广播,代码如下所示:

    private IntentFilter receiveFilter;

    private MessageReceiver messageReceiver;
```
    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 中的代码,如下所示:

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


当有短信到来时,短信的发送方和内容就会显示在界面上。


完整源代码如下:

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView sender_tv_main;

    private TextView content_tv_maiin;

    private IntentFilter receiveFilter;

    private MessageReceiver messageReceiver;

    private static final String TAG = "MainActivity";

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

        sender_tv_main = (TextView) findViewById(R.id.sender_tv_main);
        content_tv_maiin = (TextView) findViewById(R.id.content_tv_maiin);

        receiveFilter = new IntentFilter();
        receiveFilter.addAction("android.provider.Telephony.SMS_RECEIVED");
        messageReceiver = new MessageReceiver();
        registerReceiver(messageReceiver, receiveFilter);
        //1555 521 5554
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(messageReceiver);
    }

    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_tv_main.setText(address);
            content_tv_maiin.setText(fullMessage);
            //abortBroadcast();
        }

    }
}


还有个坑就是AS中怎么发短信?

Android studio中用了Genymotion模拟器,已经识别到了Device但是DDMS-Emulator Control是灰色的,模拟拨打电话和发送短信不可用(关键词检索)

碰到了这个坑,还以为是端口被占用的情况,但是已经发现设备了啊,已经启动了啊,检查端口没有发现任何问题:

这里附一个检测adb端口的方法:

1:netstat -aon|findstr "5037"  查看占用端口PID情况,5037是adb默认端口

2:tasklist|findstr "2720" 假如占用的PID是2020,那么此条查看的就是此PID对应的应用程序

如果不是adb,那么就到任务管理器中找到这个PID对应的程序,关闭,重启adb即可。

问题情况:

验证:本机AVD manager生成的Android模拟器就可以使用,so,原理就是别人的东西,你来我这里来不一定好使。

别费时间去纠结为啥不能用,他就是不能用。

另外用这个Genymotion生成的模拟器在制作的过程中不知道电话号码是哪个,所以在类似做拨号器应用的时候,无法验证此功能,可以这样:

在模拟器中查看:

设置-关于手机-状态消息-本机号码:我这里看到的是:15555215554,5554就是这个模拟器的号码,前边一大堆数字不用管,取后四位。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值