本文共 13102 字,大约阅读时间需要 43 分钟。
关于这个功能实现的灵感来自于这篇博客,以为我以前出过一篇的博客,这篇博客主要是针对Android端的实现,所以我们可以通过flutter和Android实现相互通信,从而达到flutter也可以实现手机验证码登录的效果
。
虽然白嫖固然好,但是首先声明一下,因为这个平台的每个账号,一天只能发送10次验证码
。
因为下面那篇博客已经说的很清楚了,所以我就不在做详细说明。
关于如何注册这个平台应用,你可以去看一下我的:https://blog.csdn.net/qq_45137584/article/details/111414308 这篇博客,说的挺详细的,大概从开始看到下图红色圆圈处就可以了。关于这个步骤因为我以前的博客有说过,就不在进行说明了,可以看一下我的,从开头看到下图红色圆圈处部分就可以了。
记得仔细阅读每一步,如果你缺少了一步,可以就会导致你的功能无法实现。下面的文字是补充,可以不需要看
。
classpath "com.mob.sdk:MobSDK:2018.0319.1724"
maven { url 'https://jitpack.io' }
配置mob环境的代码
: id 'com.mob.sdk'
建议修改为自己的appKey和appSecret
MobSDK { appKey "31d18b327d099" //修改为你自己的appKey appSecret "5e6a2e16f58f9c1e374acf77abb70b70" //修改为你自己的appSecret SMSSDK { }}
配置flutter的环境:因为我在与flutter端通信的时候需要用到flutter的库,所以需要配置flutter的环境。
代码如下:
def localProperties = new Properties()def localPropertiesFile = rootProject.file('local.properties')if (localPropertiesFile.exists()) { localPropertiesFile.withReader('UTF-8') { reader -> localProperties.load(reader) }}def flutterRoot = localProperties.getProperty('flutter.sdk')apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
flutter { source '../..'}
代码如下:
首先把build.gradle(Module:app)文件中图中红色圆圈处改为与build.gradle(Module:mob_plugin)文件中版本相同
配置mob环境:
代码如下:配置mob环境
apply plugin: 'com.mob.sdk'
导入library库
implementation project(':mob_plugin')
这个页面的实现对于学过flutter的人来说比较简单,毕竟我们主要是用于测试功能,所以没必要做的过于复杂。主要就两个输入框和两个按钮。
这里我就说一下主要的一个部分吧,代码如下///这个方法主要是把你输入的手机号码传输过去ArsManager.telephone(myController.text);///这个方法主要是把你输入的手机号码和验证码存入Map里面,然后传输过去。Map ages={ }; ages['phone']=myController.text; ages['code']=myController1.text; ArsManager.correct(ages).then((result){ int code = result["code"]; String message = result["message"]; if(message=="提交验证码正确") { Navigator.of(context).push( MaterialPageRoute(builder: (context)=>Login())); }else{ print(message); } });
main.dart页面
import 'package:flutter/material.dart';import 'package:mob_app/asr_manger.dart';import 'package:mob_app/login.dart';void main() { runApp(MaterialApp( home: MyApp(), ));}class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState();}class _MyAppState extends State{ final myController = TextEditingController(); final myController1=TextEditingController(); @override void dispose() { // TODO: implement dispose myController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Column( children: [ Padding( padding: const EdgeInsets.all(8.0), child: TextField( controller: myController, obscureText: true, decoration: InputDecoration( labelText: "请输入手机号码", hintText: "请输入手机号码", prefixIcon: Icon(Icons.people_alt_rounded)), ), ), Container( height: 40, child:OutlineButton( borderSide:new BorderSide(color: Theme.of(context).primaryColor), child: new Text('获取验证码',style: new TextStyle(color: Theme.of(context).primaryColor),), onPressed: (){ _data(); }, ), ), Padding( padding: const EdgeInsets.all(4.0), child: TextField( controller: myController1, decoration: InputDecoration( labelText: "请输入验证码", prefixIcon: Icon(Icons.lock), hintText: "请输入验证码", ), ), ), Container( height: 40, child:OutlineButton( borderSide:new BorderSide(color: Theme.of(context).primaryColor), child: new Text('登录',style: new TextStyle(color: Theme.of(context).primaryColor),), onPressed: (){ _login(); }, ), ), ], ), ); } _data() { setState(() { ArsManager.telephone(myController.text); }); } _login() { setState(() { Map ages={ }; ages['phone']=myController.text; ages['code']=myController1.text; ArsManager.correct(ages).then((result){ int code = result["code"]; String message = result["message"]; if(message=="提交验证码正确") { Navigator.of(context).push( MaterialPageRoute(builder: (context)=>Login())); }else{ print(message); } }); }); }}
这个页面用于我们验证码验证成功的时候跳转页面。
login.dart页面:import 'package:flutter/material.dart';class Login extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: Text('登录成功',style: TextStyle(decoration: TextDecoration.none,fontSize: 20,color:Color(0xFFFFFFFF)),), ); }}
这里我们主要设置了两个方法:
telephone方法:把手机号码传输给Android端,然后发送验证码的方法
。 传送的值是String类型,返回的值也是String类型 correct方法:把手机号码和你输入的验证码传输给Android端,然后实现验证验证码输入是否正确
。 传送的值是Map类型,返回的值是dynamic类型 如果对于那个基础类型不是很懂,可以去看一下我的这篇文章。 代码如下:
import 'dart:async';import 'package:flutter/services.dart';class ArsManager{ static const MethodChannel _channel=const MethodChannel('asr_plugin'); static Futuretelephone(String phone) async{ return await _channel.invokeMethod('telephone',phone); } static Future correct(Map map) async{ return await _channel.invokeMethod('correct',map); }}
主要使用到三个方法:
send方法:输入值是phone;主要功能就是通过手机号码获取验证码
submit方法:主要输入值是phone,code;主要功能就是通过手机号码和输入的验证码来验证验证码是否输入正确。
verification方法:主要输入值是message;主要功能就是回调验证码的输入是否正确,然后把结果发送给flutter端
。 package com.example.mob_plugin;import android.app.Activity;import android.text.TextUtils;import android.util.Log;import com.mob.MobSDK;import org.json.JSONException;import org.json.JSONObject;import java.util.HashMap;import java.util.Map;import cn.smssdk.EventHandler;import cn.smssdk.SMSSDK;import io.flutter.plugin.common.MethodChannel;class ArsManger extends Activity { EventHandler handler; boolean f1=false; public void submit(String phone, String code, Activity activity, MethodChannel.Result result) { SMSSDK.submitVerificationCode("86",phone,code); verification(activity,result); } //点击发送验证码 public void send(String phone) { //获取验证码 SMSSDK.getVerificationCode("86",phone); } public void verification(Activity activity,MethodChannel.Result message){ MobSDK.init(activity, "31d18b327d099","5e6a2e16f58f9c1e374acf77abb70b70"); handler = new EventHandler(){ @Override public void afterEvent(int event, int result, Object data) { if (result == SMSSDK.RESULT_COMPLETE){ //回调完成 if (event == SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE) { //提交验证码成功 runOnUiThread(new Runnable() { @Override public void run() { Log.e("123","提交验证码正确"); MapresultMap = new HashMap<>(); resultMap.put("message", "提交验证码正确"); resultMap.put("code", 200); //发消息至 Flutter //此方法只能使用一次 message.success(resultMap); } }); }else if (event == SMSSDK.EVENT_GET_VERIFICATION_CODE){ //获取验证码成功 runOnUiThread(new Runnable() { @Override public void run() { // Toast.makeText(MainActivity.this,"验证码已发送", Toast.LENGTH_SHORT).show(); Log.e("123","验证码已发送"); Map resultMap = new HashMap<>(); resultMap.put("message", "验证码已发送"); resultMap.put("code", 200); //发消息至 Flutter //此方法只能使用一次 message.success(resultMap); } }); }else if (event == SMSSDK.EVENT_GET_SUPPORTED_COUNTRIES){ } }else{ ((Throwable)data).printStackTrace(); Throwable throwable = (Throwable) data; try { JSONObject obj = new JSONObject(throwable.getMessage()); final String des = obj.optString("detail"); if (!TextUtils.isEmpty(des)){ runOnUiThread(new Runnable() { @Override public void run() { Log.e("123","提交错误信息"); // Toast.makeText(MainActivity.this,"提交错误信息", Toast.LENGTH_SHORT).show(); Map resultMap = new HashMap<>(); resultMap.put("message", "提交错误信息"); resultMap.put("code", 200); //发消息至 Flutter //此方法只能使用一次 message.success(resultMap); } }); } } catch (JSONException e) { e.printStackTrace(); } } } }; SMSSDK.registerEventHandler(handler); }}
说一下上面代码中的一段代码:
代码如下:主要用于把我们verification方法的回调结果返回给flutter,这里属于Android发送给flutter端的一段代码
。 MapresultMap = new HashMap<>(); resultMap.put("message", "验证码正确"); resultMap.put("code", 200); //发消息至 Flutter //此方法只能使用一次 message.success(resultMap);
主要使用的两个方法:
registerWith方法:等下会用到,主要用于注册plugin,实现通信功能。
onMethodCall方法:这个方法是我们继承MethodChannel.MethodCallHandler类来使用的方法,主要是功能是接受来自flutter发送过来的数据。
package com.example.mob_plugin;import android.app.Activity;import androidx.annotation.NonNull;import io.flutter.plugin.common.BinaryMessenger;import io.flutter.plugin.common.MethodCall;import io.flutter.plugin.common.MethodChannel;public class AsrPlugin implements MethodChannel.MethodCallHandler { private final Activity activity; ArsManger arsManger=new ArsManger(); public static void registerWith(Activity activity, BinaryMessenger messenger) { MethodChannel channel = new MethodChannel(messenger, "asr_plugin"); AsrPlugin instance = new AsrPlugin(activity); channel.setMethodCallHandler(instance); } public AsrPlugin(Activity activity) { this.activity = activity; } @Override public void onMethodCall(@NonNull MethodCall methodCall, @NonNull MethodChannel.Result result) { switch (methodCall.method) { case "telephone": arsManger.send(methodCall.arguments.toString()); break; case "correct": arsManger.submit(methodCall.argument("phone"),methodCall.argument("code"),activity,result); break; default: result.notImplemented(); } }}
package com.example.mob_app;import android.os.Bundle;import androidx.annotation.NonNull;import com.example.mob_plugin.AsrPlugin;import io.flutter.embedding.android.FlutterActivity;import io.flutter.embedding.engine.FlutterEngine;import io.flutter.plugins.GeneratedPluginRegistrant;public class MainActivity extends FlutterActivity { @Override public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { GeneratedPluginRegistrant.registerWith(flutterEngine); //flutter sdk >= v1.17.0 时使用下面方法注册自定义plugin AsrPlugin.registerWith(this, flutterEngine.getDartExecutor().getBinaryMessenger()); } @Override protected void onCreate(Bundle savedInstanceState ) { super.onCreate(savedInstanceState); }}
过程还是比较多的,其实全部代码都已经写出来,如果你觉得结构不够明了,可以找我要这个demo,发送你的电子邮箱或者私聊等方法都可以。