自己的项目遇到需要使用短信验证的功能,要改原来的登录注册,真是头疼。害,经过一番苦寻在网上找到了使用Mob进行短信验证,为什么呢
第一 ,它免费, 哈哈,这无疑是开发者的福音
第二,他的效果,正如它官网写到几乎百分比收到短信
于是去网上看了很多篇博客对于SDK使用的介绍。因为比较懒,只想找到一个框架直接把自己逻辑写回调里哈哈,还真让我找到了,可惜的是,看完介绍,它竟然源码收费,6块钱,算了 ,不如买杯奶茶,于是,我决定自己封装一个框架提供给像我一样白嫖的人,^^。我是可爱,不是贱
好了话不多说,我们还是先来介绍功能实现,当然不想看功能实现的可以直接下滑copy代码^^.
1.到Mob官网注册成为开发者,然后下载SDK
相信对于大部分开发者这一步都不陌生

直接到这里注册,然后登录
然后我们实现用的是他的SMSSDK服务,下载它的SDK
然后导入项目就行了
当然现在新版的话不需要下载SDK,配置一下项目就可以具体看下面。
2.添加一个应用
这个也挺简单,按操作来就行了,会提醒你添加自己的应用,如实填写就能拿到
appKey 和 appSecret

这里从别人博客拿的图
3.项目配置
1、打开项目根目录的build.gradle,在buildscrip–>dependencies 模块下面添加 classpath ‘com.mob.sdk:MobSDK:+’,如下所示:
buildscript {
repositories {
...
}
dependencies {
...
classpath "com.mob.sdk:MobSDK:2018.0319.1724"
}
}

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();
}
}
初始化变量然后回调写自己的代码逻辑就行了。
效果图

害 比较粗略就不精修了