Known Limitations
Please review the following requirements and limitations before using the SDK.
Device Requirements
| Item | OpenCL Minimum | OpenCL Recommended |
|---|---|---|
| Android Version | 8.0 (API 26) | 12+ (API 31) |
| RAM | 4GB | 6GB or more |
| Storage | 500MB | 1GB or more |
| GPU | OpenGL ES 2.0 / OpenCL 1.2 | OpenGL ES 3.0+ / OpenCL 2.0+ |
Supported Architectures (ABI)
| ABI | Supported | Notes |
|---|---|---|
arm64-v8a | Supported | Most modern devices |
armeabi-v7a | Supported | Older 32-bit devices |
x86_64 | Not supported | Emulator |
x86 | Not supported | Emulator |
The SDK does not work on x86/x86_64 emulators.
Testing methods:
- Use a real Android device (recommended)
- Use an ARM-based emulator (e.g., default emulator on Apple Silicon Macs)
Network Requirements
Prerequisites
- Internet connection: Required for real-time WebSocket communication
- Protocol: HTTPS / WSS (TLS 1.2 or higher)
- Port: 443
Firewall Configuration
# Domains to allow
*.klleon.io
Network Permissions
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Audio Limitations
USB Microphone Compatibility
- MMAP policy: MMAP is managed internally by the SDK and is disabled by default. Enabling MMAP may cause stream open failures with some USB microphones.
- USB device selection: USB microphones are automatically detected and selected when connected.
- Incompatible devices: On some MediaTek-based TVs, opening audio streams from USB composite devices (e.g., DM30RGB) may fail.
Echo Prevention
- Voice recognition is automatically blocked during avatar speech.
Known Issues
1. Memory Usage
Memory usage can be high during video processing and AI inference. In particular, calling ResourceManager.init() allocates approximately 1GB of native memory for YUV frame buffers.
Buffer Lifecycle
finish() retains buffers for immediate reuse when re-entering with the same avatar (0ms). For complete memory release, deinit() must be explicitly called.
| Scenario | Behavior |
|---|---|
| Same avatar re-entry | init(same avatarId) -> Buffer reuse (0ms) |
| Different avatar switch | init(new avatarId) -> Automatically release previous buffer + new allocation |
| App background transition | onTrimMemory -> deinit() -> Buffer release |
| App exit | CharacterActivity.onDestroy -> deinit() -> Complete release |
| Process force kill | OS kernel auto-reclaims (no code needed) |
Required Implementation Patterns
Application class -- Automatic background memory release:
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
registerComponentCallbacks(object : ComponentCallbacks2 {
override fun onTrimMemory(level: Int) {
if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
ResourceManager.deinit()
}
}
override fun onConfigurationChanged(newConfig: Configuration) {}
override fun onLowMemory() { ResourceManager.deinit() }
})
}
}
SDK play screen (ChatActivity, etc.):
override fun onDestroy() {
super.onDestroy()
// finish() is a suspend function, so run it in a coroutine
CoroutineScope(Dispatchers.Default).launch {
klleonOndeviceSdk.finish() // Retain buffers (waiting for reuse)
}
}
Avatar selection screen (CharacterActivity, etc.):
override fun onDestroy() {
super.onDestroy()
// Manually release memory if SDK is not playing (exiting before play)
if (!KlleonOndeviceSdk.playing) {
ResourceManager.deinit()
}
}
init(): When called again with the same avatar (avatarId), reuses existing buffer (no duplicate allocation)deinit(): Safe to call multiple times (idempotency guaranteed)finish(): Safe for duplicate calls due to internal playing state check
2. Background Limitations
Video processing is paused when the app transitions to the background.
3. Single Instance Limitation
Only one KlleonOndeviceSdk instance should be created per app.
Internal coroutine scopes and thread pools are allocated per instance, so creating multiple instances causes resource conflicts and memory leaks.
Recommended: Manage as an object singleton
// Share a single instance across the entire app
object SdkConfig {
val sdk = KlleonOndeviceSdk()
}
// Use in Activity
class ChatActivity : ComponentActivity() {
private val klleonOndeviceSdk = SdkConfig.sdk // Reuse the same instance
}
class AnotherActivity : ComponentActivity() {
private val klleonOndeviceSdk = SdkConfig.sdk // Reuse the same instance
}
If you create KlleonOndeviceSdk() directly in an Activity field, a new instance is created each time the Activity is recreated (screen rotation, low memory, etc.), causing thread pools from previous instances to accumulate.
// Incorrect usage - multiple instances
class MainActivity : Activity() {
val sdk1 = KlleonOndeviceSdk() // Instance 1
val sdk2 = KlleonOndeviceSdk() // Instance 2 - conflict!
}
4. Screen Rotation
SDK state may be reset when an Activity is recreated due to screen rotation.
Solution:
<!-- AndroidManifest.xml - Handle screen rotation directly -->
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize|screenLayout" />
5. Android TV Specifics
- On TV platforms, auto-focus is assigned to the first focusable element on layout changes, which may cause the keyboard to appear automatically.
- Block this at the source with
focusProperties { canFocus = false }, then enable only on click. - Some MediaTek-based TVs may have compatibility issues with certain USB audio devices.
Performance Optimization Tips
GPU Acceleration
The SDK uses GPU acceleration by default. If issues occur on some low-end devices:
// Check logs when GPU issues occur
adb logcat | grep "Klleon_"
Battery Optimization
Battery consumption can be significant during prolonged use:
- Call
finish()when not in use - Recommended to stop processing when the screen is off
- Utilize standby mode with
enterStandby()/exitStandby()
Support
For issues not resolved by the above limitations, please contact us through Klleon Studio.