Android短信过滤项目中的观察者模式

时间:2023-11-24 23:46:02

观察者模式:

观察者模式定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

观察者模式提供了一种对象设计, 让主题和观察者之间松耦合。主题只知道观察者实现了某个接口(也就是Observer接口)。主题不需要知道观察者的具体类是谁、做了些什么或其他任何细节。任何时候我们都可以增加新的观察者。因为主题唯一依赖的东西是一个实现Observer接口的对象列表,所以我们可以随时增加观察者。同样我们也可以删除观察者。有新类型的观察者出现时,主题的代码不需要修改。它只会发送通知给所有实现了观察者接口的对象。

项目的Gihub地址:

https://github.com/Robin-jiangyufeng/SmsObserverForAndroid

这是一个用于拦截android实时短信的库,可以进行短信过滤,得到自己想要的内容,可以用于需要自动填写短信验证码的app项目。

该项目可以用于监听当前接收到的短信信息,并过滤接收到的短信,得到自己想要的内容,还可以用于发送短信验证码。

首先看一下程序使用的基类:

https://github.com/Robin-jiangyufeng/SmsObserverForAndroid/tree/master/SmsObserverLibrary/src/main/java/com/robin/lazy/sms

这个目录下有几个基类:

Android短信过滤项目中的观察者模式

SmsFilter.java是一个过滤器接口,定义了一个过滤的抽象方法filter()。

public interface SmsFilter {

    /***
* 过滤方法
* @param address 发信人
* @param smsContent 短信内容
* @return 过滤处理后的短信信息
*/
String filter(String address,String smsContent);
}

DefaultSmsFilter.java是一个SmsFilter接口的具体实现子类,实现了filter方法()。

public class DefaultSmsFilter implements SmsFilter{

    @Override
public String filter(String address, String smsContent) {
return smsContent;
}
}

SmsHandler是一个Handler的子类,类内部定义了两个构造方法SmsHandler(),然后定义了一个设置过滤器的方法setSmsFilter(),最后覆写了父类Handler的handleMessage()方法,目的是加入自己写的过滤器来有选择地处理信息。

public class SmsHandler extends Handler {

    private SmsResponseCallback mCallback;

    /***
* 短信过滤器
*/
private SmsFilter smsFilter; public SmsHandler(SmsResponseCallback callback) {
this.mCallback = callback;
} public SmsHandler(SmsResponseCallback callback, SmsFilter smsFilter) {
this(callback);
this.smsFilter = smsFilter;
} /***
* 设置短信过滤器
* @param smsFilter 短信过滤器
*/
public void setSmsFilter(SmsFilter smsFilter) {
this.smsFilter = smsFilter;
} @Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == SmsObserver.MSG_RECEIVED_CODE) {
String[] smsInfos = (String[]) msg.obj;
if (smsInfos != null && smsInfos.length == 2 && mCallback != null) {
if (smsFilter == null) {
smsFilter = new DefaultSmsFilter();
}
mCallback.onCallbackSmsContent(smsFilter.filter(smsInfos[0], smsInfos[1]));
}
}
}
}

SmsResponseCallback.java类负责发出通知(这里具体来说就是针对过滤器过滤后的短信进行不同的通知,比如合规的短信将进行自动回复,后面主活动中覆写了这个方法)

public interface SmsResponseCallback {

    /**
* 返回短信内容
*
* @param smsContent
* @see [类、类#方法、类#成员]
*/
void onCallbackSmsContent(String smsContent);
}

VerificationCodeSmsFilter.java类是另一个过滤器子类,负责过滤要给哪些人发送短信。

public class VerificationCodeSmsFilter implements SmsFilter {
/**
* 需要过滤的发短信的人
*/
private String filterAddress; public VerificationCodeSmsFilter(String filterAddress) {
this.filterAddress = filterAddress;
} @Override
public String filter(String address, String smsContent) {
if (address.startsWith(filterAddress)) {
Pattern pattern = Pattern.compile("(\\d{4,8})");//匹配4-8位的数字
Matcher matcher = pattern.matcher(smsContent);
if (matcher.find()) {
return matcher.group(0);
}
}
return null;
}
}

SmsObserver.java是一个观察者类,定义了观察者的一系列方法。

https://github.com/Robin-jiangyufeng/SmsObserverForAndroid/blob/master/SmsObserverLibrary/src/main/java/com/robin/lazy/sms/SmsObserver.java

先设置了三个不同的构造方法:

public SmsObserver(Activity context, SmsResponseCallback callback,SmsFilter smsFilter) {
this(new SmsHandler(callback,smsFilter));
this.mContext = context;
} public SmsObserver(Activity context, SmsResponseCallback callback) {
this(new SmsHandler(callback));
this.mContext = context;
} public SmsObserver(SmsHandler handler) {
super(handler);
this.mHandler = handler;
}

设置一个短信过滤的方法:

 public void setSmsFilter(SmsFilter smsFilter) {
mHandler.setSmsFilter(smsFilter);
}

注册一个短信观察者的方法:

public void registerSMSObserver() {
Uri uri = Uri.parse("content://sms");
if (mContext != null) {
mContext.getContentResolver().registerContentObserver(uri,
true, this);
}
}

删除一个短信观察者的方法:

public void unregisterSMSObserver() {
if (mContext != null) {
mContext.getContentResolver().unregisterContentObserver(this);
}
if (mHandler != null) {
mHandler = null;
}
}

设置状态变化并发出通知的方法:

@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
if (uri.toString().equals("content://sms/raw")) {
return;
}
Uri inboxUri = Uri.parse("content://sms/inbox");//收件箱
try {
Cursor c = mContext.getContentResolver().query(inboxUri, null, null,
null, "date desc");
if (c != null) {
if (c.moveToFirst()) {
String address = c.getString(c.getColumnIndex("address"));
String body = c.getString(c.getColumnIndex("body"));
if (mHandler != null) {
mHandler.obtainMessage(MSG_RECEIVED_CODE, new String[]{address, body})
.sendToTarget();
}
Log.i(getClass().getName(), "发件人为:" + address + " " + "短信内容为:" + body);
}
c.close();
}
} catch (SecurityException e) {
Log.e(getClass().getName(), "获取短信权限失败", e);
} catch (Exception e) {
e.printStackTrace();
}
}

主活动类MainActivity.java:

https://github.com/Robin-jiangyufeng/SmsObserverForAndroid/blob/master/Sample/src/main/java/com/robin/lazy/sample/MainActivity.java

主活动中,先创建一个观察者smsObserver并注册到主题中,在注册以后,短信观察者就已经启动短信变化监听,接下只要接收短信,对短信做处理就可以了。

定义一个TextView类型的变量textView, 并实例化。用来显示你想显示的内容,内容可以用setTEXT()方法来设置。

Dexter.checkPermission(new CompositePermissionListener(), Manifest.permission.READ_SMS)为请求权限方法,new CompositePermissionListener()为处理权限请求的回调接口,Manifest.permission.READ_SMS为请求的权限,即读取短信。

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
smsObserver=new SmsObserver(this,this,new VerificationCodeSmsFilter("180"));
smsObserver.registerSMSObserver();
textView=(TextView)findViewById(R.id.textView);
Dexter.checkPermission(new CompositePermissionListener(), Manifest.permission.READ_SMS);
}

覆写了onCallbackSmsContent()方法,即修改自动回复的短信的内容:

public void onCallbackSmsContent(String code) {
textView.setText("短信验证码:"+code);
}