转载本专栏文章,请注明出处,尊重原创 。文章博客地址:道龙的博客

很多应用刚打开的时候,让我们输入手机号,通过短信验证码来登录该应用。那么,这个场景是怎么实现的呢?其实是很多开放平台提供了短信验证功能的接口供我们使用,我们只需要关心客户端,无需关心服务端的业务逻辑,而且更加稳定安全。今天这篇文章就通过Jpush官方的JSMS模块,来实现短信验证登录功能。虽然,Jpush对于极光推送是非常有名出色的,短信验证也是它官网的新内容,不过,多种开放平台使用方式大同小异,而且综合对比,Jpush官网的短信验证使用起来很简单!既然人家给了接口,就来感受一下它的短信验证的实现吧。

首先咱们了解一下短信验证的请求流程:

1.以用户提供的手机号码作为参数,请求连接到JSMS的服务器

2.JSMS服务器校验号码格式成功,请求短信服务商发送短信验证码到该手机号

3.手机终端接收到验证码,用户输入验证码

4.验证码传入应用后台服务端,服务端通过JSMS接口验证,再把验证结果传回手机端

JPush官方地址:http://docs.jiguang.cn/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() {                    @Override                    public void getCodeSuccess(final String uuid) {                        Toast.makeText(CommonSMSActivity.this,uuid,Toast.LENGTH_SHORT).show();                        Log.e("执行", "获取验证码成功!");                    }                    @Override                    public 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() {                    @Override                    public void checkCodeSuccess(final String code) {                        if(progressDialog!=null&&progressDialog.isShowing()){                            progressDialog.dismiss();                        }                        Toast.makeText(CommonSMSActivity.this,code,Toast.LENGTH_SHORT).show();                        Log.e("执行", "验证成功!");                    }                    @Override                    public 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任务                @Override                public 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() {    @Override    public void getCodeSuccess(final String uuid) {        // 获取验证码成功,uuid 为此次获取的唯一标识码。    }    @Override    public 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() {    @Override    public void checkCodeSuccess(final String code) {        // 验证码验证成功,code 为验证码信息。    }    @Override    public 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可能的情况表:

错误码描述

错误码 错误码描述 备注
3001 请求超时
3002 无效的手机号码
4001 body 为空
4002 无效的 AppKey
4003 无效的来源
4004 body 解密失败
4005 aes key 解密失败
4006 时间戳转化失败
4007 body 格式不正确
4008 无效时间戳
4009 没有短信验证权限
4011 发送超频 单个设备或同一手机号每天获取验证码次数(默认10次)
4013 模板不存在
4014 extra 为空
4015 验证码不正确
4016 没有余额
4017 验证码超时
4018 重复验证
2993 验证码校验失败 短信已下发但获取 uuid 异常
2994 本地数据有误
2995 数据解析错误
2996 两次请求不超过 1 分钟 本地校验
2997 未获取验证码
2998 网络错误 没有网络等
2999 其它错误


很多人以为已经完成了,其实不然!翻阅了很多有关jsms相关的博客,大家仅仅是给出了怎么使用,罗列了一堆代码。并没有运行截图。也未给出后面遇到问题的解释。不卖关子了,我们发现,上面的代码没有任何错误,运行也能成功。但是,运行发现一直提示no money的错误,并不能接收短信。这是因为我们仅仅是在开放平台集成了人家的功能,并没有作为真正的开发者使用这个功能。那么有什么办法吗?一张图说明一切吧:


如果你是刚刚创建的账号,那么点击这个位置跟我的不一样,最下端会提醒你 “点击联系服务” 大致这个意思。那么你就填写完整个人信息并提交,成功后,就会获得每日20条免费短信的功能。其实,在公司实际开发中不会只给你20条的,到底后边怎么实现,到公司跟你老板商量吧!

最后,我们再来运行一下,看看效果:


我使用的模拟器,短信下发到了我的手机。为了不暴露自己的手机号,就截了下方的验证部分。可以肯定的是,验证登录功能是实现完毕了~

刚才连续发了好几条验证信息。再看看后台数据吧:


JSMS基本使用就介绍这么多,更多功能请参考官方文档。

参考文章:极光推送(短信验证)

Android学习之如何集成极光短信验证

喜欢我的朋友,可以关注我的博客。

也可以打开微信搜索公众号 Android程序员开发指南 或者手机扫描下方二维码 在公众号阅读更多Android文章。

微信公众号图片:












更多相关文章

  1. Android开发之MOB短信验证SDK的使用(二)
  2. Android常见管理器—短信管理器 SmsManager(一)
  3. Android调用百度地图Web端接口,实现百度定位、导航
  4. 避免在Java接口中使用数组的3个理由
  5. 【Java笔记】——抽象类和接口
  6. C#/Java 调用WSDL接口及方法
  7. 第三部分:Android 应用程序接口指南---第二节:UI---第六章 对话框
  8. Android两种方式监听短信内容---BroadcastReceiver和ContentObse
  9. sc7731 Android 5.1 Camera 学习之二 framework 到 HAL接口整理

随机推荐

  1. 传播智客ASP.NET基础系列视频资料分享
  2. 传播智客ASP.NET中级系列视频视频资料
  3. 传播智客ASP.NET高级系列视频资料分享
  4. 总结.NET如何获取当前路径的方法
  5. asp保存二进制图片到access数据库
  6. ASP.NET MVC对异常处理的解决方法汇总
  7. C++开发中国象棋游戏的资源下载(视频、课
  8. Asp.Net MVC实现分页、检索、排序的代码
  9. asp如何解析json字符串并转化为asp对象
  10. asp读取excel表格第x行第y列值