简体   繁体   中英

Handling AWS Amplify onError Callback Exceptions

I'm having trouble understanding how to handle the onError callbacks from Amplify functions in Android Java. For instance, below is an Amplify call to sign up a user. The function works great and does what it is supposed to do, however, i'm unable to figure out how to handle the different types of onError callbacks that can be thrown with this function, especially since it is formated with Lambda functions.

For instance, if the user is already signed up, the "error" callback becomes a "UsernameExistsException", but I can't figure out how to filter for that exception and handle it. Ultimately, I would like to be able to handle this specific exception to produce an AlertDialog which tells the user "this account already exists" in this example.

There are alot of other similar functions that are structured the same way where I would like to handle other types of errors.

Any help is very appreciated. For reference on how these functions are used, check out the Amplify documentation and tutorials here .

SOLVED UPDATE 1/23/21: I posted an answer below using @Jameson's answer

Amplify.Auth.signUp(
            user_email,
            user_password,
            AuthSignUpOptions.builder().userAttributes(attributes).build(),
            result -> {
                Log.i("AuthQuickStart", "Result: " + result.toString());
                Intent intent = new Intent(SignUpActivity.this, SignUpAuthActivity.class);
                Bundle bun = new Bundle();
                bun.putSerializable("user", user);
                intent.putExtras(bun);
                startActivity(intent);
                finish();
            },

            error -> {
                //in the example, the Error becomes the UsernameExistsException callback
                Log.e("AuthQuickStart", "Sign up failed", error); 
            }
    );

As you note, most of Amplify Android's methods are asynchronous , and emit either a result or error in one of two callbacks . The callback interfaces are "simple functional interface," and so may be simplified with lambda expression syntax.

In Java, you could look for the UsernameExistsException error like this:

AuthSignUpOptions options =
    AuthSignUpOptions.builder()
        .userAttributes(attributes)
        .build();
Amplify.Auth.signUp(username, password, options,
    result -> { /* handle result ... */ },
    error -> {
        if (error instanceof UsernameExistsException) {
            showAlreadyExistsDialog();
        }
    }
);

with:

private void showAlreadyExistsDialog() {
    new AlertDialog.Builder(context)
        .setTitle("User already exists!")
        .setMessage("Tried to sign-up an already-existing user.")
        .setPositiveButton(android.R.string.yes, (dialog, which) -> {
            // on click...
        })
        .setNegativeButton(android.R.string.no, null)
        .setIcon(android.R.drawable.ic_dialog_alert)
        .show();
}

Similar with Kotlin, except you can use the when construct:

val options = AuthSignUpOptions.builder()
    .userAttributes(attributes)
    .build()
Amplify.Auth.signUp(username, password, options,
    { /* result handling ... */ },
    { error ->
        when (error) {
            is UsernameExistsException -> 
                showAlreadyExistsDialog()
        }
    }
)

Thanks to @Jameson for providing some insights. Here is the solution I ended up using to handle errors from Amplify.

Couple things to note: Due to the Amplify libraries using some old Java libraries and some new code for error handling, I wasn't able to cast the errors appropriately like in @Jameson's answer. Something about the way the Amplify library is set up in AuthExceptions dis-allowed me to cast the root error that was being thrown. The only way I was able to identify the errors correctly was by using a string.contains function to scan the string that the Amplify function outputs during an error.

Also, due to the lambda function format, you have to run a thread inside the lambda function to be able to interact with the UI elements. Otherwise a looper error is thrown.

Amplify.Auth.signIn(
            user_email,
            user_pass,
            result -> {
                Log.i("AmplifyAuth", result.isSignInComplete() ? "Sign in succeeded" : "Sign in not complete");
                startActivity(new Intent(LoginActivity.this, MainDashActivity.class));
                finish();
            },
            error -> {
                Log.e("AmplifyAuth", error.toString());
                //Handles incorrect username/password combo
                if (error.getCause().toString().contains("Incorrect username or password") ) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            incorrectLoginDialog.show();
                        }
                    });
                    return;
                }

                //Handles too many login attempts
                if (error.getCause().toString().contains("Password attempts exceeded") ) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            tooManyAttemptsDialog.show();
                        }
                    });
                    return;
                }

                //Handles when the email user does not exist in the user pool
                if (error.getCause().toString().contains("User does not exist") ) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            doesNotExistDialog.show();
                        }
                    });
                    return;
                }
            }
    );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM