Android Troubleshooting Guide
This guide addresses Android-specific issues and solutions when integrating the Squad SDK.
Installation Issues
Gradle Integration
Issue: Dependency Resolution
Error: Failed to resolve: com.withsquad.sdk:squadline:1.0.0
Solutions:
- Check repositories in settings.gradle:
dependencyResolutionManagement {
repositories {
mavenCentral()
}
}
- Force dependency refresh:
./gradlew clean build --refresh-dependencies
Version Conflicts
Issue: Dependency Version Conflicts
Error: Duplicate class found
Solutions:
- Add resolution strategy:
configurations.all {
resolutionStrategy {
force 'com.withsquad.sdk:squadline:1.0.0'
}
}
- Check dependency tree:
./gradlew app:dependencies
Build Issues
ProGuard/R8
Issue: ProGuard Optimization Failures
Error: Class not found after ProGuard optimization
Solutions:
- Add ProGuard rules:
-keep class com.withsquad.sdk.** { *; }
-keepclassmembers class com.withsquad.sdk.** { *; }
- Check mapping file:
build/outputs/mapping/release/mapping.txt
Architecture Issues
Issue: ABI Compatibility
Error: Unable to load native library
Solutions:
- Configure ABI filters:
android {
defaultConfig {
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}
}
}
WebView Issues
WebView Loading
Issue: Content Loading Failures
Error: WebView failed to load content
Solutions:
- Configure WebView properly:
webView.settings.apply {
javaScriptEnabled = true
domStorageEnabled = true
mediaPlaybackRequiresUserGesture = false
}
webView.webViewClient = object : WebViewClient() {
override fun onReceivedError(
view: WebView?,
request: WebResourceRequest?,
error: WebResourceError?
) {
// Handle error
}
}
- Handle SSL errors:
webView.webViewClient = object : WebViewClient() {
override fun onReceivedSslError(
view: WebView?,
handler: SslErrorHandler?,
error: SslError?
) {
if (BuildConfig.DEBUG) {
handler?.proceed()
} else {
handler?.cancel()
}
}
}
JavaScript Bridge
Issue: Bridge Communication Failures
Error: JavaScript interface not working
Solutions:
- Verify bridge setup:
class SquadJSInterface(private val context: Context) {
@JavascriptInterface
fun postMessage(message: String) {
// Handle message
}
}
webView.addJavascriptInterface(SquadJSInterface(context), "SquadAndroid")
- Debug bridge messages:
webView.evaluateJavascript(
"(function() { return window.SquadBridge != null; })();"
) { result ->
Log.d("SquadSDK", "Bridge available: $result")
}
Audio Issues
AudioManager
Issue: Audio Configuration
Error: Failed to initialize audio system
Solutions:
- Configure audio settings:
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
audioManager.isSpeakerphoneOn = false
- Handle audio focus:
private val audioFocusRequest = AudioFocusRequest.Builder(
AudioManager.AUDIOFOCUS_GAIN
).run {
setAudioAttributes(AudioAttributes.Builder().run {
setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
build()
})
setAcceptsDelayedFocusGain(true)
setOnAudioFocusChangeListener { focusChange ->
// Handle focus change
}
build()
}
Permissions
Issue: Microphone Access
Error: Missing RECORD_AUDIO permission
Solutions:
- Check permissions:
private fun checkAudioPermission() {
if (ContextCompat.checkSelfPermission(
context,
Manifest.permission.RECORD_AUDIO
) != PackageManager.PERMISSION_GRANTED) {
requestAudioPermission()
}
}
private fun requestAudioPermission() {
ActivityCompat.requestPermissions(
activity,
arrayOf(Manifest.permission.RECORD_AUDIO),
PERMISSION_REQUEST_CODE
)
}
Memory Management
Memory Leaks
Issue: Memory Leaks
Error: Memory leak detected
Solutions:
- Handle activity lifecycle:
override fun onDestroy() {
webView.clearCache(true)
webView.clearHistory()
webView.destroy()
super.onDestroy()
}
- Monitor memory:
class MemoryMonitor {
fun logMemoryInfo(context: Context) {
val runtime = Runtime.getRuntime()
val usedMemInMB = (runtime.totalMemory() - runtime.freeMemory()) / 1048576L
Log.d("MemoryMonitor", "Used memory: $usedMemInMB MB")
}
}
Debug Tools
Logging
- Enable SDK logging:
SquadSDK.setLogLevel(LogLevel.DEBUG)
- Add debug interceptor:
class DebugInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
Log.d("SquadSDK", "Request: ${request.url}")
return chain.proceed(request)
}
}
Performance Monitoring
Monitor WebView performance:
webView.setWebViewClient(object : WebViewClient() {
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
startTime = System.currentTimeMillis()
}
override fun onPageFinished(view: WebView, url: String) {
val loadTime = System.currentTimeMillis() - startTime
Log.d("SquadSDK", "Page load time: $loadTime ms")
}
})
Configuration Changes
Handle configuration changes properly:
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
// Handle configuration change
webView.requestLayout()
}
Related Resources
- General Troubleshooting Guide
- Android Configuration Guide
- Android WebView Management
- ProGuard Configuration
Support
When contacting support, provide:
- Android Studio version
- Android OS version
- Device model
- SDK version
- Error logs
- Steps to reproduce
- Sample project (if possible)
- ProGuard mapping file (if applicable)