> For the complete documentation index, see [llms.txt](/llms.txt).

# Embedded Wallets SDK for Android

## Overview[​](#overview "Direct link to Overview")

MetaMask Embedded Wallets SDK (formerly Web3Auth Plug and Play) provides authentication for Android applications with social sign-in, external wallets, and more. Our Android SDK, written in Kotlin, simplifies how you connect users to their preferred wallets and manage authentication state natively.

## Requirements[​](#requirements "Direct link to Requirements")

- Android API version `26` or newer
- Android Compile and Target SDK: `34`
- Basic knowledge of Java or Kotlin development

## Prerequisites[​](#prerequisites "Direct link to Prerequisites")

- Set up your project on the [Embedded Wallets dashboard](https://developer.metamask.io/).

tip

See the [dashboard setup](/embedded-wallets/dashboard/) guide to learn more.

## Installation[​](#installation "Direct link to Installation")

Install the Web3Auth Android SDK by adding it to your project dependencies:

### 1. Add JitPack repository[​](#1-add-jitpack-repository "Direct link to 1. Add JitPack repository")

In your project-level Gradle file add JitPack repository:

```
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven { url "https://jitpack.io" } // <-- Add this line
    }
}

```

### 2. Add Web3Auth dependency[​](#2-add-web3auth-dependency "Direct link to 2. Add Web3Auth dependency")

Then, in your app-level `build.gradle` dependencies section, add the following:

```
dependencies {
    // ...
    implementation 'com.github.web3auth:web3auth-android-sdk:10.0.1'
}

```

2.1. Update permissions

Open your app's `AndroidManifest.xml` file and add the following permission. Ensure the `<uses-permission>` element is a direct child of the `<manifest>` root element.

```
<uses-permission android:name="android.permission.INTERNET" />

```

2.2 Configure `AndroidManifest.xml` File

Ensure your main activity `launchMode` is set to `singleTop` in your `AndroidManifest.xml`:

```
<activity
  android:launchMode="singleTop"
  android:name=".YourActivity">
  // ...
</activity>

```

From version **7.1.2**, set `android:allowBackup` to `false` and add `tools:replace="android:fullBackupContent"` in your `AndroidManifest.xml` file:

```
<application
        android:allowBackup="false"
        tools:replace="android:fullBackupContent"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher">
</application>

```

### 3. Handle redirects[​](#3-handle-redirects "Direct link to 3. Handle redirects")

Once the Gradle files and permissions have been updated, you need to configure your Embedded Wallets project by allowlisting your scheme and package name.

#### Configure a Plug n Play project[​](#configure-a-plug-n-play-project "Direct link to Configure a Plug n Play project")

- From the [Embedded Wallets dashboard](https://developer.metamask.io), create or open an existing Web3Auth project.
- Allowlist `{SCHEME}://{YOUR_APP_PACKAGE_NAME}` in the dashboard. This step is mandatory for the redirect to work.

#### Configure deep link[​](#configure-deep-link "Direct link to Configure deep link")

Open your app's `AndroidManifest.xml` file and add the following deep link intent filter to your main activity:

```
<intent-filter>
  <action android:name="android.intent.action.VIEW" />

  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />

  <data android:scheme="{scheme}" android:host="{YOUR_APP_PACKAGE_NAME}"/>
  <!-- Accept URIs: w3a://com.example.w3aflutter -->
</intent-filter>

```

### 4. Triggering sign-in exceptions[​](#4-triggering-sign-in-exceptions "Direct link to 4. Triggering sign-in exceptions")

note

The Android SDK uses the custom tabs and from current implementation of Chrome custom tab, it's not possible to add a listener directly to Chrome custom tab close button and trigger sign-in exceptions.

Apply the `setCustomTabsClosed` method in your sign-in screen to trigger sign-in exceptions for Android.

```
class MainActivity : AppCompatActivity() {
    // Additional code

    override fun onResume() {
        super.onResume()
        if (Web3Auth.getCustomTabsClosed()) {
            Toast.makeText(this, "User closed the browser.", Toast.LENGTH_SHORT).show()
            web3Auth.setResultUrl(null)
            Web3Auth.setCustomTabsClosed(false)
        }
    }

    // Additional code
}

```

## Initialize Embedded Wallets[​](#initialize-embedded-wallets "Direct link to Initialize Embedded Wallets")

### 1. Create an Embedded Wallets instance[​](#1-create-an-embedded-wallets-instance "Direct link to 1. Create an Embedded Wallets instance")

Create an Embedded Wallets instance and configure it with your project settings:

```
import com.web3auth.core.Web3Auth
import com.web3auth.core.types.Web3AuthOptions
import org.torusresearch.fetchnodedetails.types.Web3AuthNetwork

var web3Auth = Web3Auth(
  Web3AuthOptions(
    clientId = "YOUR_WEB3AUTH_CLIENT_ID", // Pass over your Web3Auth Client ID from Developer Dashboard
    web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET, // or Web3AuthNetwork.SAPPHIRE_DEVNET
    redirectUrl = "{YOUR_APP_PACKAGE_NAME}://auth",
  ),
  this
)

// Handle user signing in when app is in background
web3Auth.setResultUrl(intent?.data)

```

### 2. Set result URL[​](#2-set-result-url "Direct link to 2. Set result URL")

Whenever user initiates a sign-in flow, a new intent of CustomTabs is launched. It's necessary step to use `setResultUrl` in `onNewIntent` method to successful track the sign-in process.

```
override fun onNewIntent(intent: Intent?) {
  super.onNewIntent(intent)

  // Handle user signing in when app is active
  web3Auth.setResultUrl(intent.data)
}

```

### 3. Initialize the Embedded Wallets instance[​](#3-initialize-the-embedded-wallets-instance "Direct link to 3. Initialize the Embedded Wallets instance")

After instantiating Embedded Wallets, the next step is to initialize it using the `initialize` method. This method is essential for setting up the SDK, checking for any active sessions, and fetching the whitelabel configuration from your dashboard.

Once the `initialize` method executes successfully, you can use the `getPrivateKey` or `getEd25519PrivateKey` methods to verify if an active session exists. If there is no active session, these methods will return an empty string; otherwise, they will return the respective private key.

note

The `initialize` method may throw an error in the following situations:

- No active session exists for the user.
- A network error occurs while fetching the project configuration from the dashboard.
- Session validation fails (for example, the stored session token is invalid or expired).

Wrap the call in a `whenComplete` handler and treat any non-null error as a failed initialization rather than an absent session.

```
val initializeCF: CompletableFuture<Void> = web3Auth.initialize()
initializeCF.whenComplete { _, error ->
  if (error == null) {
    // Check for the active session
    if(web3Auth.getPrivateKey().isNotEmpty()) {
      // Active session found
    }
    // No active session is not present

  } else {
    // Handle the error
  }
}

```

## Advanced configuration[​](#advanced-configuration "Direct link to Advanced configuration")

The Web3Auth Android SDK offers a rich set of advanced configuration options:

- **[Custom authentication](/embedded-wallets/sdk/android/advanced/custom-authentication/):** Define authentication methods.
- **[Whitelabeling and UI customization](/embedded-wallets/sdk/android/advanced/whitelabel/):** Personalize the modal's appearance.
- **[Multi-Factor Authentication (MFA)](/embedded-wallets/sdk/android/advanced/mfa/):** Set up and manage MFA.
- **[Dapp Share](/embedded-wallets/sdk/android/advanced/dapp-share/):** Share dapp sessions across devices.

tip

See the [advanced configuration sections](/embedded-wallets/sdk/android/advanced/) to learn more about each configuration option.

- Basic Configuration
- Advanced Configuration

```
val web3Auth = Web3Auth(
    Web3AuthOptions(
        clientId = "YOUR_CLIENT_ID",
        web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET, // or Web3AuthNetwork.SAPPHIRE_DEVNET
        redirectUrl = "YOUR_APP_SCHEME://auth"
    ),
    this
)

```

```
val web3Auth = Web3Auth(
    Web3AuthOptions(
        clientId = "YOUR_CLIENT_ID",
        web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET, // or Web3AuthNetwork.SAPPHIRE_DEVNET
        redirectUrl = "YOUR_APP_SCHEME://auth",
        authConnectionConfig = listOf(AuthConnectionConfig(
          authConnectionId = "auth-connection-id", // Get it from MetaMask Developer Dashboard
          authConnection = AuthConnection.GOOGLE,
          clientId = getString(R.string.google_client_id) // Google's client id
        )),
        mfaSettings = MfaSettings(
          deviceShareFactor = MfaSetting(true, 1, true),
          socialBackupFactor = MfaSetting(true, 2, true),
          passwordFactor = MfaSetting(true, 3, false),
          backUpShareFactor = MfaSetting(true, 4, false),
          passkeysFactor = MfaSetting(true, 5, true),
          authenticatorFactor = MfaSetting(true, 6, true),
        )
    ),
    this
)

```

## Single Factor Auth (SFA) Support[​](#single-factor-auth-sfa-support "Direct link to Single Factor Auth (SFA) Support")

Web3Auth Android SDK includes built-in support for Single Factor Auth (SFA), allowing for seamless authentication when you already have a JWT token from your authentication system. When MFA is disabled, users won't even notice Web3Auth's presence; they'll be automatically authenticated using just your JWT token, making the sign-in experience frictionless.

```
// SFA sign-in with custom JWT
val loginCompletableFuture = web3Auth.connectTo(
    LoginParams(
        AuthConnection.CUSTOM,
        authConnectionId = "your_verifier_id",
        idToken = "your_jwt_token"
    )
)

```

SFA mode is automatically activated when you provide an `idToken` parameter. This enables direct authentication without additional social sign-in steps, perfect for applications that already have their own authentication system.

## Blockchain Integration[​](#blockchain-integration "Direct link to Blockchain Integration")

Embedded Wallets is blockchain agnostic, enabling integration with any blockchain network. Out of the box, Embedded Wallets offers robust support for both **Solana** and **Ethereum**.

### Ethereum integration[​](#ethereum-integration "Direct link to Ethereum integration")

For Ethereum integration, you can get the private key using the `getPrivateKey` method and use it with web3j or other Ethereum libraries:

```
import org.web3j.crypto.Credentials
import org.web3j.protocol.core.DefaultBlockParameterName
import org.web3j.protocol.Web3j
import org.web3j.protocol.http.HttpService

// Use your Web3Auth instance to get the private key
val privateKey = web3Auth.getPrivateKey()

// Generate the Credentials
val credentials = Credentials.create(privateKey)

// Get the address
val address = credentials.address

// Create the Web3j instance using your RPC URL
val web3 = Web3j.build(HttpService("YOUR_RPC_URL"))

// Get the balance
val balanceResponse = web3.ethGetBalance(address, DefaultBlockParameterName.LATEST).send()

// Convert the balance from Wei to Ether format
val ethBalance = BigDecimal.valueOf(balanceResponse.balance.toDouble()).divide(BigDecimal.TEN.pow(18))

```

### Solana integration[​](#solana-integration "Direct link to Solana integration")

For Solana integration, you can get the Ed25519 private key using the `getEd25519PrivateKey` method and use it with sol4k or any other Solana libraries:

```
import org.sol4k.Connection
import org.sol4k.Keypair

val connection = Connection(RpcUrl.DEVNET)

// Use your Web3Auth instance to get the private key
val ed25519PrivateKey = web3Auth.getEd25519PrivateKey()

// Generate the Solana KeyPair
val solanaKeyPair = Keypair.fromSecretKey(ed25519PrivateKey.hexToByteArray())

// Get the user's public key
val publicKey = solanaKeyPair.publicKey.toBase58()

// Get the user balance
val userBalance = connection.getBalance(publicKey).toBigDecimal()

```
