# Android Quickstart

**Example Repository**

- [Android Quickstart Repo](https://github.com/clerk/clerk-android/tree/main/samples/quickstart)

**Before you start**

- [Set up a Clerk application](https://clerk.com/docs/getting-started/quickstart/setup-clerk.md?sdk=android)

1. ## Enable Native API

   In the Clerk Dashboard, navigate to the [**Native applications**](https://dashboard.clerk.com/~/native-applications) page and ensure that the Native API is enabled. This is required to integrate Clerk in your native application.
2. ## Create a new Android app

   1. If you don't already have an Android app, create a new project in Android Studio using the **Empty Activity** template. This tutorial uses `MyClerkApp` as the app name. If your app has a different name, be sure to update any code examples accordingly to match your app's name.

   2. Open the `app/build.gradle.kts` file and ensure that your project's minimum SDK version is set to 24 or higher, and that your project's Java version is set to 17 or higher, as these are the minimum requirements for the Clerk Android SDK.

   3. In `app/build.gradle.kts`, add the following libraries to your `dependencies` block:

      - The Clerk Android SDK. Check the [GitHub release page](https://github.com/clerk/clerk-android/releases) for the latest version. The SDK is split into two packages:
        - `com.clerk:clerk-android-api` - The core Clerk SDK for authentication and user management.
        - `com.clerk:clerk-android-ui` - The Clerk UI components for authentication and user management.

      - [Android's Lifecycle ViewModel Compose library](https://developer.android.com/reference/kotlin/androidx/lifecycle/viewmodel/compose/package-summary).

        ```gradle
        dependencies {
            ...
            // Only if you're using the Clerk API without the Clerk UI components
            implementation("com.clerk:clerk-android-api:<latest-version>")

            implementation("com.clerk:clerk-android-ui:<latest-version>")
            implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.9.2")
            ...
        }
        ```

   4. Sync your project to apply the changes after adding the dependencies.
3. ## Initialize Clerk

   In `app/src/main/java/com/example/myclerkapp/`, create a Kotlin class named `MyClerkApp`. Add the following code to:

   1. Create a subclass of `Application` named after your application (e.g., `MyClerkApp`).
   2. In this subclass, override the `onCreate()` method and call `Clerk.initialize()` to initialize the Clerk Android SDK with your application context (`this`) and Clerk Publishable Key.

   1) Create a subclass of `Application` named after your application (e.g., `MyClerkApp`).
   2) In this subclass, override the `onCreate()` method and call `Clerk.initialize()` to initialize the Clerk Android SDK with your application context (`this`) and Clerk Publishable Key.

   To find your Publishable Key:

   1. In the Clerk Dashboard, navigate to the [**API keys**](https://dashboard.clerk.com/~/api-keys) page.
   2. Copy your Clerk Publishable Key. It's prefixed with `pk_test_` for development instances and `pk_live_` for production instances.

   filename: app/src/main/java/com/example/myclerkapp/MyClerkApp.kt

   ```kotlin
     package com.example.myclerkapp

     import android.app.Application
     import com.clerk.api.Clerk

     class MyClerkApp: Application() {
         override fun onCreate() {
           super.onCreate()
           Clerk.initialize(
               this,
               publishableKey = "{{pub_key}}"
           )
         }
     }
   ```
4. ## Configure the `AndroidManifest.xml`

   In `app/src/main/AndroidManifest.xml`, add the following configuration:

   1. Inside the root `<manifest>` tag, add the following line to enable internet permission on your Android device.

      ```xml
      <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
          <uses-permission android:name="android.permission.INTERNET"/>
          ...
      </manifest>
      ```

   2. Inside the `<application>` tag, add the following line to use the `MyClerkApp` class as the entry point for app-level configuration.

      ```xml
      <application android:name=".MyClerkApp">
          ...
      </application>
      ```
5. ## Listen for SDK initialization and authentication events

   Let's start building out your home page.

   In your `app/src/main/java/com/example/myclerkapp/` directory, create a Kotlin class named `MainViewModel` with the following code. `MainViewModel` is a `ViewModel` that sets the state as `Loading` when the Clerk SDK is initializing, `SignedIn` when the user is signed in, or `SignedOut` when the user is signed out. The Clerk SDK initialization is non-blocking. Therefore, it's recommended to listen for the SDK to emit a success from Clerk's `isInitialized` global object to know when it's ready to use.

   filename: app/src/main/java/com/example/myclerkapp/MainViewModel.kt

   ```kotlin
   package com.example.myclerkapp

   import android.util.Log
   import androidx.lifecycle.ViewModel
   import androidx.lifecycle.viewModelScope
   import com.clerk.api.Clerk
   import kotlinx.coroutines.flow.MutableStateFlow
   import kotlinx.coroutines.flow.asStateFlow
   import kotlinx.coroutines.flow.combine
   import kotlinx.coroutines.flow.launchIn

   class MainViewModel: ViewModel() {
       private val _uiState = MutableStateFlow<MainUiState>(MainUiState.Loading)
       val uiState = _uiState.asStateFlow()
       init {
           combine(Clerk.isInitialized, Clerk.userFlow) { isInitialized, user ->
               _uiState.value = when {
                 !isInitialized -> MainUiState.Loading
                 user != null -> MainUiState.SignedIn
                 else -> MainUiState.SignedOut
               }
           }
           .launchIn(viewModelScope)
       }
   }
   sealed interface MainUiState {
       data object Loading : MainUiState
       data object SignedIn : MainUiState
       data object SignedOut : MainUiState
   }
   ```
6. ## Conditionally render content

   Now that you're listening for initialization and authentication events, set up your UI to react to them. In your `MainActivity.kt`, add the following code. This will show a loading indicator while the Clerk SDK is initializing, and a signed in or signed out experience based on the user's authentication state.

   filename: app/src/main/java/com/example/myclerkapp/MainActivity.kt

   ```kotlin
   package com.example.myclerkapp

   import android.os.Bundle
   import androidx.activity.ComponentActivity
   import androidx.activity.compose.setContent
   import androidx.activity.viewModels
   import androidx.compose.runtime.getValue
   import androidx.compose.foundation.layout.Box
   import androidx.compose.foundation.layout.fillMaxSize
   import androidx.compose.material3.CircularProgressIndicator
   import androidx.compose.material3.Text
   import androidx.compose.ui.Alignment
   import androidx.compose.ui.Modifier
   import androidx.lifecycle.compose.collectAsStateWithLifecycle

   class MainActivity : ComponentActivity() {

     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setContent {

             val viewModel: MainViewModel by viewModels()
             val state by viewModel.uiState.collectAsStateWithLifecycle()

             Box(
                 modifier = Modifier.fillMaxSize(),
                 contentAlignment = Alignment.Center
             ) {
                 when (state) {
                     MainUiState.Loading -> CircularProgressIndicator()
                     MainUiState.SignedOut -> Text("You're signed out")
                     MainUiState.SignedIn -> Text("You're signed in")
                 }
             }
         }
     }
   }
   ```
7. ## Create sign-up and sign-in views
8. ### Sign-up view

   Create a Kotlin class named `SignUpViewModel` with the following code. It allows users to sign up using their email address and password, and sends an email verification code to confirm their email address.

   filename: app/src/main/java/com/example/myclerkapp/SignUpViewModel.kt

   ```kotlin
   package com.example.myclerkapp

   import android.util.Log
   import androidx.lifecycle.ViewModel
   import androidx.lifecycle.viewModelScope
   import com.clerk.api.Clerk
   import com.clerk.api.network.serialization.errorMessage
   import com.clerk.api.network.serialization.onFailure
   import com.clerk.api.network.serialization.onSuccess
   import com.clerk.api.signup.SignUp
   import com.clerk.api.signup.attemptVerification
   import com.clerk.api.signup.prepareVerification
   import kotlinx.coroutines.flow.MutableStateFlow
   import kotlinx.coroutines.flow.asStateFlow
   import kotlinx.coroutines.launch


   class SignUpViewModel : ViewModel() {
     private val _uiState = MutableStateFlow<SignUpUiState>(SignUpUiState.SignedOut)
     val uiState = _uiState.asStateFlow()

     fun signUp(email: String, password: String) {
         viewModelScope.launch {
             SignUp.create(SignUp.CreateParams.Standard(emailAddress = email, password = password))
                 .onSuccess {
                     if (it.status == SignUp.Status.COMPLETE) {
                         _uiState.value = SignUpUiState.Success
                     } else {
                         _uiState.value = SignUpUiState.NeedsVerification
                         it.prepareVerification(SignUp.PrepareVerificationParams.Strategy.EmailCode())
                     }
                 }
                 .onFailure {
                     // See https://clerk.com/docs/guides/development/custom-flows/error-handling
                     // for more info on error handling
                     Log.e("SignUpViewModel", it.errorMessage, it.throwable)
                 }
         }
     }

     fun verify(code: String) {
         val inProgressSignUp = Clerk.auth.currentSignUp ?: return

         viewModelScope.launch {
             inProgressSignUp
                 .attemptVerification(SignUp.AttemptVerificationParams.EmailCode(code))
                 .onSuccess { _uiState.value = SignUpUiState.Success }
                 .onFailure {
                     // See https://clerk.com/docs/guides/development/custom-flows/error-handling
                     // for more info on error handling
                     Log.e("SignUpViewModel", it.errorMessage, it.throwable)
                 }
         }
     }

     sealed interface SignUpUiState {
         data object SignedOut : SignUpUiState
         data object Success : SignUpUiState
         data object NeedsVerification : SignUpUiState
     }
   }
   ```

   Then, create a `SignUpView` file with the following code to use the `SignUpViewModel`.

   filename: app/src/main/java/com/example/myclerkapp/SignUpView\.kt

   ```kotlin
   package com.example.myclerkapp

   import androidx.compose.foundation.layout.Arrangement
   import androidx.compose.foundation.layout.Column
   import androidx.compose.material3.Button
   import androidx.compose.material3.Text
   import androidx.compose.material3.TextField
   import androidx.compose.runtime.Composable
   import androidx.compose.runtime.collectAsState
   import androidx.compose.runtime.mutableStateOf
   import androidx.compose.runtime.remember
   import androidx.compose.runtime.getValue
   import androidx.compose.runtime.setValue
   import androidx.compose.ui.Alignment
   import androidx.compose.ui.text.input.PasswordVisualTransformation
   import androidx.compose.ui.unit.dp
   import androidx.lifecycle.viewmodel.compose.viewModel


   @Composable
   fun SignUpView(viewModel: SignUpViewModel = viewModel()) {

     val state by viewModel.uiState.collectAsState()

     Column(
         horizontalAlignment = Alignment.CenterHorizontally,
         verticalArrangement = Arrangement.spacedBy(24.dp, Alignment.CenterVertically)
     ) {
         Text("Sign Up")

         if (state is SignUpViewModel.SignUpUiState.NeedsVerification) {
             var code by remember { mutableStateOf("") }

             TextField(value = code, onValueChange = { code = it })

             Button(onClick = { viewModel.verify(code) }) { Text("Verify") }
         } else {
             var email by remember { mutableStateOf("") }
             var password by remember { mutableStateOf("") }

             TextField(value = email, onValueChange = { email = it }, placeholder = { Text("Email") })

             TextField(
                 value = password,
                 placeholder = { Text("Password") },
                 onValueChange = { password = it },
                 visualTransformation = PasswordVisualTransformation(),
             )

             Button(onClick = { viewModel.signUp(email, password) }) { Text("Sign Up") }
         }
     }
   }
   ```
9. ### Sign-in view

   Create a Kotlin class named `SignInViewModel` with the following code. It allows users to sign in using their email address and password.

   filename: app/src/main/java/com/example/myclerkapp/SignInViewModel.kt

   ```kotlin
   package com.example.myclerkapp

   import androidx.lifecycle.ViewModel
   import androidx.lifecycle.viewModelScope
   import com.clerk.api.network.serialization.onFailure
   import com.clerk.api.network.serialization.onSuccess
   import com.clerk.api.signin.SignIn
   import kotlinx.coroutines.flow.MutableStateFlow
   import kotlinx.coroutines.flow.asStateFlow
   import kotlinx.coroutines.launch

   class SignInViewModel : ViewModel() {

     private val _uiState = MutableStateFlow<SignInUiState>(SignInUiState.Idle)
     val uiState = _uiState.asStateFlow()

     fun signIn(email: String, password: String) {
         viewModelScope.launch {
             SignIn.create(SignIn.CreateParams.Strategy.Password(identifier = email, password = password))
                 .onSuccess { _uiState.value = SignInUiState.Success }
                 .onFailure { _uiState.value = SignInUiState.Error }
         }
     }

     sealed interface SignInUiState {
         data object Idle : SignInUiState

         data object Error : SignInUiState

         data object Success : SignInUiState
     }
   }
   ```

   Then, create a `SignInView` file with the following code to use the `SignInViewModel`.

   filename: app/src/main/java/com/example/myclerkapp/SignInView\.kt

   ```kotlin
   package com.example.myclerkapp

   import androidx.compose.foundation.layout.Arrangement
   import androidx.compose.foundation.layout.Column
   import androidx.compose.material3.Button
   import androidx.compose.material3.Text
   import androidx.compose.material3.TextField
   import androidx.compose.runtime.Composable
   import androidx.compose.runtime.mutableStateOf
   import androidx.compose.runtime.remember
   import androidx.compose.runtime.getValue
   import androidx.compose.runtime.setValue
   import androidx.compose.ui.Alignment
   import androidx.compose.ui.text.input.PasswordVisualTransformation
   import androidx.compose.ui.unit.dp
   import androidx.lifecycle.viewmodel.compose.viewModel


   @Composable
   fun SignInView(viewModel: SignInViewModel = viewModel()) {

     var email by remember { mutableStateOf("") }
     var password by remember { mutableStateOf("") }

     Column(
         horizontalAlignment = Alignment.CenterHorizontally,
         verticalArrangement = Arrangement.spacedBy(24.dp, Alignment.CenterVertically)
     ) {
         Text("Sign In")
         TextField(value = email, onValueChange = { email = it }, placeholder = { Text("Email") })
         TextField(
             value = password,
             onValueChange = { password = it },
             placeholder = { Text("password") },
             visualTransformation = PasswordVisualTransformation(),
         )
         Button(onClick = { viewModel.signIn(email, password) }) { Text("Sign In") }
     }
   }
   ```
10. ### Combine the views

    Commonly, authentication flows will allow users to switch between sign up and sign in, such as a "Already signed up? Sign in" button. To add this to your app, create a `SignInOrUpView` file with the following code. This container view combines the `SignUpView` and `SignInView`, and allows users to switch between them.

    filename: app/src/main/java/com/example/myclerkapp/SignInOrUpView\.kt

    ```kotlin
    package com.example.myclerkapp

    import androidx.compose.foundation.layout.Arrangement
    import androidx.compose.foundation.layout.Column
    import androidx.compose.foundation.layout.fillMaxSize
    import androidx.compose.material3.Button
    import androidx.compose.material3.Text
    import androidx.compose.runtime.Composable
    import androidx.compose.runtime.mutableStateOf
    import androidx.compose.runtime.remember
    import androidx.compose.runtime.getValue
    import androidx.compose.runtime.setValue
    import androidx.compose.ui.Alignment
    import androidx.compose.ui.Modifier
    import androidx.compose.ui.unit.dp

    @Composable
    fun SignInOrUpView() {
      var isSignUp by remember { mutableStateOf(true) }

      Column(
          modifier = Modifier.fillMaxSize(),
          horizontalAlignment = Alignment.CenterHorizontally,
          verticalArrangement = Arrangement.spacedBy(24.dp, Alignment.CenterVertically),
      ) {
          if (isSignUp) {
              SignUpView()
          } else {
              SignInView()
          }

          Button(onClick = { isSignUp = !isSignUp }) {
              if (isSignUp) {
                Text("Already have an account? Sign in")
              } else {
                Text("Don't have an account? Sign up")
              }
          }
      }
    }
    ```

    Then, in your `MainActivity` file, render your newly created `SignInOrUpView` when the user isn't signed in.

    filename: app/src/main/java/com/example/myclerkapp/MainActivity.kt

    ```kotlin
    package com.example.myclerkapp

    import android.os.Bundle
    import androidx.activity.ComponentActivity
    import androidx.activity.compose.setContent
    import androidx.activity.viewModels
    import androidx.compose.runtime.getValue
    import androidx.compose.foundation.layout.Box
    import androidx.compose.foundation.layout.fillMaxSize
    import androidx.compose.material3.CircularProgressIndicator
    import androidx.compose.material3.Text
    import androidx.compose.ui.Alignment
    import androidx.compose.ui.Modifier
    import androidx.lifecycle.compose.collectAsStateWithLifecycle

    class MainActivity : ComponentActivity() {

      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContent {

              val viewModel: MainViewModel by viewModels()
              val state by viewModel.uiState.collectAsStateWithLifecycle()

              Box(
                  modifier = Modifier.fillMaxSize(),
                  contentAlignment = Alignment.Center
              ) {
                  when (state) {
                      MainUiState.Loading -> CircularProgressIndicator()
                      MainUiState.SignedOut -> SignInOrUpView()
                      MainUiState.SignedIn -> Text("You're signed in")
                  }
              }
          }
      }
    }
    ```
11. ## Allow users to sign out

    Finally, provide users with a way to sign out of your app.

    In your `MainViewModel`, add a `signOut` function that calls `Clerk.auth.signOut()`.

    filename: app/src/main/java/com/example/myclerkapp/MainViewModel.kt

    ```kotlin
    package com.example.myclerkapp

    import android.util.Log
    import androidx.lifecycle.ViewModel
    import androidx.lifecycle.viewModelScope
    import com.clerk.api.Clerk
    import com.clerk.api.network.serialization.errorMessage
    import com.clerk.api.network.serialization.onFailure
    import com.clerk.api.network.serialization.onSuccess
    import kotlinx.coroutines.flow.MutableStateFlow
    import kotlinx.coroutines.flow.asStateFlow
    import kotlinx.coroutines.flow.combine
    import kotlinx.coroutines.flow.launchIn
    import kotlinx.coroutines.launch

    class MainViewModel: ViewModel() {
      private val _uiState = MutableStateFlow<MainUiState>(MainUiState.Loading)
      val uiState = _uiState.asStateFlow()

      init {
          combine(Clerk.isInitialized, Clerk.userFlow) { isInitialized, user ->
              _uiState.value = when {
                !isInitialized -> MainUiState.Loading
                user != null -> MainUiState.SignedIn
                else -> MainUiState.SignedOut
              }
          }
          .launchIn(viewModelScope)
      }

      fun signOut() {
          viewModelScope.launch() {
              Clerk.auth.signOut()
              .onSuccess { _uiState.value = MainUiState.SignedOut }
              .onFailure {
                  // See https://clerk.com/docs/guides/development/custom-flows/error-handling
                  // for more info on error handling
                  Log.e("MainViewModel", it.errorMessage, it.throwable)
              }
          }
      }
    }

    sealed interface MainUiState {
      data object Loading : MainUiState
      data object SignedIn : MainUiState
      data object SignedOut : MainUiState
    }
    ```

    Then, in your `MainActivity`, add a button that calls the `signOut` function when clicked.

    filename: app/src/main/java/com/example/myclerkapp/MainActivity.kt

    ```kotlin
    package com.example.myclerkapp

    import android.os.Bundle
    import androidx.activity.ComponentActivity
    import androidx.activity.compose.setContent
    import androidx.activity.viewModels
    import androidx.compose.runtime.getValue
    import androidx.compose.foundation.layout.Box
    import androidx.compose.foundation.layout.fillMaxSize
    import androidx.compose.material3.Button
    import androidx.compose.material3.CircularProgressIndicator
    import androidx.compose.material3.Text
    import androidx.compose.ui.Alignment
    import androidx.compose.ui.Modifier
    import androidx.lifecycle.compose.collectAsStateWithLifecycle

    class MainActivity : ComponentActivity() {

      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContent {

              val viewModel: MainViewModel by viewModels()
              val state by viewModel.uiState.collectAsStateWithLifecycle()

              Box(
                  modifier = Modifier.fillMaxSize(),
                  contentAlignment = Alignment.Center
              ) {
                  when (state) {
                      MainUiState.Loading -> CircularProgressIndicator()
                      MainUiState.SignedOut -> SignInOrUpView()
                      MainUiState.SignedIn -> Button(onClick = { viewModel.signOut() }) { Text("Sign out") }
                  }
              }
          }
      }
    }
    ```
12. ## Run your project

    In Android Studio, select `Run ▶︎` to build and launch the app.
13. ## Create your first user

    Once the app launches successfully, tap "Sign up" and authenticate to create your first user.

## Next steps

Learn more about Clerk views, how to customize them, and explore the Clerk Android SDK using the following guides.

- [Prebuilt views](https://clerk.com/docs/android/reference/views/overview.md): Learn how to quickly add authentication to your app using Clerk's suite of views.
- [Customization with ClerkTheme](https://clerk.com/docs/android/guides/customizing-clerk/clerk-theme.md): Learn how to customize Clerk views using&#x20;
- [Add native Sign in with Google](https://clerk.com/docs/guides/configure/auth-strategies/sign-in-with-google.md?sdk=android): Learn how to add native Sign in with Google to your Clerk apps on Android platforms.
- [Clerk Android SDK Reference](https://clerk.com/docs/reference/native-mobile/overview.md?sdk=android): Learn about the Clerk Android SDK and how to integrate it into your app.

---

## Sitemap

[Overview of all docs pages](https://clerk.com/docs/llms.txt)
