Android Studio精彩案例(五)《JSMS短信验证码功能实现》

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

很多应用刚打开的时候,让我们输入手机号,通过短信验证码来登录该应用。那么,这个场景是怎么实现的呢?其实是很多开放平台提供了短信验证功能的接口供我们使用,我们只需要关心客户端,无需关心服务端的业务逻辑,而且更加稳定安全。今天这篇文章就通过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无效的手机号码 
4001body 为空 
4002无效的 AppKey 
4003无效的来源 
4004body 解密失败 
4005aes key 解密失败 
4006时间戳转化失败 
4007body 格式不正确 
4008无效时间戳 
4009没有短信验证权限 
4011发送超频单个设备或同一手机号每天获取验证码次数(默认10次)
4013模板不存在 
4014extra 为空 
4015验证码不正确 
4016没有余额 
4017验证码超时 
4018重复验证 
2993验证码校验失败短信已下发但获取 uuid 异常
2994本地数据有误 
2995数据解析错误 
2996两次请求不超过 1 分钟本地校验
2997未获取验证码 
2998网络错误没有网络等
2999其它错误 


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


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

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


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

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


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

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

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

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

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

微信公众号图片:












  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值