Writing a Serverless Android app (ft. Huawei's AppGallery Connect) - Part 1 - Auth
Tags: android, serverless, java, appgallery
Published: 2021-07-07 11:45:35

Not read part 0? Read it first! {% link https://dev.to/devwithzachary/writing-a-serverless-android-app-ft-huawei-s-appgallery-connect-part-0-3hmj %}


Over the next couple of months I will be releasing a complete end to end guide to creating an Android app using serverless functionality to completely remove the need for any backend server/hosting etc.

This weeks Video is below

{% youtube OMX7xXBQ6Yg%}

And at the bottom of this post you will find my twitch channel where we live stream every Thursday at 2pm BST and the github repo for this project!.

But for those that would rather a written guide, lets get into it!

#Project Setup
Starting with a brand new project (or one that has never used Huawei services) we will need to start by setting up a new app. (If you haven't setup your developer account yet [sign up!](https://developer.huawei.com/consumer/en/)) 

If you would like the complete step by step guide on how to get setup check out the [Official Documentation](https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agc-get-started-android-0000001058210705), but below is a summery.

Navigate to the the [AppGallery Connect](https://developer.huawei.com/consumer/en/service/josp/agc/index.html#/) area of the developer portal, here you need to create a [new project](https://developer.huawei.com/consumer/en/service/josp/agc/index.html#/addProject).
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g07gsy6ch6bocg9zdnad.png)

Follow the new project guide, giving that project a name. Once completed on the left hand menu find the Auth service under the build menu.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ksranpl51ul2hk6ntp4b.png)
Click the enable now button in the top right corner to enable this service for your project. Set a default data processing location, depending on your physical location will most likely help decide which to use. For us we have selected Germany as this is the closest location and within the EU.

From here you are presented with the list of authentication modes, Huawei supports a wide range of services from Facebook login to AppleID. However today we are focusing on the email auth method. Click the enable button next to this.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ayls0pm8aipkmw8filq9.png)

  
Now that everything is setup in the project, its time to setup the app! At this point I will assume you have created a new blank project in Android Studio and given it a package name etc.
From the project settings top screen, select the Add app button to setup a new app under this project.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hhftxijc5fx19qmaqkoa.png)
Fill in the add app form, setting the platform, app name, package etc so that it can be added to the created project. Its worth noting at this point, that while we are focusing on Android today many of these services can be used across multiple platforms including iOS and web.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ieevkpi5t3bdyenubgo.png)
Once completed you will be told to download the agconnect-services.json file and presented with a code to get the core services setup. As we are already focusing on a specific service for today the setup at this point is a little different.
Start by placing your nearly downloaded `agconnect-services.json` file into the app directory of your project.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m1hmuam07yih8wecej9a.png)

Next we will get gradle configured correctly. In your top level gradle build file add the below to your repositories both under buildscript and allprojects
  
```gradle
maven {
    url 'https://developer.huawei.com/repo/'
}
```

And to your dependencies add `classpath 'com.huawei.agconnect:agcp:1.4.1.300'`

Your file should now look a little like

```gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        google()
        mavenCentral()
        maven {
            url 'https://developer.huawei.com/repo/'
        }
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.2.2"
        classpath 'com.huawei.agconnect:agcp:1.4.1.300'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
        jcenter() // Warning: this repository is going to shut down soon
        maven {
            url 'https://developer.huawei.com/repo/'
        }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
```

Next open your app build.gradle file

Start by adding the agconnect plugin into your plugins list

```gradle
plugins {
    id 'com.android.application'
    id 'com.huawei.agconnect'
}
```

Make sure to set your midSdkVersion to at least `17` (this is required for any Huawei AppGallery Connect services.

And then in dependencies we are going to add the core and auth services

```gradle
    implementation 'com.huawei.agconnect:agconnect-core:1.4.1.300'
    implementation 'com.huawei.agconnect:agconnect-auth:1.4.1.300'
```

So your file should now look something like

```gradle
plugins {
    id 'com.android.application'
    id 'com.huawei.agconnect'
}

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.3"

    defaultConfig {
        applicationId "site.zpweb.barker"
        minSdkVersion 17
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation 'com.huawei.agconnect:agconnect-core:1.4.1.300'
    implementation 'com.huawei.agconnect:agconnect-auth:1.4.1.300'
    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'com.google.android.material:material:1.3.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
```

And thats it! let gradle sync up and we are all good to go!

#Registration
As I mentioned before there are a wide range of ways a user can authenticate using the Auth service, but here we are looking at the email service. Email authenticate the user by sending them a code via (your guessed it) Email. The user then inputs this code back into the app to confirm that they are who the say they are, and that they have access to that contact method. We will assume you have setup some kind of register view that will capture a users email.

We start by requesting an authentication code be set to the user, the code to do this looks like

```java
VerifyCodeSettings settings = VerifyCodeSettings.newBuilder()
                .action(VerifyCodeSettings.ACTION_REGISTER_LOGIN)
                .sendInterval(30)
                .locale(Locale.ENGLISH)
                .build();
Task<VerifyCodeResult> task = EmailAuthProvider.requestVerifyCode(emailString, settings);
            task.addOnSuccessListener(TaskExecutors.uiThread(), new OnSuccessListener<VerifyCodeResult>() {
                @Override
                public void onSuccess(VerifyCodeResult verifyCodeResult) {
                    authCodeDialog();
                }
            }).addOnFailureListener(TaskExecutors.uiThread(), new OnFailureListener() {
                @Override
                public void onFailure(Exception e) {
                    Toast.makeText(RegisterActivity.this,
                            "Error, code sending failed: " + e,
                            Toast.LENGTH_LONG).show();
                }
            });
```

Lets break this down, we start by defining a `VerifyCodeSettings` object, this holds all the settings relating to the sending of the code. Here we define what locale should be used for the message text that is sent, what kind of code it is and the send interval.

Next we create a task to be run
```java
Task<VerifyCodeResult> task = EmailAuthProvider.requestVerifyCode(emailString, settings);
```

Using the EmailAuthProvider, where `emailString` is the email address the user has entered, as a string and the settings object is the VerifyCodeSettings object we just created.

Next we setup an OnSucessListener which will be called if the code was successfully sent to the user. In this example we are calling the method `authCodeDialog();` to display a dialog to enter the code, which will see in a moment.
We also setup an OnFailureListener which simply create a toast on screen to display what ever error is sent back.

Now that we have sent the user a code we should display some view for them to enter that code, in my instance I have the method below, but of course this could be what ever view you wanted.

```java
private void authCodeDialog() {
        AlertDialog.Builder alert = new AlertDialog.Builder(this);
        final EditText authCodeField =  new EditText(this);
        alert.setMessage("Enter your auth code below");
        alert.setTitle("Authentication Code");

        alert.setView(authCodeField);

        alert.setPositiveButton("Register", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                String authCode = authCodeField.getText().toString();
                register(authCode);
            }
        });

        alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(RegisterActivity.this,
                        "Registration Cancelled",
                        Toast.LENGTH_LONG).show();
            }
        });

        alert.show();
    }
```

Finally once the user has inputted the code we can register them as you can see above we have a register method that is called, this has the below code:

```java
EmailUser emailUser = new EmailUser.Builder()
                    .setEmail(emailString)
                    .setVerifyCode(authCode)
                    .build();

            AGConnectAuth.getInstance().createUser(emailUser).addOnSuccessListener(new OnSuccessListener<SignInResult>() {
                @Override
                public void onSuccess(SignInResult signInResult) {
                    Toast.makeText(RegisterActivity.this,
                            "Register Successful: " + signInResult.getUser().getUid(),
                            Toast.LENGTH_LONG);
                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(Exception e) {
                    Toast.makeText(RegisterActivity.this,
                            "Registering failed " + e,
                            Toast.LENGTH_LONG);
                }
            });
```

So we start by creating an `EmailUser` using the email address we captured earlier and the authCode that the user has entered. Using that `EmailUser` we then attempt to register. Note that we can also set a password against the `EmailUser`, if we do this when they go to login they do not need to verify their email address again. They can just enter their email and password.

As you can see we pass the created object into the createUser method, attaching OnSuccess and OnFailure Listeners. If the user is successfully registered, i.e the code they entered matches what was sent we are returned a `SignInResult` this object containes the user. So in this example we simply print out the registered users UID to confirm it completed successfully.

#Login

Now that we have covered the sign up process lets look at how we might handle a login process. This would assume that the user has already registered via the above method and is now logging into the app, perhaps after installing it on a new phone.

As I mentioned before if the user signed up without a password then start by sending a verify code, in just the same way as we did during the sign up process. Once we have the code we can generate a `AGCOnnectAuthCredential` object

```java
AGConnectAuthCredential credential = credential = EmailAuthProvider.credentialWithVerifyCode(
                            email.getText().toString().trim(),
                            null,
                            authCode);
```

Here we get the email that the user entered (`email` being an `EditText` object). We pass null for the password as we haven't used this, and finally the authCode which the user has entered into the app.

Now we can attempt the sign the user in:

```java
  AGConnectAuth.getInstance().signIn(credential)
                .addOnSuccessListener(new OnSuccessListener<SignInResult>() {
                    @Override
                    public void onSuccess(SignInResult signInResult) {
                        Toast.makeText(MainActivity.this, "Sign in successful: " +
                                signInResult.getUser().getUid(), Toast.LENGTH_LONG);
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(Exception e) {
                        Toast.makeText(MainActivity.this, "sign in failed:" + e, Toast.LENGTH_LONG);
                    }
                });
```

We pass the credential object into the signIn method, if the code and email matched and was correct the OnSuccessListener will return the SignInResult object just as it did during the sign up, from here we have access to the users detials.
If for any reason the login fails we will get an Exception in the OnFailureListener. 

And thats it! We have setup the application to use Huawei services and configured the app to use email authentication during sign up and log in.


For more information on the Auth service, full documentation can be found here https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agc-auth-introduction-0000001053732605

#Twitch Acccount

{% twitch devwithzachary%}

#Github Repo

{% github devwithzachary/Barker%}

We will be back with the next part next week!