首页 > 代码库 > Android新姿势:如何截取短信

Android新姿势:如何截取短信

公司要做一个【因为是机密所以不能说】的项目,有个需求是拦截手机系统的短信,而且不能在手机的短信应用上显示。


OK,一开始以为不难,网上查了一下资料也发现有人做过,于是就开始写demo,结果才发现,这尼玛就是个大坑啊!!


首先网上查到的最多的实现方案是利用自定义的 BroadcastReceiver 去拦截"android.provider.Telephony.SMS_RECEIVED" 的广播,看起来也不难,于是试了下。发现好坑爹啊!在我的酷派大神上无论怎么样就是拦截不到~

好吧,一定是我写代码的姿势不对,所以又到网上查资料。


嚯嚯嚯,我果然机智~~ 一下子就找到了!原来是我的优先级不够。

安卓的广播是有优先级的,并且动态注册的广播优先级更高。于是参考网上说的,优先级设到2147483647,又弄个动态注册,然后兴奋的用我的酷派再试一次——但还是不行!

详见:http://www.apkbus.com/forum.php?mod=viewthread&tid=53053 


郁闷,难道是我手机的问题?好吧,拿一个同事的2.3安卓机试了一下,还真的可以。。。难道真是手机问题?不行,多拿几台试一下。于是再拿其他同事的手机了一下,也跟我一样。那么大概就可以确定了,是手机系统版本不一样,因为其他同事都是4.0以上的手机。


好吧虽然原因找到,但总得想办法解决是吧?


网上关于拦截短信的资料虽然比较少,不过还是有提到其他的方法的。另一个方法就是监听数据库发生变化时去删除短信的数据。也就是在插入新信息的时候把新信息删了,这样也算是拦截。


网上的资料是注册一个内容提供者监听"content://sms/" 的数据变化,按照他写的代码试了,还是可以监听到数据库变化的。

详见:http://bingtian.iteye.com/blog/641566

但是,在4.0以上系统cursor居然是空的(2.3的手机没问题)!


TUT好坑爹啊!到底毛回事啊! 


好吧,耐心的我又想到另一个onChange(boolean selfChange, Uri uri),这个带Uri参数的方法是高版本的安卓系统上才有的,所以我在这里把uri打印了出来。结果发现打印出来的都是content://sms/910、content://sms/911之类的,根本就没有content://sms/inbox。那么也怪不得cursor是空的!


好吧,既然content://sms/inbox查不到,那我就查你给我的uri吧~


首先把该uri的字段打印出来:

 _id;thread_id;address;m_size;person;date;date_sent;protocol;read;status;type;reply_path_present;subject;body;service_center;locked;sim_id;error_code;seen;ipmsg_id;ref_id;total_len;rec_len;itemInfoid;receive_date;

再跟2.3系统的content://sms/inbox字段对比一下:

_id;thread_id;address;person;date;sc_timestamp;protocol;read;status;type;reply_path_present;subject;body;service_center;locked;error_code;seen;lgeMsgType;lgeSiid;lgeCreated;lgeExpires;lgeReceived;lgeAction;lgeSec;lgeMac;lgeDoc;doInstalled;lgePinRemainCnt;index_on_icc;service_msg_sender_address;modified;modified_time; 

有些字段是不一样的,不过一些主要的字段如_id、address、body还是一样的。

 

那么要拿到短信的内容跟发件人的号码还是没问题的,address就是发件人号码,body是短信内容。试了一下,可以拿到。


比较担心的就是能不能删除掉数据库里的这些短信,不过试了一下还是可以的~


就结果而言还不错——成功的拦截到短信,并把短信删掉了,系统虽然会“叮~”的一声提醒来短信了,但是显示的却不是我刚发的短信,而是我上一次发的(刚发的已经被删了)。


总结:既然不能在这棵树上吊死,就多找几课树试试。

Android新姿势:如何截取短信