转载本专栏文章,请注明出处,尊重原创 。文章博客地址:道龙的博客
很多应用刚打开的时候,让我们输入手机号,通过短信验证码来登录该应用。那么,这个场景是怎么实现的呢?其实是很多开放平台提供了短信验证功能的接口供我们使用,我们只需要关心客户端,无需关心服务端的业务逻辑,而且更加稳定安全。今天这篇文章就通过Jpush官方的JSMS模块,来实现短信验证登录功能。虽然,Jpush对于极光推送是非常有名出色的,短信验证也是它官网的新内容,不过,多种开放平台使用方式大同小异,而且综合对比,Jpush官网的短信验证使用起来很简单!既然人家给了接口,就来感受一下它的短信验证的实现吧。
首先咱们了解一下短信验证的请求流程:
1.以用户提供的手机号码作为参数,请求连接到JSMS的服务器
2.JSMS服务器校验号码格式成功,请求短信服务商发送短信验证码到该手机号
3.手机终端接收到验证码,用户输入验证码
4.验证码传入应用后台服务端,服务端通过JSMS接口验证,再把验证结果传回手机端
JPush官方地址:/jsms/resources/
进入官网,JSMS模块,官网是这么给出的
短信验证码概述
功能
极光面向开发者提供短信验证码服务,主要包括:
SDK 短信验证功能,满足 App 短信验证需求。REST API 短信验证,主要满足网站和其他终端访问需求。
主要场景
用户注册;登录验证;关键信息修改;支付确认;人员身份有效性确认。
试用步骤
注册成为极光开发者。通过极光后台创建 APP 得到 AppKey(如果之前创建过可以通用)。
官网概述的确言简意赅,我觉得使用图文告知您,可能更贴切一些。看下图:
步骤一 (获取appkey)
1.在极光官网平台上新建短信应用(根据要求包名和应用名称填写好)
2.获取得到Jpush_AppKey。
步骤二 (导入第三方库和so文件)
1.用Android studio打开应用
2.切换应用状态Android为Project状态
3.在libs文件夹下把对应的jar文件拷入 然后as libraries
步骤三(填写配置文件)
1.配置应用权限
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
2.配置meta (appkey 从平台上新建的对应应用中来)
<meta-data android:name="JPUSH_APPKEY" android:value="You JPUSH_APPKEY"/>
步骤四(初始化以及调用)
1.新建Application初始化
public class MyApplication extends Application {@Override public void onCreate() {super.onCreate(); SMSSDK.getInstance().initSdk(this); SMSSDK.getInstance().setIntervalTime(30*1000); }}
接口的意思是:
SMSSDK.getInstance().init(this);
该接口为初始化接口,主要是检测一些配置信息,如果配置错误将会初始化失败,将会打印错误日志。调用其它接口前必须先调用该接口,仅且仅需调用一次,建议在 Application 或初始 Activity 中调用。我这里自定义了一个Applicatiion,这样的话会排除一些可能存在的问题。
SMSSDK.getInstance().setIntervalTime(60000);
设置前后两次获取验证码的时间间隔,默认 30 秒。参数是一个时间间隔,单位是毫秒(ms)
2.在activity中使用
public class CommonSMSActivity extends Activity {private EditText editText; private Button btn; private EditText codeText; private Button signBtn; private TimerTask timerTask; private Timer timer; private int timess; private ProgressDialog progressDialog; @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); progressDialog = new ProgressDialog(this); editText = (EditText) findViewById(R.id.edt_code); codeText = (EditText) findViewById(R.id.edt_write_code); btn = (Button) findViewById(R.id.btn); signBtn = (Button) findViewById(R.id.btn_sign); // 获取验证码 btn.setOnClickListener(new View.OnClickListener() {@Override public void onClick(View v) {String phoneNum = editText.getText().toString();if(TextUtils.isEmpty(phoneNum)){Toast.makeText(CommonSMSActivity.this, "请输入手机号码", Toast.LENGTH_SHORT).show();Log.e("执行", "请输入手机号码!");return;}btn.setClickable(false);// 开始倒计时startTimer();SMSSDK.getInstance().getSmsCodeAsyn(phoneNum, 1+"", new SmscodeListener() {@Overridepublic void getCodeSuccess(final String uuid) {Toast.makeText(CommonSMSActivity.this,uuid,Toast.LENGTH_SHORT).show(); Log.e("执行", "获取验证码成功!");}@Overridepublic void getCodeFail(int errCode, final String errmsg) {//失败后停止计时 stopTimer(); Toast.makeText(CommonSMSActivity.this,errmsg,Toast.LENGTH_SHORT).show(); Log.e("执行", "获取验证码失败,请重新获取!");}}); }}); //开始验证 signBtn.setOnClickListener(new View.OnClickListener() {@Override public void onClick(View v) {String code = codeText.getText().toString();String phoneNum = editText.getText().toString();if(TextUtils.isEmpty(code)){Toast.makeText(CommonSMSActivity.this,"请输入验证码",Toast.LENGTH_SHORT).show();Log.e("执行", "验证前请确保您已经输入验证码了!");return;}if(TextUtils.isEmpty(phoneNum)){Toast.makeText(CommonSMSActivity.this,"请输入手机号码",Toast.LENGTH_SHORT).show();Log.e("执行", "验证前请确保您有输入手机号");return;}progressDialog.setTitle("正在验证...");progressDialog.show();SMSSDK.getInstance().checkSmsCodeAsyn(phoneNum, code, new SmscheckListener() {@Overridepublic void checkCodeSuccess(final String code) {if(progressDialog!=null&&progressDialog.isShowing()){progressDialog.dismiss(); }Toast.makeText(CommonSMSActivity.this,code,Toast.LENGTH_SHORT).show(); Log.e("执行", "验证成功!");}@Overridepublic void checkCodeFail(int errCode, final String errmsg) {if(progressDialog!=null&&progressDialog.isShowing()){progressDialog.dismiss(); }Toast.makeText(CommonSMSActivity.this,errmsg,Toast.LENGTH_SHORT).show(); Log.e("执行", "验证失败!");}}); }}); }//开始计时private void startTimer(){timess = (int) (SMSSDK.getInstance().getIntervalTime()/1000);//获取短信时长 btn.setText(timess+"s"); if(timerTask==null){timerTask = new TimerTask() {//启动task任务@Overridepublic void run() {runOnUiThread(new Runnable() {@Override public void run() {timess--; if(timess<=0){stopTimer();//停止倒计时 return; }btn.setText(timess+"s"); }});}}; }if(timer==null){timer = new Timer(); }timer.schedule(timerTask, 1000, 1000);//每隔1s执行一次任务 }private void stopTimer(){//停止计时if(timer!=null){timer.cancel(); timer=null; }if(timerTask!=null){timerTask.cancel(); timerTask=null; }btn.setText("重新获取"); btn.setClickable(true); }}
这里的代码稍微有点长,核心的API说明一下:
SMSSDK 类:对外的类,该类为单例,调用该类的方法都需要获取该类的唯一实例,获得方法为 SMSSDK.getInstance()。
SmscodeListener:获取验证码的回调接口,在调用 SMSSDK 的 getSmsCode 时需要传入接口实例。
SmscheckListener:检查验证码的回调接口,在调用 SMSSDK 的 checkSmsCode 时需要传入接口实例。
SMSSDK.init(Context context)
接口说明
该接口为初始化接口,主要是检测一些配置信息,如果配置错误将会初始化失败,将会打印错误日志。调用其它接口前必须先调用该接口,仅且仅需调用一次,建议在 Application 或初始 Activity 中调用。
调用示例
SMSSDK.getInstance().init(this);
SMSSDK.getSmsCode(String phone, String tempId, SmscodeListener listener)
接口说明
获取验证码。
该接口是在非 UI 线程回调,需要在 UI 线程回调可调用 SMSSDK.getSmsCodeAsyn()。
参数说明
phone:手机号码tempId:短信模板listener:回调接口调用示例
SMSSDK.getInstance().getSmsCodeAsyn("159xxxxxxxx", "1", new SmscodeListener() {@Overridepublic void getCodeSuccess(final String uuid) {// 获取验证码成功,uuid 为此次获取的唯一标识码。}@Overridepublic void getCodeFail(int errCode, final String errMsg) {// 获取验证码失败 errCode 为错误码,详情请见文档后面的错误码表;errMsg 为错误描述。}});
SMSSDK.checkSmsCode(String phone, String code, SmscheckListener listener)
接口说明
验证码验证接口。
该接口是在非 UI 线程回调,需要在 UI 线程回调可调用 SMSSDK.checkSmsCodeAsyn()。
参数说明
phone:手机号码code:短信验证码listener:回调接口调用示例
SMSSDK.getInstance().checkSmsCodeAsyn("159xxxxxxxx", "123456", new SmscheckListener() {@Overridepublic void checkCodeSuccess(final String code) {// 验证码验证成功,code 为验证码信息。}@Overridepublic void checkCodeFail(int errCode, final String errMsg) {// 验证码验证失败, errCode 为错误码,详情请见文档后面的错误码表;errMsg 为错误描述。}});
SMSSDK.setIntervalTime(long intervalTime)
接口说明
设置前后两次获取验证码的时间间隔,默认 30 秒。
参数说明
intervalTime:时间间隔,单位是毫秒(ms)。调用示例
SMSSDK.getInstance().setIntervalTime(60000); // 设置间隔时间为 60 秒
SMSSDK.getIntervalTime()
接口说明
获取当前设置的时间间隔。
返回值
long:单位为毫秒(ms)。调用示例
SMSSDK.getInstance().getIntervalTime();
我们平时使用短信验证太频繁了,相信上边代码对你来说是soeasy;只不过是做了两个点击事件,然后获取短信以及验证短信交流jsms去处理了,我们并不需要实现业务逻辑。我们额外再做的,也就是启动倒计时任务罢了。
最后再贴上error可能的情况表:
错误码描述
很多人以为已经完成了,其实不然!翻阅了很多有关jsms相关的博客,大家仅仅是给出了怎么使用,罗列了一堆代码。并没有运行截图。也未给出后面遇到问题的解释。不卖关子了,我们发现,上面的代码没有任何错误,运行也能成功。但是,运行发现一直提示no money的错误,并不能接收短信。这是因为我们仅仅是在开放平台集成了人家的功能,并没有作为真正的开发者使用这个功能。那么有什么办法吗?一张图说明一切吧:
如果你是刚刚创建的账号,那么点击这个位置跟我的不一样,最下端会提醒你 “点击联系服务” 大致这个意思。那么你就填写完整个人信息并提交,成功后,就会获得每日20条免费短信的功能。其实,在公司实际开发中不会只给你20条的,到底后边怎么实现,到公司跟你老板商量吧!
最后,我们再来运行一下,看看效果:
我使用的模拟器,短信下发到了我的手机。为了不暴露自己的手机号,就截了下方的验证部分。可以肯定的是,验证登录功能是实现完毕了~
刚才连续发了好几条验证信息。再看看后台数据吧:
JSMS基本使用就介绍这么多,更多功能请参考官方文档。
参考文章:极光推送(短信验证)
Android学习之如何集成极光短信验证
喜欢我的朋友,可以关注我的博客。
也可以打开微信搜索公众号 Android程序员开发指南 或者手机扫描下方二维码 在公众号Android文章。
微信公众号图片:
如果觉得《Android Studio精彩案例(五)《JSMS短信验证码功能实现》》对你有帮助,请点赞、收藏,并留下你的观点哦!