项目需求介绍:
由于我们在短代支付中需要通过运营商的途径扣费,而扣费后运营商会给用户发送扣费短信,但是!!由于不同的游戏需要使用同一款短代支付代码(运营商有控制,不会很多,很多游戏只能使用其他游戏的短代代码)的东西,所以,我们需要拦截这个不符合游戏产品的短信,防止用户大量投诉!
项目解决思路:
为了用户安全性的提高,谷歌在短信上也做了安全工作!所以就需要不同的方式拦截短信!
方案1:
适用场景:4.4以下Android系统
通过设置高优先级的广播来处理,在短信广播发送过来时,我们通过查看短信的内容,
判断我们是否要拦截短信:
/**
* 开始拦截短信
*
* @param context 上下文对象
* @param address 拦截特定地址的短信
* @param keyWord 拦截特定关键字的短信
*/
public static void interceptSMS(final Contextcontext, final String address, final String keyWord) {
broadcastReceiver= new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//第一步、获取短信的内容和发件人
StringBuilderbody = new StringBuilder();// 短信内容
StringBuildernumber = new StringBuilder();// 短信发件人
Bundlebundle = 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]);
}
number.append(message[0].getDisplayOriginatingAddress());
for (SmsMessage currentMessage : message) {
body.append(currentMessage.getDisplayMessageBody());
}
String smsBody =body.toString();
String smsNumber =number.toString();
if (smsNumber.contains("+86")) {
smsNumber = smsNumber.substring(3, smsNumber.length() - 1);
}
// 第二步:确认该短信内容是否满足过滤条件
boolean flags_filter= false;
if (smsNumber.equals(address)|| smsBody.contains(keyWord)) {// 屏蔽特定手机号发来的短信
flags_filter = true;
}
// 第三步:取消广播
if (flags_filter) {
this.abortBroadcast();
//提醒代码 后期删除掉
/*NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setContentTitle("拦截短信").setContentText("拦截手机号为:" + smsNumber + "内容" + smsBody).setSmallIcon(R.mipmap.ic_launcher);
builder.setDefaults(NotificationCompat.DEFAULT_LIGHTS);
Notificationnotification = builder.build();
NotificationManagermanager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(666,notification);*/
}
}
}
};
IntentFilter filter = new IntentFilter(SMS_ACTION);
filter.setPriority(Integer.MAX_VALUE);
context.registerReceiver(broadcastReceiver, filter);
}
方案二:
适用场景:4.4以下Android系统
通过注册短信内容的观察者,当短信内容发生变化时,删除掉特定的短信、
测试中出现的问题:
测试机型: 小米2s
1:在删除后 系统短信 界面依旧出现短信提示 1 的问题 (无法解决)
2:在删除过程中,由于onChange()会调用两次,有时会删除两个短信(如果这两个短信一个是最近刚打算拦截的,一个是刚不需要拦截的),有时不会(只有最近刚打算拦截的),
解决方法
问题2 这种问题可以解决,就是加一个变量出来,每次调用时判断短信时间与变量是否相同,相同时不掉用,不同是调用,然后给变量赋值为刚才的时间,这样就可以保证每次处理短信处理一次
/**
* 短信内容变化监听
* 现在做的事 特定的地址处理包含特定关键字的短信
*
* @param context 上下文对象
* @param address 拦截地址
* @param keyWord 拦截消息
* @param smsObserver接口回调对象
*/
public static void observerSMS(final Context context, @NonNull final String address, @NonNull final String keyWord, final SMSObserver smsObserver) {
ContentObserver observer = new ContentObserver(new Handler()) {
private String date = "";
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
String myaddress = "";
String body = "";
String mydate = "";
ContentResolver resolver = context.getContentResolver();
Cursor cursor =resolver.query(Uri.parse("content://sms/inbox"), new String[]{"_id", "address", "body", "date"}, null, null, null);
long id = -1;
if (cursor.getCount()> 0 &&cursor.moveToFirst()) {
id = cursor.getLong(0);
myaddress =cursor.getString(1);
body = cursor.getString(2);
mydate =cursor.getString(3);
}
cursor.close();
if (myaddress.equals(address) &&body.contains(keyWord) && !mydate.equals(date)) {
smsObserver.onOperate();
date = mydate;
}
}
};
context.getContentResolver().registerContentObserver(Uri.parse("content://sms/"), true, observer);
}
/**
* 短信变化回掉接口
*/
public interface SMSObserver {
voidonOperate();
}
方案3:
适用场景:4.4以上Android系统
4.4之后我们就不能通过拦截广播的方式拦截短信了,也不能直接删除短信,但是我们可以通过成为default sms 来做短信拦截,像腾讯管家之类的就是这样做的
如果就这样的需求可以查看如何做。。
但是在游戏产品中是不可能让我们的app成为default sms的
最终解决思路:在低版本的情况下,使用广播的拦截方式,在高版本的情况下,只能给予提示或者不提示。。