awslabs / aws-mobile-appsync-sdk-android

Android SDK for AWS AppSync.
https://docs.amplify.aws/sdk/api/graphql/q/platform/android/
Apache License 2.0
105 stars 58 forks source link

Android app crashes on Appsync Initialisation #234

Closed Sahil-24 closed 4 years ago

Sahil-24 commented 4 years ago

I am creating an Android application that is using appsync to communicate with an existing graphql API. My android application crashes every time I try to initialise the Appsync Client. I am using Cognito Userpools to successfully authenticate with the server with no issues. The Appsync Initialisation code I am using is as follows (using Kotlin):

 val awsConfig = AWSConfiguration(this)

        val client = AWSAppSyncClient.builder()
            .context(this)
            .awsConfiguration(awsConfig)
            .build()

Once I've successfully authenticated a user, if I then try and initialise the Appsync client with the above code the program crashes with the following error: E/AndroidRuntime: FATAL EXCEPTION: main Process: com.emits.driverapp, PID: 24044 java.lang.NoClassDefFoundError: Failed resolution of: Lcom/amazonaws/mobileconnectors/appsync/fetcher/AppSyncResponseFetchers; at com.amazonaws.mobileconnectors.appsync.AWSAppSyncClient$Builder.<init>(AWSAppSyncClient.java:314) at com.amazonaws.mobileconnectors.appsync.AWSAppSyncClient$Builder.<init>(AWSAppSyncClient.java:295) at com.amazonaws.mobileconnectors.appsync.AWSAppSyncClient.builder(AWSAppSyncClient.java:662) at com.emits.driverapp.DriverInfoActivity.onCreate(DriverInfoActivity.kt:71) at android.app.Activity.performCreate(Activity.java:6723) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2619) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2727) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1478) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6121) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) Caused by: java.lang.ClassNotFoundException: Didn't find class "com.amazonaws.mobileconnectors.appsync.fetcher.AppSyncResponseFetchers" on path: DexPathList[[zip file "/data/app/com.emits.driverapp-2/base.apk"],nativeLibraryDirectories=[/data/app/com.emits.driverapp-2/lib/arm, /system/lib, /vendor/lib]] at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) at java.lang.ClassLoader.loadClass(ClassLoader.java:380) at java.lang.ClassLoader.loadClass(ClassLoader.java:312) at com.amazonaws.mobileconnectors.appsync.AWSAppSyncClient$Builder.<init>(AWSAppSyncClient.java:314)  at com.amazonaws.mobileconnectors.appsync.AWSAppSyncClient$Builder.<init>(AWSAppSyncClient.java:295)  at com.amazonaws.mobileconnectors.appsync.AWSAppSyncClient.builder(AWSAppSyncClient.java:662)  at com.emits.driverapp.DriverInfoActivity.onCreate(DriverInfoActivity.kt:71)  at android.app.Activity.performCreate(Activity.java:6723)  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2619)  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2727)  at android.app.ActivityThread.-wrap12(ActivityThread.java)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1478)  at android.os.Handler.dispatchMessage(Handler.java:102)  at android.os.Looper.loop(Looper.java:154)  at android.app.ActivityThread.main(ActivityThread.java:6121)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)  W/Adreno-EGLSUB: <DequeueBuffer:726>: dequeue native buffer fail: No such device, buffer=0x0, handle=0x0 W/Adreno-EGL: <qeglDrvAPI_eglSwapBuffers:3798>: EGL_BAD_SURFACE W/OpenGLRenderer: swapBuffers encountered EGL error 12301 on 0x989526c0, halting rendering... Process 24044 terminated.

my awsconfiguration.json is as follows:

{
    "UserAgent": "aws-amplify-cli/0.1.0",
    "Version": "0.1.0",
    "IdentityManager": {
        "Default": {}
    },
    "CognitoUserPool": {
        "Default": {
            "PoolId": "us-east-1_IS1TExPaV",
            "AppClientId": "XXXXXXXXXXXXXXXXXXXXXXXXX",
            "Region": "us-east-1"
        }
    },
    "Auth": {
        "Default": {
            "authenticationFlowType": "CUSTOM_AUTH"
        }
    },
    "AppSync": {
        "Default": {
            "ApiUrl": "https://mgn5tyhirnflfh3zm4kuexehnm.appsync-api.us-east-1.amazonaws.com/graphql",
            "Region": "us-east-1",
            "AuthMode": "CUSTOM_AUTH"
        }
    }
} 

Environment:

 apply plugin: 'com.android.application'
apply plugin: 'com.amazonaws.appsync'

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'androidx.navigation.safeargs'
apply plugin: 'kotlin-kapt'

dependencies {
    //Base SDK
    implementation('com.amazonaws:aws-android-sdk-core:2.16.1')

    //AppSync SDK
    implementation('com.amazonaws:aws-android-sdk-appsync:2.10.0')
    implementation('org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.2')
    implementation("org.eclipse.paho:org.eclipse.paho.android.service:1.1.1")

    //For AWSMobileClient only:
    implementation('com.amazonaws:aws-android-sdk-mobile-client:2.16.1')

    //Cognito UserPools for SignIn
    implementation('com.amazonaws:aws-android-sdk-auth-userpools:2.16.1')
    implementation 'com.amazonaws:aws-android-sdk-cognitoidentityprovider:2.16.1'
    //For the drop-in UI also:
    implementation('com.amazonaws:aws-android-sdk-auth-ui:2.16.1')
    implementation 'com.apollographql.apollo:apollo-runtime:1.0.0'
} 

build.gradle (my Application ):

 dependencies {
        classpath 'com.android.tools.build:gradle:3.5.2'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0'
        classpath 'com.apollographql.apollo:apollo-gradle-plugin:1.0.0'
        classpath "com.amazonaws:aws-android-sdk-appsync-gradle-plugin:2.6.17"
 } 

Device Information:

mutablealligator commented 4 years ago

@Sahil-24 Thank you for reporting to us. Sorry for the inconvenience caused.

We do not support the following flags in the configuration file.

 "AuthMode": "CUSTOM_AUTH"

Using these flags in the configuration file will cause a crash. Can you elaborate on what is your strategy for Auth with AppSync?

If you are using CustomAuth with Amazon Cognito UserPools, I would recommend doing the following:

1) Follow the guide to use Custom Auth with AWSMobileClient 2) Add the following to awsconfiguration.json

 "AuthMode": "AMAZON_COGNITO_USER_POOLS"
Sahil-24 commented 4 years ago

Hi @kvasukib.

I had a look at the link and it suggests that we can use CustomAuth in the aws configuration file (here) just as I have done.

Our strategy is to authenticate the user via the app using Cognito Userpools. Then they will be issued credentials in amplify that will be required in order to interact with our Graphql API.

I've also tried using AMAZON_COGNITO_USER_POOLS as you suggested with the same sign in code you referenced (see below for awsconfiguration.json file contents) but encountered a new error:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.emits.driverapp, PID: 26445
    java.lang.RuntimeException: Please check the AppSync configuration in awsconfiguration.json.
        at com.amazonaws.mobileconnectors.appsync.AWSAppSyncClient$Builder.build(AWSAppSyncClient.java:485)
        at com.emits.driverapp.ui.login.LoginPinActivity$signIn$1$onResult$1.run(LoginPinActivity.kt:501)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7050)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.amazonaws.mobileconnectors.appsync.AWSAppSyncClient$AuthMode.toString()' on a null object reference
        at com.amazonaws.mobileconnectors.appsync.AWSAppSyncClient$Builder.build(AWSAppSyncClient.java:482)
        at com.emits.driverapp.ui.login.LoginPinActivity$signIn$1$onResult$1.run(LoginPinActivity.kt:501) 
        at android.os.Handler.handleCallback(Handler.java:873) 
        at android.os.Handler.dispatchMessage(Handler.java:99) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7050) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965) 

awsconfiguration.json [Note on this github issue I've replaced the actual strings with X's, however my actual awsconfiguration file has the correct strings from the aws console]:

{
    "UserAgent": "aws-amplify-cli/0.1.0",
    "Version": "0.1.0",
    "IdentityManager": {
        "Default": {}
    },
    "CognitoUserPool": {
        "Default": {
            "PoolId": "us-east-1_XXXXXXXXX",
            "AppClientId": "xxxxxxxxxxxxxxxxxxxxxxxxx",
            "Region": "us-east-1"
        }
    },
    "Auth": {
        "Default": {
            "authenticationFlowType": "AMAZON_COGNITO_USER_POOLS"
        }
    },
    "AppSync": {
        "Default": {
            "ApiUrl": "https://xxxxxxxxxxxxxxxxxxxxxxxxxx.appsync-api.us-east-1.amazonaws.com/graphql",
            "Region": "us-east-1",
            "AuthMode": "AMAZON_COGNITO_USER_POOLS"
        }
    }
}
mutablealligator commented 4 years ago

You have to use CUSTOM_AUTH as authenticationFlowType and AMAZON_COGNITO_USER_POOLS as AuthMode in AppSync configuration.

{
    "UserAgent": "aws-amplify-cli/0.1.0",
    "Version": "0.1.0",
    "IdentityManager": {
        "Default": {}
    },
    "CognitoUserPool": {
        "Default": {
            "PoolId": "us-east-1_XXXXXXXXX",
            "AppClientId": "xxxxxxxxxxxxxxxxxxxxxxxxx",
            "Region": "us-east-1"
        }
    },
    "Auth": {
        "Default": {
            "authenticationFlowType": "CUSTOM_AUTH"
        }
    },
    "AppSync": {
        "Default": {
            "ApiUrl": "https://xxxxxxxxxxxxxxxxxxxxxxxxxx.appsync-api.us-east-1.amazonaws.com/graphql",
            "Region": "us-east-1",
            "AuthMode": "AMAZON_COGNITO_USER_POOLS"
        }
    }
}
Sahil-24 commented 4 years ago

I've followed your instructions and I have modified my awsconfiguration file as follows:

{
    "UserAgent": "aws-amplify-cli/0.1.0",
    "Version": "0.1.0",
    "IdentityManager": {
        "Default": {}
    },
    "CognitoUserPool": {
        "Default": {
            "PoolId": "us-east-1_xxxxxxxxx",
            "AppClientId": "xxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "Region": "us-east-1"
        }
    },
    "Auth": {
        "Default": {
            "authenticationFlowType": "CUSTOM_AUTH"
        }
    },

    "AppSync": {
        "Default": {
            "ApiUrl": "https://xxxxxxxxxxxxxxxxxxxxxxxxxx.appsync-api.us-east-1.amazonaws.com/graphql",
            "Region": "us-east-1",
            "AuthMode": "AMAZON_COGNITO_USER_POOLS"
        }
    }
}

The signin code I am using is as follows (I've also tried a variant of this where after sign in has been confirmed and then move to the next activity and then initialise the appsync object) [Note I am using Kotlin]:

      fun signIn(username: String, password: String) {

          AWSMobileClient.getInstance()
              .signIn(username, password, null, object : Callback<SignInResult> {
                  override fun onResult(signInResult: SignInResult) {
                   //   ThreadUtils.runOnUiThread {
                          Log.d("APP", "Sign-in callback state: " + signInResult.signInState)
                          when (signInResult.signInState) {
                              SignInState.DONE -> {
                                  Log.d(TAG, "Sign-in done.")

                                  val awsConfig: AWSConfiguration = AWSConfiguration(this@LoginPinActivity)

                                  val client: AWSAppSyncClient = AWSAppSyncClient.builder()
                                      .context(this@LoginPinActivity)
                                      .awsConfiguration(awsConfig)
                                      .build()
                              }
                              SignInState.SMS_MFA -> Log.d(TAG, "Please confirm sign-in with SMS.")
                              SignInState.NEW_PASSWORD_REQUIRED -> Log.d(
                                  TAG,
                                  "Please confirm sign-in with new password."
                              )
                              SignInState.CUSTOM_CHALLENGE -> confirmSignIn()
                              else -> Log.d(
                                  TAG,
                                  "Unsupported sign-in confirmation: " + signInResult.signInState
                              )
                          }
                      //}
                  }

                  override fun onError(e: Exception) {
                      Log.e(TAG, "Sign-in error", e)
                  }
              })

      }

While doing this I am getting the following error when trying to initialise the appsync client:

D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.emits.driverapp, PID: 9666
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.emits.driverapp/com.emits.driverapp.DriverInfoActivity}: java.lang.RuntimeException: Please check the AppSync configuration in awsconfiguration.json.
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3114)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3257)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1948)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7050)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
     Caused by: java.lang.RuntimeException: Please check the AppSync configuration in awsconfiguration.json.
        at com.amazonaws.mobileconnectors.appsync.AWSAppSyncClient$Builder.build(AWSAppSyncClient.java:485)
        at com.emits.driverapp.DriverInfoActivity.onCreate(DriverInfoActivity.kt:70)
        at android.app.Activity.performCreate(Activity.java:7327)
        at android.app.Activity.performCreate(Activity.java:7318)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3094)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3257) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1948) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7050) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965) 
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.amazonaws.mobileconnectors.appsync.AWSAppSyncClient$AuthMode.toString()' on a null object reference
        at com.amazonaws.mobileconnectors.appsync.AWSAppSyncClient$Builder.build(AWSAppSyncClient.java:482)
        at com.emits.driverapp.DriverInfoActivity.onCreate(DriverInfoActivity.kt:70) 
        at android.app.Activity.performCreate(Activity.java:7327) 
        at android.app.Activity.performCreate(Activity.java:7318) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3094) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3257) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1948) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7050) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965) 

it looks like I'm getting an error in my awsconfiguration file

Sahil-24 commented 4 years ago

I've actually fixed the issue using the awscofiguration file you referenced. The issue I was having is how I was initialising the aws appsync client. I used the following code to initialise the appsync client successfully:

       val awsConfig = AWSConfiguration(this)

        val cognitoUserPool = CognitoUserPool(this, awsConfig)
        val basicCognitoUserPoolsAuthProvider =
            BasicCognitoUserPoolsAuthProvider(cognitoUserPool)

        val awsAppSyncClient = AWSAppSyncClient.builder()
            .context(this)
            .awsConfiguration(awsConfig)
            .cognitoUserPoolsAuthProvider(basicCognitoUserPoolsAuthProvider)
            .build()