在应用的开发过程中 我们需要向用户发送验证码以验证用户的身份,但是用户收到短信验证码后,需要离开当前的应用去查看验证码,然后再返回我们的应用来填写验证码,这样会给用户带来诸多的不便。android系统上的应用可以读取到手机上的短信,我们可以通过这个特性去获取我们想要的内容,显示到我们的输入框中。
本次我们实现的功能要用到ContentObserver,当我们发送一条短信到我们的手机上时,手机会自动调用ContentObserver类中的指定方法,来通知我们的应用短信内容的改变,我们提取内容中的信息 填写到我们的输入框中
在这里我和大家说一个与之相关的设计模式:观察者模式:
观察者模式是软件设计模式中的一种,在此模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常是透过呼叫各观察者所提供的方法来实现。此模式通常被用来实现时间处理系统。
观察者模式(Observer)完美的将观察者和被观察者的对象分离开,在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。
观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。
应用到我们的这个例子上来说,就是首先我们在我们的应用刚开始运行的过程中,向我们的系统短信应用注册一个观察者,就告诉我们的短信应用说,我是你的观察者,当你自己的状态发生了变化后,你就通知我。
我们来看一下观察者的基本流程:
观察者将自己注册到被观察对象(subject)中,被观察者对象将观察者存放在一个容器(Container)里。
被观察者对象发生变化,从容器中得到所有注册过的观察者,将变化通知观察者。
观察者告诉观察者要撤销观察,被观察者从容器中将观察者去除。
接下来说下ContentObservber类
ContentObserver
内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentOberver所观察的Uri发生变化时,便会触发它。
观察特定Uri的步骤如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <EditText android:ems="10" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/et_validateCode" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" /> </RelativeLayout>创建一个ContentObserver的派生类 去实现获取到短信的一些功能实现
public class SmsObserver extends ContentObserver { private static final String TAG = SmsObserver.class.getSimpleName(); private Context mContext; private Handler mHandler; public SmsObserver(Context mContext, Handler handler) { super(handler); this.mContext = mContext; this.mHandler = handler; } @Override public void onChange(boolean selfChange, Uri uri) { super.onChange(selfChange, uri); Log.e(TAG, "sms has changed !"); Log.e(TAG, uri.toString()); String code = ""; 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 address = c.getString(c.getColumnIndex("address")); String body = c.getString(c.getColumnIndex("body")); Log.e(TAG, "发件人为:" + address + "" + "内容为:" + body); Pattern pattern = Pattern.compile("\\d{6}"); Matcher matcher = pattern.matcher(body); if (matcher.find()) { code = matcher.group(0); Log.e(TAG, "code is " + code); mHandler.obtainMessage(1, code).sendToTarget(); } } c.close(); } } }
public class SmsActivity extends Activity{ private SmsObserver observer; private EditText et_validateCode; private Handler mHadler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what==1){ String code= (String) msg.obj; //update the ui et_validateCode.setText(code); } } }; @Override protected void onPause() { super.onPause(); getContentResolver().unregisterContentObserver(observer); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sms); et_validateCode= (EditText) findViewById(R.id.et_validateCode); observer=new SmsObserver(SmsActivity.this,mHadler); Uri uri=Uri.parse("content://sms"); getContentResolver().registerContentObserver(uri,true,observer); } }