博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Flutter学习第十五天:2021年最新版超详细Flutter实现Mob+SMSSDK手机验证码登录实现,Android和Flutter混合开发?
阅读量:3962 次
发布时间:2019-05-24

本文共 13102 字,大约阅读时间需要 43 分钟。

Flutter实现手机验证码登录

关于这个功能实现的灵感来自于这篇博客,以为我以前出过一篇的博客,这篇博客主要是针对Android端的实现,所以我们可以通过flutter和Android实现相互通信,从而达到flutter也可以实现手机验证码登录的效果在这里插入图片描述

废话少说,我们先看一下效果,因为个人隐私问题,我把手机号码设置为了密码类型,但是不影响效果:
在这里插入图片描述

虽然白嫖固然好,但是首先声明一下,因为这个平台的每个账号,一天只能发送10次验证码

所以我建议你自己去注册这个平台,建立一个账号来获取验证码登录功能的App Key和App Secret。关于如何注册这个平台应用,你可以去看一下我的这篇博客,说的挺详细的。

第一步:在mob平台配置SMSSDK环境

因为下面那篇博客已经说的很清楚了,所以我就不在做详细说明

关于如何注册这个平台应用,你可以去看一下我的:https://blog.csdn.net/qq_45137584/article/details/111414308
这篇博客,说的挺详细的,大概从开始看到下图红色圆圈处就可以了。
在这里插入图片描述

第二步:建立flutter项目和android的library文件

关于这个步骤因为我以前的博客有说过,就不在进行说明了,可以看一下我的,从开头看到下图红色圆圈处部分就可以了。

在这里插入图片描述
记得仔细阅读每一步,如果你缺少了一步,可以就会导致你的功能无法实现。

下面的文字是补充,可以不需要看

看一下我们建立的项目结构吧,关于Android端那里爆红是因为我这个是flutter的项目,没有Android端相关的jar文件,只需要我们把那个爆红的文件,用Android studio打开即可。
在这里插入图片描述

在这里插入图片描述

下面就我们通过Android studio打开的文件,然后我们在他里面建立的Android的library的文件,名字是mob_plugin。
在这里插入图片描述

第三步:在Android的library文件中部署mob+SMSSDK环境

1.在project的build.gradle文件中加入如下代码

在这里插入图片描述

代码如下:

classpath "com.mob.sdk:MobSDK:2018.0319.1724"
maven {
url 'https://jitpack.io' }

2.在你建立的library中加入如下代码

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

代码如下:
配置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 '../..'}

3.在你的AndroidMainfest.xml文件中加入权限

在这里插入图片描述

代码如下:

第四步:在flutter的Android文件中配置环境

1.修改版本

首先把build.gradle(Module:app)文件中图中红色圆圈处改为与build.gradle(Module:mob_plugin)文件中版本相同

在这里插入图片描述

2.flutter的Android文件中导入android端的library和配置mob环境

配置mob环境:

在这里插入图片描述
代码如下:
配置mob环境

apply plugin: 'com.mob.sdk'

导入library库

mob_plugin改为你自己的library库名即可

implementation project(':mob_plugin')

第五步:实现flutter验证码功能

1.在flutter端首先UI设计(view层)

这个页面的实现对于学过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)),), ); }}

2.配置flutter端的MethodChannel

这里我们主要设置了两个方法:

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 Future
telephone(String phone) async{
return await _channel.invokeMethod('telephone',phone); } static Future
correct(Map map) async{
return await _channel.invokeMethod('correct',map); }}

3.在Android端配置实现发送验证码和验证验证码需要的方法

主要使用到三个方法:

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","提交验证码正确"); Map
resultMap = 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端的一段代码

Map
resultMap = new HashMap<>(); resultMap.put("message", "验证码正确"); resultMap.put("code", 200); //发消息至 Flutter //此方法只能使用一次 message.success(resultMap);

4.在Android端配置MethodChannel

主要使用的两个方法:

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(); } }}

5.最后注册plugin,实现数据通信

在这里插入图片描述

代码如下:

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,发送你的电子邮箱或者私聊等方法都可以。

你可能感兴趣的文章
(1)Pascal 程序结构和基本语句
查看>>
LoadRunner之——脚本分析
查看>>
Advanced searching - fields reference
查看>>
Advanced searching - operators reference
查看>>
LoadRunner之——Java vuser
查看>>
LoadRunner之——场景创建、设置、运行
查看>>
QTP基本使用——Recovery Scenarios
查看>>
Ruby 的优缺点
查看>>
Ruby 教程(一)
查看>>
Ruby 教程(二)
查看>>
Android——简介
查看>>
Ruby 教程(三)
查看>>
Ruby 教程(四)
查看>>
GHOST后只剩下一个分区后的解决方法
查看>>
局部变量、全局变量、对象变量、类变量
查看>>
手动测试 VS 自动测试
查看>>
QTP基本使用——WORD
查看>>
QTP基本使用——Excel
查看>>
QTP基本使用——检查焦点
查看>>
排序算法之一
查看>>