Android操作短信

本文介绍了在Android 4.4及更高版本中如何处理短信操作。发送短信前需确保应用为默认短信程序。提供了发送短信、读取短信和删除短信的代码示例。还讨论了使用ContentObserver监听短信变化,以及在接收到短信时通过通知栏提醒用户的方式,强调了对于被安全软件拦截的短信监听的局限性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近做的一个项目智能设备项目,应用与设备之间的通信是通过短信实现的。因此在项目中就涉及到短信的拦截、发送、删除以及状态更新等问题。
Android中使用短信功能要配置一些基本的权限:
`<!-- 发送消息 -->
<uses-permission android:name="android.permission.SEND_SMS" />
<!-- 阅读消息 -->
<uses-permission android:name="android.permission.READ_SMS" />
<!-- 写入消息 -->
<uses-permission android:name="android.permission.WRITE_SMS" />
<!-- 接收消息 -->
<uses-permission android:name="android.permission.RECEIVE_SMS" />`
Android4.4上增加了不少安全措施,除了把SELinux设置为enforce外,在短信方向也加强了限制。

4.4之后,新增了一个default sms的机制,应用必须是默认的短信程序才可以收发短信。收发短信之前,先调用
if (!SmsWriteOpUtil.isWriteEnabled(mActivity)) {
SmsWriteOpUtil.setWriteEnabled(
mActivity, true);
}

发送代码:
device_no是目标手机号码,text是发送内容。

SmsManager.getDefault().sendTextMessage(device_no, null, text, null, null);

读取手机中的短信代码:
protocol 0代表短信,1代表彩信;
address 手机号码
body 短信内容
date 短信时间,long整型
_id 短信sqlite数据库中的id,自增
read 是否已读
其它字段百度

private Uri SMS_INBOX = Uri.parse("content://sms/inbox");
String query = WhereBuilder.b("address", "in", targets).and("protocol", "=", "0").toString();
        ContentResolver cr = mActivity.getContentResolver();
        String[] projection = new String[]{"_id", "body", "person", "address", "date"};//"_id", "address", "person",, "date", "type
        Cursor cur = cr.query(SMS_INBOX, projection, query, null, "date desc");

        if (null == cur)
            return;
        while (cur.moveToNext()) {

            String id = cur.getString(cur.getColumnIndex("_id"));
            String number = cur.getString(cur.getColumnIndex("address"));//手机号
            String name = cur.getString(cur.getColumnIndex("person"));//联系人姓名列表
            String body = cur.getString(cur.getColumnIndex("body"));
            long x = cur.getLong(cur.getColumnIndex("date"));
            //String date = DateUtil.formatDate(new Date(x), DateUtil.yyyyMMDD);
        }
        cur.close();

短信删除代码:
result为数据库操作返回的行数。

String where = "_id=" + bean.get_id();
ContentResolver cr = getActivity().getContentResolver();
int result = cr.delete(Uri.parse("content://sms/"), where, null);

更新短信已读状态:

String query = WhereBuilder.b("address", "in", targets).and("protocol", "=", "0").toString();
        ContentResolver cr = getActivity().getContentResolver();
        ContentValues ct = new ContentValues();
        ct.put("read",1);
        cr.update(SMS_INBOX,ct,query,null);

短信监听,当手机接收到短信时,我们要进行一些过滤,是绑定的设备,程序才响应。可以用监听广播的方法来实现。但是这种方法只对新接收到的短信有效,对收件箱中的未读和已读短信无法响应。而且如果一些安全软件对短信进行拦截后,无法接收到广播。一句话,这种方法不推荐。我们可以使用ContentObserver观察者来观察短信数据库,但数据发生改变时,回调做后续处理。
首先继承一个ContentObserver:
targets为绑定的手机号码,因为我们只需要过滤处理这些,其它的短信不管。

class SmsObserver extends ContentObserver {

        public SmsObserver(Context context, Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            String query = WhereBuilder.b("address", "in", targets).and("protocol", "=", "0").and("read","=","0").toString();
            ContentResolver cr = getActivity().getContentResolver();
            String[] projection = new String[]{"_id", "body", "person", "address", "date"};//"_id", "address", "person",, "date", "type"
            Cursor cur = cr.query(SMS_INBOX, projection, query, null, "date desc");

            if (null == cur)
                return;
            while (cur.moveToNext()) {
                String id = cur.getString(cur.getColumnIndex("_id"));
                .....
            }
            cur.close();
            smsHandler.sendEmptyMessage(0);
        }
    }

Handler实现UI操作:
我们在这里使用通知栏提醒,点击通知栏后重新打开应用,最重要的代码是setContentIntent(getDefalutIntent())方法,接着给出

NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getActivity());
                mBuilder.setContentTitle(getString(R.string.app_name))//设置通知栏标题
                        .setContentText(content) //设置通知栏显示内容
                        .setContentIntent(getDefalutIntent(Notification.FLAG_AUTO_CANCEL)) //设置通知栏点击意图
                        //  .setNumber(number) //设置通知集合的数量
                        .setTicker(ticker) //通知首次出现在通知栏,带上升动画效果的
                        .setWhen(System.currentTimeMillis())//通知产生的时间,会在通知信息里显示,一般是系统获取到的时间
                        .setPriority(Notification.PRIORITY_DEFAULT) //设置该通知优先级
                        //  .setAutoCancel(true)//设置这个标志当用户单击面板就可以让通知将自动取消
                        .setOngoing(false)//ture,设置他为一个正在进行的通知。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐)或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)
                        .setDefaults(Notification.DEFAULT_VIBRATE)//向通知添加声音、闪灯和振动效果的最简单、最一致的方式是使用当前的用户默认设置,使用defaults属性,可以组合
                        //Notification.DEFAULT_ALL  Notification.DEFAULT_SOUND 添加声音 // requires VIBRATE permission
                        .setSmallIcon(R.drawable.notify);//设置通知小ICON
                Notification notification = mBuilder.build();
                notification.flags = Notification.FLAG_AUTO_CANCEL;
                mNotificationManager.notify(888, notification);
public PendingIntent getDefalutIntent(int flags){
        Intent intent = new Intent(getActivity(),com.xxxx.MainActivity.class);
        Bundle bundle = new Bundle();
        bundle.putInt(Const.KEY_NOTIFY_OPEN,1);
        intent.putExtras(bundle);
        Context mContext = getApplicationContext();
        PendingIntent contextIntent = PendingIntent.getActivity(mContext, (int)(Math.random()*1000), intent, PendingIntent.FLAG_UPDATE_CURRENT);
        return contextIntent;
    }

MainActivity.class要使用singleTask启动模式,这样应用原来在哪一个页面,在点击通知栏后,都会只进入到MainActivity中。如果app已经被kill掉,MainActivity会进入onCreate方法,重建窗口。如果MainActivity只是onStop(),则会进入onNewIntent(Intent intent),可以从这里获取到intent中的值。
PendingIntent.getActivity是获取一个Activity打开,在一些要做初始化的应用中我们可以用getActivitys()的方法返回Intent[],例如:LoadingActivity->LoginActivity->MainActivity;ApiDemo中也是使用getActivitys来模拟从新打开应用的流程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值