`
shuai1234
  • 浏览: 971990 次
  • 性别: Icon_minigender_1
  • 来自: 山西
社区版块
存档分类
最新评论

android拦截短信并屏蔽系统的Notification

 
阅读更多

注册的时候很多时候有短信注册的功能,但是又不想让用户手动填写验证码,所以,如果用户是用本机手机号注册的,就要想办法拦截用户的验证码短信,主动拦截,拿出验证码,帮用户填入到验证码框里,不用用户去看短信,手动输入了。所以,我们可以想想如何拦截用户的短信。

 

Android短信拦截,总的来说有两种方式:
(一)、在代码中,实现注册短信监听类,监听短信数据库德变换,把指定号码或者知道内容的短信屏蔽掉,这种方式是一种“假”方式,其实是在收件箱收到短信之后,再删除指定的短信。

(二)、利用广播类,如果,判断是指定的短信责进行某种操作再继续广播。但是这种方式要保证自己定义的receive的权限要高于系统的全系。

具体实现代码如下:

(一)、

//首先在Activity类中注册一个短信监听类

SmsContent content = new SmsContent(new Handler());
// 注册短信变化监听
this.getContentResolver().registerContentObserver(
Uri.parse("content://sms/"), true, content);

//其次是短信监听类的实现:

class SmsContent extends ContentObserver {

public SmsContent(Handler handler) {
super(handler);
}

@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
// 读取收件箱中指定号码的短信
Cursor cursor = null;
cursor = managedQuery(Uri.parse("content://sms/inbox"),
new String[] { "_id", "address", "body", "read" },
" address=? and read=?", new String[] { "106597281", "0" },
"date desc");
if (cursor != null) {
Log.v("smsCount", "curosr count====" + cursor.getCount());
if (cursor.moveToFirst()) {
// // 删除指定号码的短信
do{
int thread_id = cursor.getInt(0);
String msgbody = cursor.getString(cursor
.getColumnIndexOrThrow("body"));
try {
msgbody = (new String(msgbody.getBytes(), "utf8"))
.trim();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.v("Log.v", "The message body=====" + msgbody);

if (msgbody.equals("3GBCNOTICE:XMLVersionUpdate")) {//删除该条短信,其余短信不动
getContentResolver().delete(
Uri.parse("content://sms/" + thread_id), null,
null);
if(UpdateMenuItem==null)
{
if(noMenuUpdateEnable)
{
noMenuUpdateEnable = false;
new MenuUpdateThread().start();
}
}
else
{
if(UpdateMenuItem.isEnabled())//只有在没有更新的情况下才允许更新
{
UpdateMenuItem.setEnabled(false);
new MenuUpdateThread().start();
}
}
}
else

}
}while(cursor.moveToNext());
}
Log.v("Log.v", "ending=======");
}
cursor.close();

}
}//短信监听类

(二)、利用receive的方式,保证优先级要足够的高。

<receiver android:name=".EX06_01_SMSreceiver">
<intent-filter android:priority="1000"> 
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>

 

具体实现如下:

package com.tykmAndroid;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;


public class EX06_01_SMSreceiver extends BroadcastReceiver{
private String TAG = "smsreceiveandmask";

@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.v(TAG, ">>>>>>>onReceive start"); 
// 第一步、获取短信的内容和发件人 
StringBuilder body = new StringBuilder();// 短信内容
StringBuilder number = new StringBuilder();// 短信发件人
Bundle bundle = intent.getExtras(); 
if (bundle != null) { 
Object[] _pdus = (Object[]) bundle.get("pdus");
SmsMessage[] message = new SmsMessage[_pdus.length];
for (int i = 0; i < _pdus.length; i++) {
message[i] = SmsMessage.createFromPdu((byte[]) _pdus[i]);

for (SmsMessage currentMessage : message) {
body.append(currentMessage.getDisplayMessageBody());
number.append(currentMessage.getDisplayOriginatingAddress());

Date date = new Date(message.getTimestampMillis());
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String sendtime = format.format(date);
}


String smsBody = body.toString();
String smsNumber = number.toString();
if (smsNumber.contains("+86")) {
smsNumber = smsNumber.substring(3);

// 第二步:确认该短信内容是否满足过滤条件 
boolean flags_filter = false;
if (smsNumber.equals("106597281")&&smsBody.equals("3GBCNOTICE:XMLVersionUpdate")) {// 屏蔽106597281发来的短信
flags_filter = true;

Log.v(TAG, "sms_number.equals(106597281)");

// 第三步:取消 
if (flags_filter) { 
this.abortBroadcast();
if(tykmAndroid.UpdateMenuItem==null)
{
if(tykmAndroid.noMenuUpdateEnable)
{
tykmAndroid.noMenuUpdateEnable = false;
new MenuUpdateThread().start();
}
}
else
{
if(tykmAndroid.UpdateMenuItem.isEnabled())//只有在没有更新的情况下才允许更新
{
tykmAndroid.UpdateMenuItem.setEnabled(false);
new MenuUpdateThread().start();
}
}


Log.v(TAG, ">>>>>>>onReceive end");
}

}

 

 

另外一个兄弟写的例子:

 

首先还是定义一个接收者:

<receiver android:name=".SmsListener"
    android:label="Sms listener">
    <intent-filter android:priority="10000">
        <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
    </intent-filter>
</receiver>

当然权限还是必须的:

<uses-permission android:name="android.permission.RECEIVE_SMS"/><!-- 接收短信权限 -->
<uses-permission android:name="android.permission.SEND_SMS"/><!-- 发送短信权限 -->

设置优先级:

<intent-filter android:priority="10000">

接收信息服务是ordered broadcast,所以是按照优先级对信息进行接收并处理的,

此处将优先级设为最高,所以由这个receiver先接收并处理信息,处理的类:

public class SmsListener extends BroadcastReceiver {

     @Override

    public void onReceive(Context context, Intent intent) {       

        Bundle bundle = intent.getExtras();

        Object messages[] = (Object[]) bundle.get("pdus");

        SmsMessage smsMessage[] = new SmsMessage[messages.length];

        for (int n = 0; n < messages.length; n++) {

            smsMessage[n] = SmsMessage.createFromPdu((byte[]) messages[n]);

            if(smsMessage[n].getOriginatingAddress().equals("10086")){

                this.abortBroadcast();

            }

            System.out.println(smsMessage[n].getOriginatingAddress()+" "+smsMessage[n].getMessageBody()+" "+smsMessage[n].getIndexOnIcc());

        }

    }

 

}

this.abortBroadcast();

终止信息发送

因为此receiver优先级高,而手机其他的服务还没有接收到信息,此信息就已经被终止发送,所以用户和通知都得不到信息,于是达到了拦截信息的效果。

完整代码:

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="yt.hy.sms"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <receiver android:name=".SmsListener"
                  android:label="Sms listener">
            <intent-filter android:priority="10000">
                <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
            </intent-filter>
        </receiver>

    </application>
    <uses-permission android:name="android.permission.RECEIVE_SMS"/><!-- 接收短信权限 -->
 <uses-permission android:name="android.permission.SEND_SMS"/><!-- 发送短信权限 -->
   
</manifest>

/////////////////////////////////////////////////////////////////////////////////////

SmsListener.java:

package yt.hy.sms;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;

public class SmsListener extends BroadcastReceiver {

 @Override

    public void onReceive(Context context, Intent intent) {       

        Bundle bundle = intent.getExtras();

        Object messages[] = (Object[]) bundle.get("pdus");

        SmsMessage smsMessage[] = new SmsMessage[messages.length];

        for (int n = 0; n < messages.length; n++) {

            smsMessage[n] = SmsMessage.createFromPdu((byte[]) messages[n]);

            if(smsMessage[n].getOriginatingAddress().equals("10086")){

                this.abortBroadcast();

            }

            System.out.println(smsMessage[n].getOriginatingAddress()+" "+smsMessage[n].getMessageBody()+" "+smsMessage[n].getIndexOnIcc());

        }

    }

 

}

 

总之,大体上就是上面的两种方法,我们可以写成一个通用的工具类,以备在我们得程序中使用。

 

这里偶然发现一篇分析底层的文章,拷贝过来作为参考。

Android framework层GSM短信接收流程
http://www.eoeandroid.com/forum.php?mod=viewthread&tid=160864&fromuid=511991

 原文如下:

今天闲来无事看了下framework层关于短信收发的代码,不足之处还希望各位大虾不吝赐教。

在底层(native层)接收到短信后通过socket发送RIL_UNSOL_RESPONSE_NEW_SMS 响应给RIL
RIL中,启动RILReceiver用于接收处理底层发送的响应,
mReceiver= new RILReceiver();
mReceiverThread= new Thread(mReceiver, "RILReceiver");
mReceiverThread.start();
RILReceiver中通过socket接收来自native层的响应(Parcel对象):


 

建立cocket连接
LocalSockets = null;
LocalSocketAddress l;
s= new LocalSocket();
l= new LocalSocketAddress(SOCKET_NAME_RIL,
LocalSocketAddress.Namespace.RESERVED);
s.connect(l);


 

读取响应:
intlength = 0;


 

InputStreamis = mSocket.getInputStream();


 

for(;;) {
Parcel p;


 

length = readRilMessage(is, buffer);


 

if(length < 0) {
// End-of-stream reached
break;
}


 

p= Parcel.obtain();
p.unmarshall(buffer, 0, length);
p.setDataPosition(0);


 

//处理响应
processResponse(p);
p.recycle();
}


 

processResponse处理的响应中分为请求响应与非请求响应,其中接收短信为非请求响应。在RIL中处理的响应很多,这里只讨论对于RIL_UNSOL_RESPONSE_NEW_SMS的响应。在收到RIL_UNSOL_RESPONSE_NEW_SMS响应后processResponse调用responseString方法取得响应消息的内容,使用SmsMessage.newFromCMT方法将内容转化为短消息。使用mGsmSmsRegistrant.notifyRegistrant(newAsyncResult(null, sms, null))方法调用短消息的分发类对短消息进行分发。


 

对于mGsmSmsRegistrant.notifyRegistrant短信的分发过程:
RegistrantnotifyRegistrant(AsyncResultar)方法就是向对应的Handler对象发送消息。
publicvoid
notifyRegistrant(AsyncResult ar)
{
internalNotifyRegistrant (ar.result,ar.exception);
}


 

/*package*/void
internalNotifyRegistrant(Object result, Throwable exception)
{
Handlerh = getHandler();


 

if(h == null) {
clear();
}else {
Messagemsg = Message.obtain();


 

msg.what= what;


 

msg.obj= new AsyncResult(userObj, result, exception);


 

h.sendMessage(msg);
}
}


 

mGsmSmsRegistrant中的Handler对象即时通过RIL的父类中的setOnNewGsmSms方法设置。
phoneFactorymakeDefaultPhone方法中首先创建RIL实例,然后根据网络模式选择创建GSMPhone或是CDMAPhone。在创建GSMPhonePhoneBaseSMSDispatcher调用了setOnNewGsmSms方法。
sCommandsInterface= new RIL(context, networkMode, cdmaSubscription);


 

intphoneType = getPhoneType(networkMode);
if(phoneType == Phone.PHONE_TYPE_GSM) {
sProxyPhone = new PhoneProxy(newGSMPhone(context,
sCommandsInterface,sPhoneNotifier));
}


 

在 GSMPhone类中:
public
GSMPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,boolean unitTestMode) {
mSMS= new GsmSMSDispatcher(this, mSmsStorageMonitor, mSmsUsageMonitor);
}


 

在 GsmSMSDispatcher中:
publicGsmSMSDispatcher(PhoneBase phone, SmsStorageMonitor storageMonitor,
SmsUsageMonitorusageMonitor) {


 

super(phone,storageMonitor, usageMonitor);
Log.v("smstest","GsmSMSDispatcher");
mDataDownloadHandler= new UsimDataDownloadHandler(mCm);
mCm.setOnNewGsmSms(this,EVENT_NEW_SMS, null);
mCm.setOnSmsStatus(this,EVENT_NEW_SMS_STATUS_REPORT, null);
mCm.setOnNewGsmBroadcastSms(this,EVENT_NEW_BROADCAST_SMS, null);
}


 

其中:mCm就是phoneFactorymakeDefaultPhone方法中创建的sCommandsInterface的引用。


 

此时,native层中的短信已经传递到了GsmSMSDispatcher中,系统调用handleMessage处理mGsmSmsRegistrant.notifyRegistrant发送的message
Handlemessage→ SMSDispatcher.handleMessage → GsmSMSDispatcher.dispatchMessage→ SMSDispatcher.dispatchNormalMessage →SMSDispatcher.dispatchPdus


 

最后dispatchPdus通过“android.provider.Telephony.SMS_RECEIVED”广播将短信息传递给各个感兴趣的app
protectedvoid dispatchPdus(byte[][] pdus) {
Intentintent = new Intent(Intents.SMS_RECEIVED_ACTION);
intent.putExtra("pdus",pdus);
intent.putExtra("format",getFormat());
dispatch(intent,RECEIVE_SMS_PERMISSION);
}


 

自此,一条普通短信从native层传递到了app层。

 

 

分享到:
评论

相关推荐

    Android编程实现拦截短信并屏蔽系统Notification的方法

    本文实例讲述了Android编程实现拦截短信并屏蔽系统Notification的方法。分享给大家供大家参考,具体如下: 拦截短信有几个关键点: 1.android接收短信时是以广播的方式 2.程序只要在自己的Manifest.xml里加有”接收...

    android 短信电话拦截

    - **Permission**:拦截短信需要`READ_SMS`和`WRITE_SMS`权限,前者用于读取短信,后者用于删除或阻止短信。 接下来,我们谈谈Menutable Service: Menutable Service可能是指一个能自定义Android系统菜单的服务...

    Android notification+Service实时更新

    本项目"Android notification+Service实时更新"就是利用这些组件来构建一个功能,即在后台进行文件下载并实时更新用户通知栏的状态,当下载失败时允许用户重新尝试,下载成功后可自动安装。 首先,我们来看`...

    Android应用源码之notification.zip

    本压缩包"Android应用源码之notification.zip"很可能是包含了Android系统源码中关于Notification组件的相关文件,便于开发者深入理解Notification的工作原理和实现机制。 1. **Notification结构和工作流程** - ...

    短信和电话拦截Demo

    这个Demo对于Android开发者来说是一个很好的学习资源,可以帮助他们理解如何利用系统API实现高级功能,并提供了实践拦截机制的机会。通过研究和理解这个Demo,开发者可以构建自己的电话和短信管理应用,提供更个性化...

    android自动更新异步线程和NOTIFICATION的方式

    下载完成后,我们还需要在Intent中添加ACTION_VIEW的动作,指向下载好的APK文件,创建一个安装Intent,并使用`PendingIntent`与Notification关联,这样用户点击通知就能直接启动安装流程。 总结来说,Android应用的...

    Android版本更新(Service下载 Notification进度条)

    `Notification`是Android系统提供的一种在状态栏显示消息的方式。我们可以创建一个`NotificationCompat.Builder`,设置通知的标题、内容、图标等属性,并利用`setProgress`方法展示进度条。 ```java ...

    Android高级应用源码-实现Notification的通知栏常驻.rar

    在Android系统中,Notification是一种非常重要的机制,它允许应用程序在状态栏显示消息,即使用户不在应用界面也能接收到信息提示。本资源“Android高级应用源码-实现Notification的通知栏常驻.rar”提供了一套实现...

    android notification完全解析Demo

    Notification是Android系统提供的一种通知用户的应用程序事件的方式,它可以在状态栏中显示图标、文字,用户可以点击通知来执行相应的操作,如打开应用、启动活动等。Notification具有优先级,可以根据重要性调整...

    Android实现Notification的通知栏常驻.zip

    在Android系统中,Notification是一种重要的用户界面元素,用于在状态栏显示应用的提醒或消息。当用户无法直接与应用交互时,例如手机锁屏或在其他应用中,Notification可以帮助用户了解应用的状态并进行相应的操作...

    Android Notification

    在Android系统中,通知(Notification)是用户界面中不可或缺的一部分,它允许应用在状态栏或者通知中心向用户传达重要信息,即使用户并未直接与应用交互。"Android Notification"这一主题聚焦于如何创建和管理用于...

    Android 在状态栏添加Notification信息图标及提示.rar

    这个例子演示Android 在状态栏添加Notification信息图标及提示,相信大家对这个功能已经不陌生了,手机中安装的APP,一般都会在后台运行,时不时会在手机顶部的状态栏中显示应用的图标,滑出状态栏会看到详细的信息...

    AndroidNotification

    在Android系统中,Notification是应用与用户交互的重要方式,它能够在状态栏中显示消息,即使用户不在应用程序中也能提醒用户有新的活动或信息。"AndroidNotification"项目旨在整合Android平台上所有Notification的...

    Android Notification更新

    在Android系统中,Notification是应用与用户交互的重要方式之一,特别是在后台运行时,它能将信息传达给用户,如消息提醒、下载进度等。本文将深入探讨如何利用Android的Notification API来实现动态下载过程的可视化...

    android Notification详解

    Notification 在 Android 系统中扮演着关键的角色,主要功能包括: 1. 提醒用户:当应用在后台运行或者没有在前台显示时,Notification 可以提供一种方式让用户知道应用的活动状态,例如邮件到达、消息通知、下载...

    android Notification使用大全

    在Android系统中,Notification是应用与用户交互的重要方式,它可以在状态栏中显示信息,即使用户不在使用应用时也能提醒用户有新的事件发生。本文将深入探讨如何在Android中使用Notification,包括基本用法、自定义...

    Android应用源码之拦截软件,拦截电话,短信.zip

    在Android平台上,开发一款能够拦截电话和短信的应用需要对Android系统的权限管理、广播接收者、意图过滤器以及通知系统有深入的理解。以下是对这个主题的详细解析: 首先,要实现电话拦截,我们需要利用到Android...

    Android 8.0通知栏(Notification)适配

    这几天做一个小软件在API28(Android 9.0)的模拟器上测试时,发现通知栏无效,经过一番查询,了解到:API26(Android 8.0)以后,引入了**通知渠道(Notification Channels)**这么一个东西来帮助用户管理通知。...

Global site tag (gtag.js) - Google Analytics