Android操作短信

来源:互联网 发布:食药局数据查询 编辑:程序博客网 时间:2024/06/05 12:51
最近做的一个项目智能设备项目,应用与设备之间的通信是通过短信实现的。因此在项目中就涉及到短信的拦截、发送、删除以及状态更新等问题。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来模拟从新打开应用的流程。

0 0
原创粉丝点击