快速解决Android使用Mob实现短信验证服务

自己的项目遇到需要使用短信验证的功能,要改原来的登录注册,真是头疼。害,经过一番苦寻在网上找到了使用Mob进行短信验证,为什么呢

第一 ,它免费, 哈哈,这无疑是开发者的福音

第二,他的效果,正如它官网写到几乎百分比收到短信

于是去网上看了很多篇博客对于SDK使用的介绍。因为比较懒,只想找到一个框架直接把自己逻辑写回调里哈哈,还真让我找到了,可惜的是,看完介绍,它竟然源码收费,6块钱,算了 ,不如买杯奶茶,于是,我决定自己封装一个框架提供给像我一样白嫖的人,^^。我是可爱,不是贱

好了话不多说,我们还是先来介绍功能实现,当然不想看功能实现的可以直接下滑copy代码^^.

1.到Mob官网注册成为开发者,然后下载SDK

Mob地址

相信对于大部分开发者这一步都不陌生

image

直接到这里注册,然后登录

然后我们实现用的是他的SMSSDK服务,下载它的SDK

然后导入项目就行了

当然现在新版的话不需要下载SDK,配置一下项目就可以具体看下面。

2.添加一个应用

这个也挺简单,按操作来就行了,会提醒你添加自己的应用,如实填写就能拿到
appKeyappSecret

image.png

这里从别人博客拿的图

3.项目配置

1、打开项目根目录的build.gradle,在buildscrip–>dependencies 模块下面添加 classpath ‘com.mob.sdk:MobSDK:+’,如下所示:

buildscript {
    repositories {
        ...
    }
    dependencies {
        ...
        classpath "com.mob.sdk:MobSDK:2018.0319.1724"
    }
}
image.png

2、在使用SMSSDK模块的build.gradle中,添加MobSDK插件和扩展,如下所示:

// 添加插件
apply plugin: 'com.mob.sdk'

// 在MobSDK的扩展中注册SMSSDK的相关信息
MobSDK {
    appKey "申请Mob的appkey"
    appSecret "申请Mob的AppSecret"
    SMSSDK {}
}

4.功能实现

好了,到这一步,不想看实现的就可以直接往下拿代码应用了,我想分享一下自己的实现思路

首先对Mob的SDK有一定了解之后
我们了解到配置完成之后,由于在配置中已经填写了我们获取的appkey和appSecret
进而在项目中不需要对SDK进行初始化。

官方提供接口方案有两套,一是使用官方的默认UI继承,由于我的项目使用自己的一套UI所以没有了解,有兴趣可以了解mobAPI文档

所以我们选择使用无GUI接口
我们主要用到的类有两个
1.EventHandler 类 该类用于处理回调,在发送短信获得验证码或者发送验证码去验证都需要回调这个类的afterEvent()

 private  EventHandler eh=new EventHandler(){
        @Override
        public void afterEvent(int event, int result, Object data) {
            // TODO 此处不可直接处理UI线程,处理后续操作需传到主线程中操作
            Message msg = new Message();
            msg.arg1 = event;
            msg.arg2 = result;
            msg.obj = data;
            handler.sendMessage(msg);
        }
    };

event是请求的事件。result返回结果,data返回一些数据
由于这里不能处理UI所以我们handle回调到主线程

2.再有就是SMSSDK这个类,主要提供一些封装的全局方法来完成收发验证

第一步我们要注册EventHandler对象

 SMSSDK.registerEventHandler(eh);

第二步我们就可以利用SMSSDK

SMSSDK.getVerificationCode(country, phone);

完成发送验证码,不过由于我们的应用没有进一步申报,一天好像只能发送20条

第三步我们再用

SMSSDK.submitVerificationCode(country, phone, code);

去完成验证码的验证

第四步,创建自己的handle处理请求

private  Handler handler=new Handler() {
        @Override
        public void handleMessage(Message msg) {
           int event=msg.arg1;  //处理的事件
           int result=msg.arg2;  //返回的结果
           Object data=msg.obj;

           if(result==SMSSDK.RESULT_COMPLETE){//处理成功
               if (event==SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE){ //验证成功
                   sendlistener.onSuccess();
               }else if(event == SMSSDK.EVENT_GET_VERIFICATION_CODE){ //获取验证码成功
                   codelistener.onSuccess();
               }
           }else {
               if (event==SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE){ //验证成功
                   sendlistener.onfail();
               }else if(event == SMSSDK.EVENT_GET_VERIFICATION_CODE){ //获取验证码成功
                   codelistener.onfail();
               }
               ((Throwable)data).printStackTrace();
           }
        }
    };

到此API的分析结束,我们该想想实现自己的封装

5.封装对象

建立一个MobHelper类

定义两个自己的回调接口

 interface MobGetcodeListener{
       void  onSuccess();
       void   onfail();
     }
     interface MobSendListener{
        void  onSuccess();
        void   onfail();
     }

然后再封装两个方法完成验证码发送和验证码验证

public   void  getVerrificationCode(String country,String phone,MobGetcodeListener listener){
       //实现回调接口
       this.codelistener=listener;

       //执行验证短信 回调afterEvent
       SMSSDK.getVerificationCode(country, phone);
   }
 public   void  submitVerrificationCode(String country, String phone,String code, MobSendListener listener){
        //实现回调接口
        this.sendlistener =listener;
        //执行验证短信 回调afterEvent
        // 提交验证码,其中的code表示验证码,如“1357”
        SMSSDK.submitVerificationCode(country, phone, code);
    }

最后我们需要手动注销

  public void unregister(){
        SMSSDK.unregisterEventHandler(eh);
    }

到这,为了更好的UI效果,我决定在项目里添加button的获取验证码倒计时功能
查询API发现android已经为我们提供了一个倒计时类 CountDownTimer不用自己实现,这对于我来说无疑又是一个好消息^^

 timer = new CountDownTimer(1000 * second, 1000) {
             @SuppressLint("DefaultLocale")
             @Override
             public void onTick(long millisUntilFinished) {
                 if (debug)
                     Log.d("MobHelper", "onTick: ");
                 if(countbt!=null) {
                     countbt.setEnabled(false);
                     countbt.setText("下一次重发剩余"+millisUntilFinished / 1000);
                 }else {
                     if(debug)
                         Log.d("MobHelper", "onTick: 按钮不能为null");
                 }
             }
             @Override
             public void onFinish() {
                 if(countbt!=null) {
                     countbt.setEnabled(true);
                     countbt.setText("重新获取");
                 }else {
                     if(debug)
                         Log.d("MobHelper", "onFinish: 按钮不能为null");
                 }
             }
         };

原理也很简单,onTick在每一次时间改变会调用,用来更新UI
onFinish那当然就是在结束时调用。

还有一点就是用户隐私授权

官方说明开发者必须有个变量控制用户隐私授权的结果,将结果传入下面函数

  MobSDK.submitPolicyGrantResult(granted, null);

所以我们代码中任意调用即可
于是我们很快实现了自己的封装。

6.注意事项

好了 白嫖的同学配置完可以直接看这里。

首先我们在AndroidManifest.xml添加权限

<!-- 可选权限说明-->
<uses-permission
     android:name="android.permission.INTERNET" />
允许应用程序联网(必须)
 <uses-permission
     android:name="android.permission.ACCESS_WIFI_STATE" />
允许访问WiFi网络状态信息(必须)
 <uses-permission
     android:name="android.permission.READ_PHONE_STATE" />
允许读取手机状态(必须)
 <uses-permission
     android:name="android.permission.ACCESS_NETWORK_STATE" />
允许访问网络状态(必须)
 <uses-permission
     android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
允许写手机存储(必须)
 <uses-permission
     android:name="android.permission.RECEIVE_SMS" />
GUI自动填充验证码功能(非必须)
 <uses-permission
     android:name="android.permission.READ_SMS" />
从短信中读取验证码接口(非必须)
 <uses-permission
     android:name="android.permission.READ_CONTACTS" />
应用内好友功能(非必须)

其中
READ_PHONE_STATE
WRITE_EXTERNAL_STORAGE
需要运行时权限申请

7.完整代码

/**
 * Created by MXL on 2020/6/14
 * <br>类描述:该类为发送短信的帮助类<br/>
 *
 * @version 1.0
 * @since 1.0
 */
public class  MobHelper {
    private boolean debug=false;
    //利用Handler异步处理UI
    private  Handler handler=new Handler() {
        @Override
        public void handleMessage(Message msg) {
           int event=msg.arg1;  //处理的事件
           int result=msg.arg2;  //返回的结果
           Object data=msg.obj;

           if(result==SMSSDK.RESULT_COMPLETE){//处理成功
               if (event==SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE){ //验证成功
                   sendlistener.onSuccess();
               }else if(event == SMSSDK.EVENT_GET_VERIFICATION_CODE){ //获取验证码成功
                   codelistener.onSuccess();
               }
           }else {
               if (event==SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE){ //验证成功
                   sendlistener.onfail();
               }else if(event == SMSSDK.EVENT_GET_VERIFICATION_CODE){ //获取验证码成功
                   codelistener.onfail();
               }
               ((Throwable)data).printStackTrace();
           }
        }
    };
    public final static  String CN="86";
    private  MobGetcodeListener codelistener;
    private  MobSendListener sendlistener;
    private  CountDownTimer timer;
    private  Button countbt;
    //SDK提供的回调类
    private  EventHandler eh=new EventHandler(){
        @Override
        public void afterEvent(int event, int result, Object data) {
            // TODO 此处不可直接处理UI线程,处理后续操作需传到主线程中操作
            Message msg = new Message();
            msg.arg1 = event;
            msg.arg2 = result;
            msg.obj = data;
            handler.sendMessage(msg);
        }
    };
    /**
     * 表明用户是否同意隐私协议
     * 第一个参数为true表示同意
     * 第二个参数为回调接口可空
     * 该方法在使用SDK任何方法之前调用都行
     */
    static {
        MobSDK.submitPolicyGrantResult(true, null);
    }
   public MobHelper(){
        //这里注册监听
        SMSSDK.registerEventHandler(eh);
    }

    /**
     * 发送短信服务
     * @param country 国家 如中国“86”
     * @param phone   手机号码
     * @param listener 回调接口
     */
   public   void  getVerrificationCode(String country,String phone,MobGetcodeListener listener){
       //实现回调接口
       this.codelistener=listener;
       //如果设置了timer 开始倒计时
       if(timer!=null){
           if(debug)
               Log.d("MobHelper", "getVerrificationCode: 倒计时开始执行");
           timer.start();
       }
       //执行验证短信 回调afterEvent
       SMSSDK.getVerificationCode(country, phone);
   }

    /**
     *  发送短信服务
     * @param country 国家 如中国“86”
     * @param phone 手机号码
     * @param listener 回调接口
     * @param listener2 这个参数是SDK提供的回调接口用于发送短信之前对短信的验证 由于自己的项目没有使用这个参数 所以使用详情参照官方SDK文档
     */
    public   void  getVerrificationCode(String country, String phone, MobGetcodeListener listener, OnSendMessageHandler listener2){
        getVerrificationCode( country, phone,listener);
        SMSSDK.getVerificationCode(country, phone,listener2);
    }
    /**
     * .验证验证码
     * @param country 国家 如中国“86”
     * @param phone   手机号码
     * @param listener 回调接口
     */
    public   void  submitVerrificationCode(String country, String phone,String code, MobSendListener listener){
        //实现回调接口
        this.sendlistener =listener;
        //执行验证短信 回调afterEvent
        // 提交验证码,其中的code表示验证码,如“1357”
        SMSSDK.submitVerificationCode(country, phone, code);
    }

    /**
     * 使用完EventHandler需注销,否则可能出现内存泄漏
     * 这里使用完之后手动注销
     */
    public void unregister(){
        SMSSDK.unregisterEventHandler(eh);
    }

     interface MobGetcodeListener{
       void  onSuccess();
       void   onfail();
     }
     interface MobSendListener{
        void  onSuccess();
        void   onfail();
     }

     /**
     * 为按钮设置倒计时
      * 非必要 可选
     * @param button  获取验证码的按钮实例
     * @param second   秒数
     */
     public void  setCountDown(Button button,int second){
         this.countbt=button;
         initCountDownTime(second);
     }

    /**
     * 初始化倒计时类
     * @param second  剩余秒数
     */
     private void  initCountDownTime( int second){
         //倒计时60秒,这里不直接写60000,而用1000*60是因为后者看起来更直观,每走一步是1000毫秒也就是1秒
          timer = new CountDownTimer(1000 * second, 1000) {
             @SuppressLint("DefaultLocale")
             @Override
             public void onTick(long millisUntilFinished) {
                 if (debug)
                     Log.d("MobHelper", "onTick: ");
                 if(countbt!=null) {
                     countbt.setEnabled(false);
                     countbt.setText("下一次重发剩余"+millisUntilFinished / 1000);
                 }else {
                     if(debug)
                         Log.d("MobHelper", "onTick: 按钮不能为null");
                 }
             }
             @Override
             public void onFinish() {
                 if(countbt!=null) {
                     countbt.setEnabled(true);
                     countbt.setText("重新获取");
                 }else {
                     if(debug)
                         Log.d("MobHelper", "onFinish: 按钮不能为null");
                 }
             }
         };
     }
}

这个类复制到项目里,然后是使用

/**
 * Created by MXL on 2020/1/18
 * <br>类描述:用于短信验证的活动<br/>
 *
 * @version 1.0
 * @since 1.0
 */
public class MobActivity extends AppCompatActivity implements View.OnClickListener {

    EditText phone;
    EditText code;
    Button send;
    Button submit;
    boolean isgrant=false;
    boolean debug=false;
    private MobHelper mobHelper;
   public static void actionStart(Context context){
       Intent intent=new Intent(context,MobActivity.class);
       context.startActivity(intent);
   }
//    private CountDownTimerHelper mCountDownTimerHelper;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mob);
        initview();
        initdata();
    }
    public void initview(){
      phone =findViewById(R.id.edit_mob);
      code=findViewById(R.id.edit_code);
      send=findViewById(R.id.send);
      submit=findViewById(R.id.submit);
      send.setOnClickListener(this);
      submit.setOnClickListener(this);
    };
   public void initdata(){
       mobHelper=new MobHelper();
       //为按钮添加倒计时 可选
       mobHelper.setCountDown(send,30);
   };

    @Override
    public void onClick(View v) {
        if(!isgrant){
            applyPermission();
        }
        if (debug)
        Log.d("MobActivity", "onClick: 经过授权");
        switch (v.getId()){
            case R.id.send:
                if (debug)
                Log.d("MobActivity", "onClick: 发送验证码");
             mobHelper.getVerrificationCode(MobHelper.CN, phone.getText().toString().trim(), new MobHelper.MobGetcodeListener() {
                 @Override
                 public void onSuccess() {
                     Toast.makeText(MobActivity.this,"成功请求验证码",Toast.LENGTH_SHORT).show();
                         //写自己逻辑
                 }

                 @Override
                 public void onfail() {
                     Toast.makeText(MobActivity.this,"请求验证码失败",Toast.LENGTH_SHORT).show();
                         //写自己逻辑
                 }
             });
                break;
            case R.id.submit:
                Log.d("MobActivity", "onClick: 验证验证码");
                mobHelper.submitVerrificationCode(MobHelper.CN,phone.getText().toString().trim(),code.getText().toString().trim(), new MobHelper.MobSendListener() {
                    @Override
                    public void onSuccess() {
                        Toast.makeText(MobActivity.this,"验证成功",Toast.LENGTH_SHORT).show();
                    }
                             //写自己逻辑
                    @Override
                    public void onfail() {
                        Toast.makeText(MobActivity.this,"验证失败",Toast.LENGTH_SHORT).show();
                          //写自己逻辑
                    }
                });
                break;
                default:
                    break;
        }
    }
    private void applyPermission(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            /**
             * API23以上版本需要发起写文件权限请求
             */
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE,},PERMISSIONS_REQUEST_CODE);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            //上面请求时候的请求码
            case PERMISSIONS_REQUEST_CODE:
                if (grantResults.length > 0 && grantResults[0] == PackageManager
                        .PERMISSION_GRANTED) {
                    //授权
                    isgrant=true;
                }
                else{
                    Toast.makeText(this,"未同意权限可能导致功能不可使用",Toast.LENGTH_LONG).show();
                }
                break;
            default:
                break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mobHelper.unregister();
    }
}

初始化变量然后回调写自己的代码逻辑就行了。

效果图


D114E8DFB3BCA472608E2A8F58F00036.jpg

害 比较粗略就不精修了

特别感谢

Android实现按钮倒计时
Anroid接入短信验证模块

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容