Install the Chat Widget in an Android app

The Front Android SDK enables you to add Front Chat to your native Android apps for real-time, chat-based support. Complete the steps in this guide to get started.

📘

The Front Android SDK is in beta

We encourage you to report issues and provide feedback on our GitHub repo.

Install the Front SDK

// build.gradle.kts 
dependencies {
  implementation("com.frontapp:frontsdk:0.0.0-alpha.1")
}
// build.gradle
dependencies {
  implementation "com.frontapp:frontsdk:0.0.0-alpha.1"
}

Update AndroidManifest.xml

Add the INTERNET permission and windowSoftInputMode to adjustResize.

<manifest 
    ...
    <uses-permission android:name="android.permission.INTERNET"/>
    <application 
       ...
       <activity android:windowSoftInputMode="adjustResize">
       </activity>
    </application>  
    ...
</manifest>

Configure Front Chat

  1. Go to Settings > Channels in Front.

  2. Search for or click on the channel you are using for Front Chat.

  3. Open the Installation tab and identify the chatID within the Widget code snippet.

  4. Configure an instance of FrontChatConfig.

    import com.frontapp.frontsdk.FrontChatConfig
    
    val config = FrontChatConfig(
        chatId = "<chatId from step above>"
    )
  5. If you are using the Verified Users feature, add the appropriate parameters. Refer to Identify users for more information.

    import com.frontapp.frontsdk.FrontChatConfig
    import com.frontapp.frontsdk.Contact
    import com.frontapp.frontsdk.CustomFieldValue
    
    val config = FrontChatConfig(
        chatId = "<chatId from step 1 above>",
        email = "<user email>",
        userHash = "<user hash generated by your backend using the verification secret",
        name = "<user name>",
        customFields = mapOf(
        	"custom_field_1" to CustomFieldValue.StringValue("value_1")
        ),
        contact = Contact(
            email = "<user email>",
            customFields = mapOf(
              "custom_field_1" to CustomFieldValue.StringValue("value_1")
            )
        )
    )

Present the FrontChatView

Refer to the code snippets below for an introduction to presenting the FrontChatView in your project. For full working code examples, visit our GitHub repo.

The FrontChatView view can be used like any other @Composable view. Here, we’ll present it as a modal sheet when the “Open Chat” button is tapped.

import ...

class MainActivity : ComponentActivity() {
    private var isShowingFrontChat by mutableStateOf(false)
    private val chatId = "your chat_id"

    @SuppressLint("SetJavaScriptEnabled")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            FrontSdkExampleComposeTheme {
                MainScreen()
            }
        }

        onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                if (isShowingFrontChat) {
                    isShowingFrontChat = false
                } else {
                    finish()
                }
            }
        })
    }

    @OptIn(ExperimentalMaterial3Api::class)
    @Composable
    fun MainScreen() {
        Box(modifier = Modifier.fillMaxSize()) {
            LaunchFrontChatButton()
            AnimatedFrontChatView()
        }
    }

    @Composable
    fun LaunchFrontChatButton() {
        // A simple button to launch FrontChatView
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(16.dp),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Button(onClick = { isShowingFrontChat = true }) {
                Text("Open Chat")
            }
        }
    }

    @OptIn(ExperimentalMaterial3Api::class)
    @Composable
    fun AnimatedFrontChatView() {
        AnimatedVisibility(
            visible = isShowingFrontChat,
            enter = fadeIn() + slideInVertically(initialOffsetY = { it }),
            exit = fadeOut() + slideOutVertically(targetOffsetY = { it }),
        ) {
            Box(
                modifier = Modifier.fillMaxSize()
            ) {
                FrontChatView(config = FrontChatConfig(chatId = chatId))
            }
        }
    }
}

Handle loading state and errors

When you run the examples above, you’ll notice there’s a loading state before the UI comes into view. This is due to the current implementation relying on a webview that loads the same code as Front Chat for web.

Below we have code samples to show how to customize the loading state and handle errors due to things like network issues that cause FrontChatView to fail to load. For working examples, visit the GitHub repo.

  1. Add an instance of FrontChatViewModel as an instance variable.
    class MainActivity : ComponentActivity() {
        private val viewModel = FrontChatViewModel()
        ...
    }
  2. Use the loadingStatus property of FrontChatViewModel to display different UI as appropriate.
    class MainActivity: ComponentActivity() {
        ...
    
        @Composable
        fun MainScreen() {
            val didEncounterUnrecoverableError by viewModel.didEncounterUnrecoverableError.observeAsState(false)
            val loadingStatus by viewModel.loadingStatus.observeAsState(LoadingStatus.IDLE)
    
            Box(modifier = Modifier.fillMaxSize()) {
                if (loadingStatus == LoadingStatus.FAILED_LOADING) { 
                  // Example of how to handle failed loading
                  FailedToLoadDialog()
                } else if (didEncounterUnrecoverableError == true) {
                  // Example of how to handle an exception from the webview that FrontChatView uses
                  UnrecoverableExceptionDialog()
                } else {
                    LaunchFrontChatButton()
    
                    AnimatedFrontChatView()
                }
            }
        }
    
        @Composable
        fun FailedToLoadDialog() {
            AlertDialog(
                title = {
                    Text(text = "Error")
                },
                text = {
                    Text(text = "Failed to load the chat.")
                },
                onDismissRequest = {
                    isShowingFrontChat = false
                },
                confirmButton = {
                    TextButton(
                        onClick = { viewModel.reset(); isShowingFrontChat = false }
                    ) {
                        Text("Ok")
                    }
                }
            )
        }
    
        @Composable
        fun UnrecoverableExceptionDialog() {
            AlertDialog(
                title = {
                    Text(text = "Error")
                },
                text = {
                    Text(text = viewModel.unrecoverableErrorMessage.value ?: "An unknown error occurred.")
                },
                onDismissRequest = {
                    viewModel.reset()
                    isShowingFrontChat = false
                },
                confirmButton = {
                    TextButton(
                        onClick = {
                            viewModel.reset()
                            viewModel.restart()
                        }
                    ) {
                        Text("Start new chat")
                    }
                },
                dismissButton = {
                    TextButton(
                        onClick = {
                            isShowingFrontChat = false
                            viewModel.reset()
                        }
                    ) {
                        Text("Dismiss")
                    }
                }
            )
        }
    }
    

Reference for FrontChatViewModel properties

Name

Type

Description

loadingStatus

FrontChatViewLoadingStatus

An enum with possible values:

  • idle
  • startedLoading
  • finishedLoading
  • failedLoading

loadingError

Error?

An instance of Error returned by the webview on navigation failure. Corresponds to loadingStatus == failedLoading.

didEncounterUnrecoverableError

Bool

Set to true if the web app loaded by the webview encounters an exception. On the web, the user is prompted to refresh.

unrecoverableErrorMessage

String?

A human readable message populated when didEncounterUnrecoverableError is set to true.