Deploy containers globally in a few clicks

This Engineering Education (EngEd) Program is supported by Section. Instantly deploy containers across multiple cloud providers all around the globe.

Try It For Free

How to Develop a Flutter App with Voice Password Authentication

January 31, 2022

Security is a major concern in the modern world. Many websites and applications need a password for authentication. Yet, traditional passwords can be easily guessed or stolen.

Users may also need to remember many passwords for different applications and websites. This can be difficult, especially if a person has a poor memory. One solution to this problem is a voice password.

This technique requires the user to speak a specific phrase to authenticate. A computer or mobile device can then compare the spoken passcode to the one stored in the server. Therefore, authorized users do not need to remember many passwords for different systems.

Goal

In this tutorial, we will develop a Flutter app that uses one’s voice as the password. This app will allow the user to input their password by speaking instead of typing. We will use the Google Voice API to convert the user’s spoken password into text.

Step 1 - Getting started

We first need to create a new Flutter project. To do this, we run the following command:

 flutter create voice_password

Let’s change the default code in the main.dart file, as shown below. The code will display an empty text field on-screen.

We will use a custom class called PasswordTextField instead of the TextField widget from the Flutter library. This class will allow us to capture the user’s input and verify it with the Google Voice API.

class App extends StatefulWidget {
    @override
    State createState() => new Main();
}

class Main extends StatefulWidget {
    static const String GOOGLE_VOICE = "GOOGLE_VOICE";
    @override
    Widget build(BuildContext context) {
        return new Scaffold(
            body: new Center(
            child: new PasswordTextField(
                    onChanged: _updatePassword,
                    onSaved: _handleSave,
                                    textRules: [
                                maxLength: 4,
                                minLength: 1,
                                pattern: r"\w*",
                                ],
                    errorTextIndicatorColor: Colors.red,
                    ),
                ),

    }
    Future<Null> _updatePassword() async {
        try {
            return await getGoogleVoicePassword();
        } catch (e) {
            print("Cannot get Google Voice password: $e");

        }
    }
    Future<bool> _handleSave() async {
        bool success = false;
        try {
            success = await saveGoogleVoicePassword(toFile: "voice_password.txt");
        } catch (e) {
            print("Cannot save Google Voice password: $e");
        }
        return success;
    }

    void _print(String msg) => print(msg);

    Future<String> getGoogleVoicePassword() async {
        final String rez = await GooglePlayServicesUtil.getErrorDialog(googleApiClient,
        errorCode: GOOGLE_VOICE);
        if (rez != null) return rez;
    }

    Future<bool> saveGoogleVoicePassword(String file) async {
        bool success = false;

        try {
            File f = new File(file);
        if (!f.exists()) {
            f.create();
        }

        byte[] bytes =Encoding.UTF8.encode(password).toBytes();
        FileOutputStream fos = new FileOutputStream(f);
        fos.write(bytes);
        fos.close();
        success = true;

    } catch (e) {
            print("Cannot save Google Voice password: $e");
        }

    return success;

    }

}

Let’s have a look at the code above. Our PasswordTextField implements a TextEditingController interface from Flutter to capture user input. The app then saves passwords in a file called voice_password.txt.

This file is inside the app’s local storage directory. This way, we can ensure that the password is only visible to us and not accessible to other apps on a user’s device.

Step 2 - Displaying an error message

We use the print() method, to display the error message from Google Voice API. For this to work, we should import the following package:

import 'dart:io';

We can now run the app on our device or emulator. Once we enter a password and click on the save button, it will be stored in a file called voice_password.txt.

Let’s go ahead and try using this password to log into our app. When we enter the password, instead of seeing it been typed on the screen, it will be spoken out loud.

This is how easy it is to use Google Voice API in Flutter applications. It provides an extra layer of security by hiding passwords from prying eyes.

Step 3 - Using the Google Voice password

Now that we have our Google Voice password, let’s see how we can use it in our app.

We need to update our print() method to log the error message returned from Google Voice API. Add the following code at the bottom of the main.dart file.

void _print(String msg) => print(msg);

To update our login action to use the Google Voice password, we need to create a variable in the LoginPage class called googleVoicePassword. This variable is of type String.

Inside this method, we will create an instance of GooglePlayServicesUtil along with our googleApiClient. This allows us to read the error code from the Google Voice API and display a DialogBox if it exists.

Future<String> getGoogleVoicePassword() async {
    final String rez = await GooglePlayServicesUtil.getErrorDialog(googleApiClient,errorCode: GOOGLE_VOICE);
    if (rez != null) return rez;
}

Next, convert the password to a byte array. We will then save these values to a file:

byte[] bytes =Encoding.UTF8.encode(password).toBytes();

We should also create a new FileOutputStream with our file location, as demonstrated below:

FileOutputStream fos = new FileOutputStream(file);

Write the byte array to the file, as follows:

fos.write(bytes);
if (!Directory.exists(storageDir)) Directory.create(storageDir);

saveGoogleVoicePassword(file).then((_) => print("Saved voice password to $file"));

We also created a new method called getGoogleVoicePassword() which is of type Future<String>. Inside this method, we use the GooglePlayServicesUtil class.

This class gets the error dialog from the Google Voice API. We then check if this dialog exists and, if it does, we return the dialog box’s text.

Next, we need to convert our password to a byte array. We can do this using the Encoding.UTF8.encode() method. We write this byte array to a file called voice_password.txt in our app’s local storage.

Remember to add the following line of code at the top of our main.dart file.

import 'dart:async';

This allow us to use the Future<String> type inside our getGoogleVoicePassword() method.

We then update the loginState method inside the LoginPage to save this password. Inside the if (googlePlayServices) {...} statement, we add the following code to call our getGoogleVoicePassword() method:

The returned value is used as the second parameter in the FileSavePicker() method.

if (googlePlayServices) {

    String password = getGoogleVoicePassword();
    FileSavePicker savePicker = new FileSavePicker(file);
    savePicker.pickAsFile(password).then((Path file) {
        // TODO: Use the path returned from pickAsFile to create and save a file.
    });

}

We need to update our print() method to display the path of the file chosen by the user.

void _print(String msg) => print(msg);

Finally, update our saveGoogleVoicePassword() method to take in the path as a parameter.

Future<void> saveGoogleVoicePassword(String password) async {
    final String rez = await GooglePlayServicesUtil.getErrorDialog(googleApiClient, errorCode: GOOGLE_VOICE);
    if (rez != null) return rez;
    var storageDir = await getApplicationDocumentsDirectory();
    var voicePasswordFilePath = Path.join(storageDir, 'voice_password.txt');
    if (!Directory.exists(storageDir)) Directory.create(storageDir);
    var file = File('$voicePasswordFilePath');
    await file.writeAsBytesAsync(password);
    file.close();
}

Step 4 - Testing the application

We can now run our app and log in using our Google Voice password. After we have logged in, we can open the voice_password.txt file to see the contents.

Note that the voice password is stored at: C:\Users\username\AppData\Local\Temp\flutter_test\voice_password.txt.

Conclusion

Congratulations! You have developed an app that stores users` voice passwords and uses them to verify their identity.

You can, therefore, use the knowledge gained from this article to craft other beautiful and quality Flutter applications.

Happy coding!


Peer Review Contributions by: Wanja Mike