Android自动填写验证码
第四篇博客就来总结下项目中使用到的一个提升用户体验的功能: Android自动填写验证码
从字面上来看,很明显的可以看出它的实现流程:监听->有改变->获取信息->改变ui
观察者模式
观察者模式是软件设计模式中的一种,在此模式中,一个目标物件管理所有相依于它的观察者物件,并且在本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统
观察者模式Observer完美的将观察者和被观察的对象分离开,在模块之间划定接线,提高应用程序的可维护性和重用性。同时定义了对象间一种一对多的以来关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。
观察者:Observer将自己注册到被观察对象中,被观察对象将观察者存放在一个容器里
被观察:当被观察者对象发生了某种变化,从容器中得到所有注册过的观察者,将变化通知观察者
撤销观察:观察者告诉被观察者要撤销观察,被观察者从容器中将观察者去除
ContentObserver
内容观察者,目的是观察捕捉特定uri引起的数据库的变化,继而做一些相应的处理,类似于数据库中的触发器。
流程如下:
1. 创建ContentObserver派生类,重载onChange()方法处理回调。
2. 利用context.getContentResolover() 获得ContentResolove对象,调用registerContentObserver()方法去注册
3. 在不需要使用时(例如验证码获取成功后),调用unregisterContentObserver()取消注册
实现
在我们创建的SmsObserver类中,必须要实现onChange方法,这是一个检测uri是否变化的方法。
而验证短信发来的时候,会调用两次,第一次的uri会提示raw,此时只是表示短信到了,还没有写入数据库中。而第二次变化的时候才是我们需要接收与检测的,此时才表示短信已经被写入了数据库中。
而对于相关验证码的提取,使用正则表达式的方式,获取连续的4个数字(根据自己的需要)。
另外,在AndroidManifest文件中添加Read_SMS的权限
相关代码如下:
package com.screform.mmd.customview;import android.content.Context;import android.database.ContentObserver;import android.database.Cursor;import android.net.Uri;import android.os.Handler;import android.util.Log;import com.screform.mmd.aty.Aty_Register;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * Created by lizhongquan on 15-11-18. * Class to Observer the sms and notify to setText in editText_IdentifyingCode */public class SmsObserver extends ContentObserver { private Context context; private Handler handler; /** * Creates a content observer. * * @param handler The handler to run {@link #onChange} on, or null if none. */ public SmsObserver(Context context, Handler handler) { super(handler); this.context = context; this.handler = handler; } /** * code ChangeListener * * @param selfChange change or not * @param uri the uri of event */ @Override public void onChange(boolean selfChange, Uri uri) { super.onChange(selfChange, uri); Log.d("info", "SMS is changed"); Log.d("info", uri.toString()); // When the sms is coming, it will be change twice. // the first time change is not the one we need. // The sms is not writed into the database in this time if (uri.toString().equals("content://sms/raw")) { return; } // handle the second change // get the inboxUri Uri inboxUri = Uri.parse("content://sms/inbox"); // query the inbox // get the sms Cursor mCursor = context.getContentResolver().query(inboxUri, null, null, null, "date desc"); if (null != mCursor) { if (mCursor.moveToFirst()) { String address = mCursor.getString(mCursor.getColumnIndex("address")); String body = mCursor.getString(mCursor.getColumnIndex("body")); Log.d("info", "address is :" + address + ", body is " + body); if (address.equals("106900321100")) { // use a regular expression to resolve and get the identifying code // get the four consecutive numbers Pattern pattern = Pattern.compile("(\\d{4})"); Matcher matcher = pattern.matcher(body); if (matcher.find()){ Log.d("info", "Identifying code is " + matcher.group(0)); handler.obtainMessage(Aty_Register.GETSMS, matcher.group(0)) .sendToTarget(); } } } } // close mCursor mCursor.close(); }}
在Aty_Register.java中:
initObserver():
Uri uri = Uri.parse("content://sms"); smsObserver = new SmsObserver(Aty_Register.this, handler); getContentResolver().registerContentObserver(uri, true, smsObserver);
onStop()中: 取消注册
@Override protected void onStop() { super.onStop(); getContentResolver().unregisterContentObserver(smsObserver); Log.d("info", "unregister"); }
handler中: 更新UI
case GETSMS: editText_IdentifyingCode.setText(msg.obj.toString()); break;
AndroidManifest:
<uses-permission android:name="android.permission.READ_SMS" />
更多相关文章
- No.11 使用firewall配置的防火墙策略的生效模式
- Android(安卓)四大组件之Activity
- Android(安卓)避免重复提交
- 调用对象[置顶] Android通过调用Webservice实现天气预报
- Android窗口管理服务WindowManagerService对窗口的组织方式分析
- Android艺术探索读书笔记 -IPC机制
- Android(安卓)MTP框架和流程分析
- Android内存泄露浅析
- Android(安卓)中内存泄漏的原因分析及解决方案