The inspiration for the implementation of this feature came fromFlutter enables Baidu to convert speech to textThis blog. I thought I wrote one beforeAndroid how to achieve mobile number loginThis blog is mainly for Android implementation, so we canFlutter and Android communicate with each other, so that Flutter can also be used for mobile verification code login.Without further ado, let’s take a look at the effect. Due to personal privacy issues, I set the mobile phone number as the password type, but the effect will not be affected:

Although white piao is good, but first of all, because each account of this platform, a day can only send verification code 10 times. Therefore, I suggest you to register this platform and set up an account to obtain the App Key and App Secret of the verification code login function. For how to register this platform application, you can go to mineAndroid mobile phone verification code loginThis blog post is quite detailed, probably from the beginning you can see the red circle below.

Step 1: Configure the SMSSDK environment on the MOB platform

Since the following blog post makes it clear, I won’t elaborate on it. For how to register this platform application, you can go to mineAndroid mobile phone verification code login:Blog.csdn.net/qq_45137584…This blog post is quite detailed, probably from the beginning you can see the red circle below.

Step 2: Create a Library file for the Flutter project and Android

I won’t explain this step because I mentioned it in my previous blog, but take a look at mineFlutter enables Baidu to convert speech to text, just look at the red circle in the picture below.Remember to read each step carefully, if you are missing a step, your feature will not work.

The following text is a supplement, can not need to see. Let’s have a look at the project structure we established. The reason why Flutter is popular on the Android side is that my project is about Flutter. There is no JAR file related to Flutter on the Android side.

Here is the file we opened through Android Studio, and then we created the Android library file in it, named mob_plugin.

Step 3: Deploy the Mob +SMSSDK environment in the Android library file

1. Add the following code to the build.gradle file of the project

The code is as follows:

classpath Com ". The mob. The SDK: MobSDK: 2018.0319.1724"
Copy the code
maven { url 'https://jitpack.io' }
Copy the code

2. Add the following code to your library

The code is as follows:Code to configure the Mob environment:

id 'com.mob.sdk'
Copy the code

You are advised to use your own appKey and appSecret

MobSDK {
    appKey "31d18b327d099"     // Change it to your own appKey
    appSecret "5e6a2e16f58f9c1e374acf77abb70b70" // Change it to your own appSecret
    SMSSDK {}
}
Copy the code

Configure the Flutter environment: Since I need to use the Flutter library when COMMUNICATING with the flutter side, I need to configure the flutter environment.

The code is as follows:

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"
Copy the code
flutter {
    source '.. /.. '
}
Copy the code

3. Add permissions to your AndroidMainfest.xml file

The code is as follows:

 <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.READ_SMS" />
    <uses-permission android:name="android.permission.GET_TASKS" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Copy the code

Step 4: Configure the environment in the Android file of Flutter

1. Modify the version

Build. Gradle (Module:app) == The version in the build.gradle(Module:mob_plugin) file is the same as that in the build.gradle(Module:mob_plugin) file

2. Import the Android library and mob environment into the Flutter Android file

Configure the Mob environment:The code is as follows:Configuring the Mob Environment

apply plugin: 'com.mob.sdk'
Copy the code

Import the library mob_plugin and change it to your own library name

implementation project(':mob_plugin')
Copy the code

Step 5: Implement the Flutter captchas

1. UI design (View layer) at the Flutter end

The implementation of this page is relatively simple for those of you who have learned about Flutter. After all, we are mainly used to test features, so there is no need to make it too complicated. It’s basically two input fields and two buttons. Here I will mention the main part, the code is as follows

/// This method mainly transmits the mobile phone number you entered
ArsManager.telephone(myController.text);

/// This method is mainly to put your mobile phone number and verification code into the Map, and then transmitted to the 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=="Submit verification code correctly") {
          Navigator.of(context).push( MaterialPageRoute(builder: (context)=>Login()));
        }else{ print(message); }});Copy the code

The main dart page

import 'package:flutter/material.dart';
import 'package:mob_app/asr_manger.dart';
import 'package:mob_app/login.dart';

void main(a) {
  runApp(MaterialApp(
    home: MyApp(),
  ));
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState(a) => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final myController = TextEditingController();
  final myController1=TextEditingController();

  @override
  void dispose(a) {
    // 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: "Please enter your mobile phone number.",
                  hintText: "Please enter your mobile phone number.",
                  prefixIcon: Icon(Icons.people_alt_rounded)),
            ),
          ),
          Container(
            height: 40,
            child:OutlineButton(
              borderSide:new BorderSide(color: Theme.of(context).primaryColor),
              child: new Text('Get captcha',style: new TextStyle(color: Theme.of(context).primaryColor),),
              onPressed: (){
                _data();
              },
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(4.0),
            child: TextField(
              controller: myController1,
              decoration: InputDecoration(
                labelText: "Please enter the verification code.",
                prefixIcon: Icon(Icons.lock),
                hintText: "Please enter the verification code.",
              ),
            ),
          ),
          Container(
            height: 40,
            child:OutlineButton(
              borderSide:new BorderSide(color: Theme.of(context).primaryColor),
              child: new Text('login',style: newTextStyle(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=="Submit verification code correctly") {
          Navigator.of(context).push( MaterialPageRoute(builder: (context)=>Login()));
        }else{ print(message); }}); }); }}Copy the code

This page is used to jump to when our captcha is successful. The login. The dart page:

import 'package:flutter/material.dart';

class Login extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text('Login successful',style: TextStyle(decoration: TextDecoration.none,fontSize: 20,color:Color(0xFFFFFFFF)))); }}Copy the code

2. Configure MethodChannel on the flutter

Here we mainly set two methods: telephone method: transfer the phone number to the Android terminal, and then send the verification code method. Correct method: Send the phone number and the verification code you entered to the Android terminal, and then implement verification code to verify that the verification code is correct. The values passed are of Map type and the values returned are of Dynamic type and if you’re not familiar with that base type, check out my article on the base type for DART.

The code is as follows:

import 'dart:async';
import 'package:flutter/services.dart';

class ArsManager{
  static const MethodChannel _channel=const MethodChannel('asr_plugin');

  static Future<String> telephone(String phone) async{
    return await _channel.invokeMethod('telephone',phone);
  }

  static Future<dynamic> correct(Map map) async{
    return await _channel.invokeMethod('correct'.map); }}Copy the code

3. Configure the method to send the verification code and verify the verification code on the Android terminal

Three methods are used: Send: the input value is phone. The main function is to obtain the verification code through the mobile phone number submit method: the main input value is phone,code; The main function is to verify whether the verification code is entered correctly through the mobile phone number and the verification code. Verification method: The primary input value is message; The main function of the flutter is to call back if the captcha is entered correctly and send the result to the flutter end.

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

    // Click send verification code
    public void send(String phone) {
        // Get the verification code
        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){
                    // The callback is complete
                    if (event == SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE) {
                        // Verification code submission succeeded
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run(a) {
                                Log.e("123"."Submit verification code correctly");
                                Map<String, Object> resultMap = new HashMap<>();
                                resultMap.put("message"."Submit verification code correctly");
                                resultMap.put("code".200);
                                // Send messages to Flutter
                                // This method can only be used oncemessage.success(resultMap); }}); }else if (event == SMSSDK.EVENT_GET_VERIFICATION_CODE){
                        // The verification code was successfully obtained
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run(a) {
                               Toast.maketext (mainactivity.this," verification code sent ", toast.length_short).show(); // Toast.maketext (mainactivity.this," verification code sent ", toast.length_short).
                                Log.e("123"."Verification code has been sent");
                                Map<String, Object> resultMap = new HashMap<>();
                                resultMap.put("message"."Verification code has been sent");
                                resultMap.put("code".200);
                                // Send messages to Flutter
                                // This method can only be used oncemessage.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(a) {
                                    Log.e("123"."Error message submitted");
                                   Toast.maketext (mainactivity.this," Submit error message ", toast.length_short).show(); // Toast.maketext (mainactivity.this," submit error message ", toast.length_short).
                                    Map<String, Object> resultMap = new HashMap<>();
                                    resultMap.put("message"."Error message submitted");
                                    resultMap.put("code".200);
                                    // Send messages to Flutter
                                    // This method can only be used oncemessage.success(resultMap); }}); }}catch(JSONException e) { e.printStackTrace(); }}}}; SMSSDK.registerEventHandler(handler); }}Copy the code

This code is used to return the result of our verification callback to flutter. This code is part of the code that Android sends to flutter.

 Map<String, Object> resultMap = new HashMap<>();
 resultMap.put("message"."The verification code is correct");
 resultMap.put("code".200);
 // Send messages to Flutter
 // This method can only be used once
 message.success(resultMap);
Copy the code

4. Configure MethodChannel on Android

The two main methods used: registerWith method: will be used in a moment, mainly used to register plugin, implement communication function. OnMethodCall method: this method is that we inherit MethodChannel MethodCallHandler class to use method, mainly function is to accept data from the flutter sent to come over.

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

5. Finally register plugin to realize data communication

The code is as follows:

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);
        // Register the custom plugin with flutter SDK >= v1.17.0
        AsrPlugin.registerWith(this, flutterEngine.getDartExecutor().getBinaryMessenger());
    }

    @Override
    protected void onCreate(Bundle savedInstanceState ) {
        super.onCreate(savedInstanceState); }}Copy the code

In fact, all the code has been written. If you think the structure is not clear enough, you can ask me for this demo, send your email or private chat and other methods.