采用动态广播和观察者模式来分别实现验证码自动填写
来源:互联网 发布:mysql max函数 编辑:程序博客网 时间:2024/06/05 14:25
采用动态广播和观察者模式来分别实现验证码自动填写
用户体验是至关重要的,我之前也实现过,就是通过短信广播的形式去监听,但是近期看了一下观察者模式,觉得实现起来也是极好的,那具体怎么做呢?大家跟我一起看下去
这里,我将用两种方式来实现短信自动填写,一种是短信广播,一种是观察者模式
我们再开始之前先定义一下规则,就是我们的短信号码和模板,一般的短信推送,你的服务号码是固定的,当然,也有可能你的量级比较大,所以在全国各地都有,但是我们这里就假设为一般的应用,所以
服务中心号码:6505551212
短信模板:感谢你使用某某应用,你的验证码为:123456!
我们就是要拿到这个验证码,既然如此,那我们开始吧!
一.BroadcastReceiver
既然通过广播来实现,我们首先先把权限给加上,不然你等下忘记了咋办
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
然后你就可以思考了,我这里写了两个控件
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:padding="10dp" android:gravity="center" android:layout_height="match_parent"> <EditText android:id="@+id/et_sms" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/btn_get_code" android:text="获取验证码" android:layout_width="match_parent" android:layout_height="wrap_content" /></LinearLayout>
我这里的逻辑也很简单,只要点击获取验证码的按钮,我就动态注册广播,然后短信广播来了之后拿到短信的内容,去截取短信验证码填入就好了,所以可以看到我们的代码如下
/* *项目名: SmsAutoWriter *包名: com.liuguilin.smsautowriter *文件名: ReceiverActivity *创建者: LGL *创建时间:2017/1/715:34 *描述: 广播监听 */public class ReceiverActivity extends AppCompatActivity { private static final String TAG = "ReceiverActivity"; //短信Action public static final String SMS_ACTION = "android.provider.Telephony.SMS_RECEIVED"; private EditText et_sms; private Button btn_get_code; private SmsReceiver receiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_receiver); initView(); } private void initView() { et_sms = (EditText) findViewById(R.id.et_sms); btn_get_code = (Button) findViewById(R.id.btn_get_code); btn_get_code.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //动态注册广播 receiver = new SmsReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(SMS_ACTION); intentFilter.setPriority(Integer.MAX_VALUE); registerReceiver(receiver,intentFilter); } }); } private class SmsReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Log.i(TAG,"action:" + action); if(SMS_ACTION.equals(action)) { //获取短信内容返回的是一个Object数组 Object[] objs = (Object[]) intent.getExtras().get("pdus"); //遍历数组得到相关数据 for (Object obj : objs) { //把数组元素转换成短信对象 SmsMessage sms = SmsMessage.createFromPdu((byte[]) obj); //发件人 String smsPhone = sms.getOriginatingAddress(); //内容 String smsContent = sms.getMessageBody(); Log.i(TAG, "短信的内容:" + smsPhone + ":" + smsContent); if(smsPhone.equals("6505551212")){ String code = smsContent.substring(17,23); et_sms.setText(code); } } } } } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(receiver); }}
这段代码的逻辑很简单,当我们获取到短信内容直接直接截取就好了,这是在知道短信内容的前提下才行的,也是之前做的,感觉思路不咋滴,而且里面获取验证码,其实我们可用去用正则表达式去解析的,这个我们下文继续讲解,嘿嘿,我们来看下运行演示的效果
恩效果是实现了,那还有没有更加逻辑性的实现方式呢?答案是有的,就是通过观察者模式去实现
二.ContentObserver
我在之前的Rx文章中提到过观察者模式,实际上大部分人还是知道以及使用观察者的
观察者
Observer将自己注册到被观察对象Subject中,被观察者将观察者存放在一个Container容器中被观察者
被观察对象发生某种变化,从容器中得到所有观察过的观察者,将变化通知观察者
理论很简单,我们今天用到的是ContentObserver,有点类似于内容提供者,不过这里是内容观察者,他的主要工作就是观察特定的Uri引起的数据库变化,做出相应的处理,在数据库中,有点类似触发器Trigger,而我们监听短信自动填写,也是用的这个,我们具体去看下代码的实现吧,先来看下我们的Activity
/* *项目名: SmsAutoWriter *包名: com.liuguilin.smsautowriter *文件名: ObserverActivity *创建者: LGL *创建时间:2017/1/715:34 *描述: 观察者模式 */public class ObserverActivity extends AppCompatActivity implements View.OnClickListener { private SmsObserver smsObserver; public Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 1000: String code = (String) msg.obj; et_sms.setText(code); break; } } }; private EditText et_sms; private Button btn_get_code; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_observer); initView(); } private void initView() { et_sms = (EditText) findViewById(R.id.et_sms); btn_get_code = (Button) findViewById(R.id.btn_get_code); btn_get_code.setOnClickListener(this); } @Override protected void onDestroy() { super.onDestroy(); if(smsObserver != null){ getContentResolver().unregisterContentObserver(smsObserver); } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_get_code: if(smsObserver == null){ smsObserver = new SmsObserver(this, handler); } Uri uri = Uri.parse("content://sms"); //注册 getContentResolver().registerContentObserver(uri, true, smsObserver); break; } }}
我在里面,同样是一模一样的控件,一个是输入框,一个是按钮,连理论也是很类似,如果你点击了按钮,我就给你注册,不过现在不是注册广播,而是注册观察者罢了,而在onDestroy中,我把观察者给取消掉了,其实主要的逻辑还是看SmsObserver
/* *项目名: SmsAutoWriter *包名: com.liuguilin.smsautowriter *文件名: SmsObserver *创建者: LGL *创建时间:2017/1/716:04 *描述: 短信 */public class SmsObserver extends ContentObserver{ private static final String TAG = "SmsObserver"; private Context mContext; private Handler handler; private String code = ""; public SmsObserver(Context mContext,Handler handler) { super(handler); this.mContext = mContext; this.handler = handler; } @Override public void onChange(boolean selfChange, Uri uri) { super.onChange(selfChange, uri); Log.i(TAG,"短信有变化:" + uri.toString()); //第一遍没有存储在数据库中 if(uri.toString().equals("content://sms/raw")){ return; } //收件箱 Uri inboxUri = Uri.parse("content://sms/inbox"); Cursor c = mContext.getContentResolver().query(inboxUri,null,null,null,"date desc"); if(c != null){ if(c.moveToFirst()){ String phone = c.getString(c.getColumnIndex("address")); String content = c.getString(c.getColumnIndex("body")); Log.i(TAG,"短信内容:" + phone + ":" + content); //连续6个数字 Pattern pattern = Pattern.compile("(\\d{6})"); Matcher matcher = pattern.matcher(content); if(matcher.find()){ code = matcher.group(0); Log.i(TAG,"验证码:" + code); } handler.obtainMessage(1000,code).sendToTarget(); } c.close(); } }}
这里的逻辑比较多,我们慢慢来说,首先,我们的构造方法传一个上下文,一个handler进来,这个肯定是有需要的参数的,可以不提,继承的是ContentObserver,重写onChange方法这个才是重点,我们监听的就是数据库的这个url发生改变,很明显,我们设置的就是短信的数据库,所以一有短信就会触发这个方法,在这个方法里面,我们做了什么事情呢?首先判断这个url是否等于content://sms/raw,如果是的话,说明短信还没有存入数据库,一般一条短信来了之后会触发两次onChange方法,所以第一次就直接return获取,然后用Cursor 查询收件箱,这个没的说,拿到短信内容之后用正则表达式(\d{6})去获取里面连续6个数字,也就是我们的验证码,这样,通过Handler去更新UI,齐活,这个思路是不是更加的明了而且有效,我们这里要注意下需要添加一个阅读短信的权限
<uses-permission android:name="android.permission.READ_SMS"/>
我们最后跑一遍
OK,到这里,我也说了两种监听的方式,你喜欢用哪种就用哪种咯,如果大家还有其他方式处理的话,欢迎来群里讨论一下哟!
源码下载:http://download.csdn.net/detail/qq_26787115/9731472
加群开车:555974449
- 采用动态广播和观察者模式来分别实现验证码自动填写
- 截取短信验证码,实现自动填写验证码
- 短信验证码自动填写
- 短信验证码自动填写
- Android自动填写验证码
- 短信验证码自动填写
- Android 自动填写验证码
- 短信验证码自动填写
- android获取短信验证码并自动填写的实现
- Android短信验证码自动填写的实现
- Android短信验证码自动填写功能的实现
- Android开发:实现APP自动填写注册验证码功能
- Android开发:实现APP自动填写注册验证码功能
- 利用CursorLoader实现短信验证码自动填写
- 短信验证码自动填写功能的实现
- Android开发:使用AutoInputAuthCode快速实现自动填写验证码
- Android短信验证码自动填写功能的实现
- 快速实现自动填写验证码的功能
- http://blog.csdn.net/huang_cai_yuan/article/details/52927630
- 分布式数据库TIDB
- 欢迎使用CSDN-markdown编辑器
- SVM与LR的比较
- 获取时间的下拉框:
- 采用动态广播和观察者模式来分别实现验证码自动填写
- 手势放大缩小的ImageView,双击放大、还原
- 关于Popupwindow在Activity加载中显示报错问题
- 微信官方再度”发力“
- Android闪屏界面点击跳过
- LocalBroadcastManager
- android contacts数据库简介
- 自动reload nginx解决nginx对动态域名不重新解析的问题
- 在Eclipse下使用Maven开发Spring Boot应用