App读取短信实现

应用中通常会涉及到读取短信,下面通过自动获取短信验证码演示了如何在应用中读取短信。

权限

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

通过广播监听短信

注意:这种方式只有在新接收到消息的时候才会执行代码,并不会读取收件箱中已读或未读的消息。

class SmsReceiver extends BroadcastReceiver {
    private OnSmsCatchListener mCallback;
    private String mPhoneNumber;
    private String mFilterRegex;

    public void setCallback(OnSmsCatchListener<String> callback) {
        this.mCallback = callback;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        final Bundle bundle = intent.getExtras();
        try {
            if (bundle != null) {
                final Object[] pdusObj = (Object[]) bundle.get("pdus");
                for (int i = 0; i < pdusObj.length; i++) {
                    SmsMessage currentMessage = getIncomingMessage(pdusObj[i], bundle);
                    String phoneNumber = currentMessage.getDisplayOriginatingAddress();

                    if (mPhoneNumber != null && !mPhoneNumber.equals(phoneNumber)) {
                        return;
                    }

                    String message = currentMessage.getDisplayMessageBody();
                    if (mFilterRegex != null && !message.matches(mFilterRegex)) {
                        return;
                    }

                    if (mCallback != null) {
                        mCallback.onSmsCatch(message);
                    }
                }
            }

        } catch (Exception e) {
        }
    }

    private SmsMessage getIncomingMessage(Object aObject, Bundle bundle) {
        SmsMessage currentSMS;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            String format = bundle.getString("format");
            currentSMS = SmsMessage.createFromPdu((byte[]) aObject, format);
        } else {
            currentSMS = SmsMessage.createFromPdu((byte[]) aObject);
        }
        return currentSMS;
    }


    public void setPhoneNumber(String phoneNumber) {
        this.mPhoneNumber = phoneNumber;
    }

    public void setFilterRegex(String regex) {
        this.mFilterRegex = regex;
    }

    public interface OnSmsCatchListener {
        void onSmsCatch(String message);
    }
}

接下来注册广播:

SmsReceiver receiver = new SmsReceiver();
receiver.setCallback(onSmsCatchListener);
receiver.setPhoneNumber(phoneNumber);
receiver.setFilterRegex(regex);
IntentFilter filter = new IntentFilter();
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
activity.registerReceiver(receiver, filter);

最后在onStop/onDestroy中取消注册:activity.unregisterReceiver(receiver)。

注意:系统这个广播是有序广播,当其他应用程序先获取到了这个广播再传递给你,如果广播在其他应用程序中被注销了就接收不到了。通过设置priority的数值,其实有时是不管用的,现在在一些定制的系统或是有安全软件的情况下,短信往往都会被截取并注销掉广播监听。

通过ContentObserver监听短信

注意:这种方式可以获取手机上所有的短信,包括已读未读的短信

public class SmsObserver extends ContentObserver {

    private OnSmsCatchListener mCatchListener;
    private String mPhoneNumberFilter;
    private String mSmsCatchRegex;
    private WeakReference<Activity> mActivityRef;

    public void setCallback(OnSmsCatchListener listener) {
        this.mCatchListener = listener;
    }

    public SmsObserver(Activity activity, Handler handler) {
        super(handler);
        mActivityRef = new WeakReference<Activity>(activity);
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);

        if (null == mCatchListener || null == mActivityRef.get()) {
            return;
        }

        Cursor cursor = null;
        try {
            final Uri uri = Uri.parse("content://sms/");
            final String[] projection = new String[]{"address", "body"};
            cursor = mActivityRef.get().getContentResolver().query(uri, projection, "read=?", new String[]{"0"}, "date desc");
            if (cursor.moveToFirst()) {
                do {
                    final String address = cursor.getString(cursor.getColumnIndex("address"));
                    if (!TextUtils.isEmpty(mPhoneNumberFilter) && !mPhoneNumberFilter.equals(address)) {
                        Pattern p = Pattern.compile(mPhoneNumberFilter);
                        Matcher m = p.matcher(address);
                        if (!m.matches()) {
                            return;
                        }
                    }

                    final String message = cursor.getString(cursor.getColumnIndex("body"));
                    if (!TextUtils.isEmpty(mSmsCatchRegex)) {
                        Pattern p = Pattern.compile(mSmsCatchRegex);
                        Matcher m = p.matcher(message);
                        if (m.find()) {
                            mCatchListener.onSmsCatch(m.group(0));
                            return;
                        }
                    }
                } while (cursor.moveToNext());
            }
        } catch (Exception e) {
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }

    /**
     * 手机号码过滤
     *
     * @param filter 手机号或者手机号正则表达式
     */
    public void setPhoneNumberFilter(String filter) {
        this.mPhoneNumberFilter = filter;
    }

    public void setSmsCatchRegex(String regex) {
        this.mSmsCatchRegex = regex;
    }
}

然后通过getContentResolver().registerContentObserver(Uri.parse(“content://sms/”), true, mSmsObserver)注册监听。

最后通过getContentResolver().unregisterContentObserver(mSmsObserver)注销监听。

SMS结构

字段描述值域/例子
_id短消息序号
thread_id对话的序号
address发件人地址,手机号
person发件人,返回一个数字就是联系人列表里的序号,陌生人为空
date消息接收日期,long型
date_sent消息发送日期,long型
protocol协议SMS_RPOTO = 0
MMS_PROTO = 1
read是否阅读未读 = 0
已读 = 1
status状态STATUS_NONE = -1
STATUS_COMPLETE = 0
STATUS_PENDING = 64
STATUS_FAILED = 128
type消息的类型MESSAGE_TYPE_ALL = 0
MESSAGE_TYPE_INBOX = 1
MESSAGE_TYPE_SENT = 2
MESSAGE_TYPE_DRAFT = 3
MESSAGE_TYPE_OUTBOX = 4
MESSAGE_TYPE_FAILED = 5
MESSAGE_TYPE_QUEUED = 6
reply_path_present消息上是否设置了TP-Reply-Path位
subject消息的主题,如果存在
body消息内容
service_center短信服务中心号码编号+8613800755500
locked消息是否被锁定
error_code与发送或接收此消息相关的错误代码
seen指示该消息是否已被用户看到。该标志将用于确定是否需要弹出状态栏通知
timed
deleted
sync_state
marker
source
bind_id
mx_status
mx_id
out_time
account
sim_id
block_type
advanced_seen
b2c_ttl
b2c_numbers
fake_cell_type
url_risky_type

关于权限问题

android6.0(API23)以后读取短信权限必须在运行时申请。

感谢大家的支持,如有错误请指正,如需转载请标明原文出处!

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于app开发与实现,是指通过应用程序开发和实施技术来创建和推出一个移动应用程序。在移动设备普及的时代,app已成为人们生活和工作中不可或缺的一部分。 首先,基于app开发与实现需要一个团队来完成,包括设计师、开发人员、测试人员和项目经理等。设计师负责制定用户界面和用户体验,开发人员则负责编写应用程序的代码,测试人员进行功能和质量测试,项目经理则负责协调和管理整个开发过程。 其次,基于app开发与实现需要选定一个适当的开发平台。目前市场上有多种开发平台可供选择,如Android和iOS等。开发人员需要根据项目要求和目标用户的设备偏好选择合适的开发平台。 然后,基于app开发与实现需要确定应用程序的功能和特性。在开发过程中,团队需要与客户合作,了解他们的需求和预期,然后根据需求来确定应用程序的功能和特性,例如登录注册、浏览商品、下单和支付等。 最后,基于app开发与实现需要进行测试和发布。在应用程序开发完成后,测试人员会对应用程序进行回归测试和性能测试,确保其功能和质量符合预期。一旦测试通过,团队将准备应用程序的发布,通过应用商店或其他渠道向用户推出。 基于app开发与实现是一个综合性的过程,需要团队的协作和各个环节的衔接。通过合理的设计和开发,可以实现一个功能完备、易用且满足用户需求的移动应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值