Skip to main content

Requirements

Before you begin, ensure your development environment meets the following requirements:
  • Android Studio: Latest stable version
  • Android SDK: API 26 (Android 8.0) or higher
  • Gradle: 7.0 or higher
  • Kotlin: 1.8.0 or higher (recommended)
  • Device: Android device with Vulkan support (most modern devices)

Step 1: Add Dependency

Add the SDK dependency to your build.gradle (Module: app) file:
  • Gradle (Kotlin DSL)
  • Gradle (Groovy)

Using Gradle Kotlin DSL

build.gradle.kts
dependencies {
    implementation("ai.spatialwalk:avatarkit:1.0.0")
}

Step 2: Initialize SDK

Initialize the SDK in your Application class or Activity:
MainActivity.kt
import net.spatialwalk.androidsdk.AvatarKit

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // Initialize SDK
        AvatarKit.initialize(
            context = applicationContext,
            appId = "your-app-id",
            configuration = AvatarKit.Configuration(
                environment = AvatarKit.Environment.TEST // or CN, US
            )
        )
        
        // Set session token if needed
        AvatarKit.sessionToken = "your-session-token"
    }
}

Step 3: Load Avatar

Load an avatar using AvatarManager:
loadAvatar.kt
import net.spatialwalk.androidsdk.assets.AvatarManager
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

lifecycleScope.launch {
    val avatar = withContext(Dispatchers.IO) {
        AvatarManager.load("avatar-id") { progress ->
            when (progress) {
                is AvatarManager.LoadProgress.Downloading -> {
                    val percent = (progress.progress * 100).toInt()
                    Log.d(TAG, "Loading: $percent%")
                }
                is AvatarManager.LoadProgress.Completed -> {
                    Log.d(TAG, "Avatar loaded")
                }
                is AvatarManager.LoadProgress.Failed -> {
                    Log.e(TAG, "Failed: ${progress.error.message}")
                }
            }
        }
    }
}

Step 4: Create View and Start Rendering

Add AvatarView to your layout and initialize it:
createView.kt
import net.spatialwalk.androidsdk.AvatarView
import androidx.compose.ui.viewinterop.AndroidView

// In your Activity/Fragment
val avatarView = findViewById<AvatarView>(R.id.avatar_view)
// Or in Compose
AndroidView(
    factory = { context -> AvatarView(context) }
)

// Initialize with avatar
avatarView.init(avatar, lifecycleScope)

// Set up callbacks
avatarView.avatarController.onConnectionState = { state ->
    Log.d(TAG, "Connection state: $state")
}

avatarView.avatarController.onAvatarState = { state ->
    Log.d(TAG, "Avatar state: $state")
}

avatarView.avatarController.onError = { error ->
    Log.e(TAG, "Error: ${error.message}")
}

// Start real-time communication
avatarView.avatarController.start()

Complete Example

Complete Example
import net.spatialwalk.androidsdk.AvatarKit
import net.spatialwalk.androidsdk.AvatarView
import net.spatialwalk.androidsdk.assets.AvatarManager
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

class MainActivity : AppCompatActivity() {
    private lateinit var avatarView: AvatarView
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 1. Initialize SDK
        AvatarKit.initialize(
            context = applicationContext,
            appId = "your-app-id",
            configuration = AvatarKit.Configuration(
                environment = AvatarKit.Environment.TEST
            )
        )
        AvatarKit.sessionToken = "your-session-token"
        
        // 2. Load avatar
        avatarView = findViewById(R.id.avatar_view)
        lifecycleScope.launch {
            val avatar = withContext(Dispatchers.IO) {
                AvatarManager.load("avatar-id") { progress ->
                    when (progress) {
                        is AvatarManager.LoadProgress.Downloading -> {
                            val percent = (progress.progress * 100).toInt()
                            updateProgress("Loading: $percent%")
                        }
                        is AvatarManager.LoadProgress.Completed -> {
                            updateProgress("Avatar loaded")
                        }
                        is AvatarManager.LoadProgress.Failed -> {
                            updateProgress("Failed: ${progress.error.message}")
                        }
                    }
                }
            }
            
            // 3. Initialize view
            avatarView.init(avatar, lifecycleScope)
            
            // 4. Set up callbacks
            avatarView.avatarController.onConnectionState = { state ->
                Log.d(TAG, "Connection state: $state")
            }
            
            avatarView.avatarController.onAvatarState = { state ->
                Log.d(TAG, "Avatar state: $state")
            }
            
            avatarView.avatarController.onError = { error ->
                Log.e(TAG, "Error: ${error.message}")
            }
            
            // 5. Start real-time communication
            avatarView.avatarController.start()
            
            // 6. Send audio data
            sendAudioData()
        }
    }
    
    private fun sendAudioData() {
        lifecycleScope.launch {
            val audioData = readAudioFile() // Your audio reading logic
            avatarView.avatarController.send(audioData, end = false)
            
            // When audio ends
            avatarView.avatarController.send(audioData, end = true)
        }
    }
    
    override fun onPause() {
        super.onPause()
        avatarView.onPause()
    }
    
    override fun onResume() {
        super.onResume()
        avatarView.onResume()
    }
    
    override fun onDestroy() {
        super.onDestroy()
        lifecycleScope.launch {
            avatarView.avatarController.stop()
            avatarView.cleanup()
        }
    }
}

Step 5: Add Permissions

Add required permissions to your AndroidManifest.xml:
AndroidManifest.xml
<manifest>
    <!-- Internet permission for downloading avatar resources -->
    <uses-permission android:name="android.permission.INTERNET" />
    
    <!-- Optional: For audio recording -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
</manifest>

Step 6: Test Your Integration

  1. Run your app on a device or emulator with Vulkan support
  2. Check Logcat output to confirm SDK initialization
  3. Verify the avatar displays correctly
  4. Test audio-driven functionality
It’s recommended to test on a physical device for best performance and Vulkan support

Next Steps

Congratulations! You’ve successfully integrated SPAvatarKit Android SDK. Next, you can:

Troubleshooting

If you encounter issues during integration, please check:
  • FAQ - Common integration questions and answers