Skip to content

Commit 2640d0a

Browse files
Siddhesh2377claude
andcommitted
fix(android-app): single root Scaffold, dynamic TopBar, and deprecated API fixes
Scanned by claude-code, written by Siddhesh. - Add TopBarState with ConfigureTopBar/ConfigureCustomTopBar for dynamic top bar - Migrate all screens from AppScreenScaffold to root Scaffold in AppNavigation - Delete unused AppScreenScaffold.kt - Migrate deprecated ClickableText to Text with LinkAnnotation - Migrate deprecated LocalClipboardManager to LocalClipboard + ClipEntry - Replace all deprecated Icons with AutoMirrored variants - Remove unused @OptIn annotations and imports - Fix indentation inconsistencies from refactoring - Add imePadding to chat input Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent f605c9d commit 2640d0a

38 files changed

Lines changed: 1200 additions & 1268 deletions

examples/android/RunAnywhereAI/app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
<activity
4141
android:name=".MainActivity"
4242
android:exported="true"
43+
android:windowSoftInputMode="adjustResize"
4344
android:theme="@style/Theme.RunAnywhereAI">
4445
<intent-filter>
4546
<action android:name="android.intent.action.MAIN" />

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/MainActivity.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.runanywhere.runanywhereai
22

33
import android.os.Bundle
4-
import android.util.Log
4+
import timber.log.Timber
55
import androidx.activity.ComponentActivity
66
import androidx.activity.compose.setContent
77
import androidx.activity.enableEdgeToEdge
@@ -76,7 +76,7 @@ class MainActivity : ComponentActivity() {
7676
}
7777

7878
is SDKInitializationState.Ready -> {
79-
Log.i("MainActivity", "App is ready to use!")
79+
Timber.i("App is ready to use!")
8080
AppNavigation()
8181
}
8282
}

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/RunAnywhereApplication.kt

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package com.runanywhere.runanywhereai
33
import android.app.Application
44
import android.os.Handler
55
import android.os.Looper
6-
import android.util.Log
76
import com.runanywhere.runanywhereai.data.ModelList
87
import com.runanywhere.runanywhereai.presentation.settings.SettingsViewModel
98
import com.runanywhere.sdk.public.RunAnywhere
@@ -19,6 +18,7 @@ import kotlinx.coroutines.flow.StateFlow
1918
import kotlinx.coroutines.flow.asStateFlow
2019
import kotlinx.coroutines.launch
2120
import kotlinx.coroutines.withContext
21+
import timber.log.Timber
2222

2323
/**
2424
* Represents the SDK initialization state.
@@ -63,7 +63,11 @@ class RunAnywhereApplication : Application() {
6363
super.onCreate()
6464
instance = this
6565

66-
Log.i("RunAnywhereApp", "🏁 App launched, initializing SDK...")
66+
if (BuildConfig.DEBUG) {
67+
Timber.plant(Timber.DebugTree())
68+
}
69+
70+
Timber.i("App launched, initializing SDK...")
6771

6872
// Post initialization to main thread's message queue to ensure system is ready
6973
// This prevents crashes on devices where device-encrypted storage hasn't mounted yet
@@ -75,7 +79,7 @@ class RunAnywhereApplication : Application() {
7579
delay(200)
7680
initializeSDK()
7781
} catch (e: Exception) {
78-
Log.e("RunAnywhereApp", "❌ Fatal error during SDK initialization: ${e.message}", e)
82+
Timber.e(e, "❌ Fatal error during SDK initialization: ${e.message}")
7983
// Don't crash the app - let it continue without SDK
8084
}
8185
}
@@ -90,14 +94,14 @@ class RunAnywhereApplication : Application() {
9094

9195
private suspend fun initializeSDK() {
9296
initializationError = null
93-
Log.i("RunAnywhereApp", "🎯 Starting SDK initialization...")
94-
Log.w("RunAnywhereApp", "=======================================================")
95-
Log.w("RunAnywhereApp", "🔍 BUILD INFO - CHECK THIS FOR ANALYTICS DEBUGGING:")
96-
Log.w("RunAnywhereApp", " BuildConfig.DEBUG = ${BuildConfig.DEBUG}")
97-
Log.w("RunAnywhereApp", " BuildConfig.DEBUG_MODE = ${BuildConfig.DEBUG_MODE}")
98-
Log.w("RunAnywhereApp", " BuildConfig.BUILD_TYPE = ${BuildConfig.BUILD_TYPE}")
99-
Log.w("RunAnywhereApp", " Package name = ${applicationContext.packageName}")
100-
Log.w("RunAnywhereApp", "=======================================================")
97+
Timber.i("🎯 Starting SDK initialization...")
98+
Timber.w("=======================================================")
99+
Timber.w("🔍 BUILD INFO - CHECK THIS FOR ANALYTICS DEBUGGING:")
100+
Timber.w(" BuildConfig.DEBUG = ${BuildConfig.DEBUG}")
101+
Timber.w(" BuildConfig.DEBUG_MODE = ${BuildConfig.DEBUG_MODE}")
102+
Timber.w(" BuildConfig.BUILD_TYPE = ${BuildConfig.BUILD_TYPE}")
103+
Timber.w(" Package name = ${applicationContext.packageName}")
104+
Timber.w("=======================================================")
101105

102106
val startTime = System.currentTimeMillis()
103107

@@ -107,8 +111,8 @@ class RunAnywhereApplication : Application() {
107111
val hasCustomConfig = customApiKey != null && customBaseURL != null
108112

109113
if (hasCustomConfig) {
110-
Log.i("RunAnywhereApp", "🔧 Found custom API configuration")
111-
Log.i("RunAnywhereApp", " Base URL: $customBaseURL")
114+
Timber.i("🔧 Found custom API configuration")
115+
Timber.i(" Base URL: $customBaseURL")
112116
}
113117

114118
// Determine environment based on DEBUG_MODE (NOT BuildConfig.DEBUG!)
@@ -136,13 +140,13 @@ class RunAnywhereApplication : Application() {
136140
baseURL = customBaseURL!!,
137141
environment = environment,
138142
)
139-
Log.i("RunAnywhereApp", "✅ SDK initialized with CUSTOM configuration (${environment.name.lowercase()})")
143+
Timber.i("✅ SDK initialized with CUSTOM configuration (${environment.name.lowercase()})")
140144
} else if (environment == SDKEnvironment.DEVELOPMENT) {
141145
// DEVELOPMENT mode: Don't pass baseURL - SDK uses Supabase URL from C++ dev config
142146
RunAnywhere.initialize(
143147
environment = SDKEnvironment.DEVELOPMENT,
144148
)
145-
Log.i("RunAnywhereApp", "✅ SDK initialized in DEVELOPMENT mode (using Supabase from dev config)")
149+
Timber.i("✅ SDK initialized in DEVELOPMENT mode (using Supabase from dev config)")
146150
} else {
147151
// PRODUCTION mode - requires API key and base URL
148152
// Configure these via Settings screen or set environment variables
@@ -151,31 +155,30 @@ class RunAnywhereApplication : Application() {
151155

152156
// Detect placeholder credentials and abort production initialization
153157
if (apiKey.startsWith("YOUR_") || baseURL.startsWith("YOUR_")) {
154-
Log.e(
155-
"RunAnywhereApp",
158+
Timber.e(
156159
"❌ RunAnywhere.initialize with SDKEnvironment.PRODUCTION failed: " +
157160
"placeholder credentials detected. Configure via Settings screen or replace placeholders.",
158161
)
159162
// Fall back to development mode
160163
RunAnywhere.initialize(environment = SDKEnvironment.DEVELOPMENT)
161-
Log.i("RunAnywhereApp", "✅ SDK initialized in DEVELOPMENT mode (production credentials not configured)")
164+
Timber.i("✅ SDK initialized in DEVELOPMENT mode (production credentials not configured)")
162165
} else {
163166
RunAnywhere.initialize(
164167
apiKey = apiKey,
165168
baseURL = baseURL,
166169
environment = SDKEnvironment.PRODUCTION,
167170
)
168-
Log.i("RunAnywhereApp", "✅ SDK initialized in PRODUCTION mode")
171+
Timber.i("✅ SDK initialized in PRODUCTION mode")
169172
}
170173
}
171174

172175
// Phase 2: Complete services initialization (device registration, etc.)
173176
// This triggers device registration with the backend
174177
RunAnywhere.completeServicesInitialization()
175-
Log.i("RunAnywhereApp", "✅ SDK services initialization complete (device registered)")
178+
Timber.i("✅ SDK services initialization complete (device registered)")
176179
} catch (e: Exception) {
177180
// Log the failure but continue
178-
Log.w("RunAnywhereApp", "⚠️ SDK initialization failed (backend may be unavailable): ${e.message}")
181+
Timber.w("⚠️ SDK initialization failed (backend may be unavailable): ${e.message}")
179182
initializationError = e
180183

181184
// Fall back to development mode
@@ -184,36 +187,36 @@ class RunAnywhereApplication : Application() {
184187
RunAnywhere.initialize(
185188
environment = SDKEnvironment.DEVELOPMENT,
186189
)
187-
Log.i("RunAnywhereApp", "✅ SDK initialized in OFFLINE mode (local models only)")
190+
Timber.i("✅ SDK initialized in OFFLINE mode (local models only)")
188191

189192
// Still try Phase 2 in offline mode
190193
RunAnywhere.completeServicesInitialization()
191194
} catch (fallbackError: Exception) {
192-
Log.e("RunAnywhereApp", "❌ Fallback initialization also failed: ${fallbackError.message}")
195+
Timber.e("❌ Fallback initialization also failed: ${fallbackError.message}")
193196
}
194197
}
195198

196199
// Register modules and models
197200
registerModulesAndModels()
198201

199-
Log.i("RunAnywhereApp", "✅ SDK initialization complete")
202+
Timber.i("✅ SDK initialization complete")
200203

201204
val initTime = System.currentTimeMillis() - startTime
202-
Log.i("RunAnywhereApp", "✅ SDK setup completed in ${initTime}ms")
203-
Log.i("RunAnywhereApp", "🎯 SDK Status: Active=${RunAnywhere.isInitialized}")
205+
Timber.i("✅ SDK setup completed in ${initTime}ms")
206+
Timber.i("🎯 SDK Status: Active=${RunAnywhere.isInitialized}")
204207

205208
isSDKInitialized = RunAnywhere.isInitialized
206209

207210
// Update observable state for Compose UI
208211
if (isSDKInitialized) {
209212
_initializationState.value = SDKInitializationState.Ready
210-
Log.i("RunAnywhereApp", "🎉 App is ready to use!")
213+
Timber.i("🎉 App is ready to use!")
211214
} else if (initializationError != null) {
212215
_initializationState.value = SDKInitializationState.Error(initializationError!!)
213216
} else {
214217
// SDK reported not initialized but no error - treat as ready for offline mode
215218
_initializationState.value = SDKInitializationState.Ready
216-
Log.i("RunAnywhereApp", "🎉 App is ready to use (offline mode)!")
219+
Timber.i("🎉 App is ready to use (offline mode)!")
217220
}
218221
}
219222

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/data/ConversationStore.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package com.runanywhere.runanywhereai.data
22

33
import android.annotation.SuppressLint
44
import android.content.Context
5-
import android.util.Log
5+
import timber.log.Timber
66
import com.runanywhere.runanywhereai.domain.models.ChatMessage
77
import com.runanywhere.runanywhereai.domain.models.Conversation
88
import com.runanywhere.runanywhereai.domain.models.MessageRole
@@ -182,7 +182,7 @@ class ConversationStore private constructor(context: Context) {
182182
_currentConversation.value = loaded
183183
return loaded
184184
} catch (e: Exception) {
185-
Log.e("ConversationStore", "Failed to load conversation from disk", e)
185+
Timber.e(e, "Failed to load conversation from disk")
186186
}
187187
}
188188

@@ -228,7 +228,7 @@ class ConversationStore private constructor(context: Context) {
228228
val jsonString = file.readText()
229229
json.decodeFromString<Conversation>(jsonString)
230230
} catch (e: Exception) {
231-
Log.e("ConversationStore", "Failed to load conversation: ${file.name}", e)
231+
Timber.e(e, "Failed to load conversation: ${file.name}")
232232
null
233233
}
234234
}
@@ -238,7 +238,7 @@ class ConversationStore private constructor(context: Context) {
238238

239239
// Don't automatically set current conversation - let ChatViewModel create a new one
240240
} catch (e: Exception) {
241-
Log.e("ConversationStore", "Failed to load conversations", e)
241+
Timber.e(e, "Failed to load conversations")
242242
}
243243
}
244244

@@ -251,7 +251,7 @@ class ConversationStore private constructor(context: Context) {
251251
val jsonString = json.encodeToString(conversation)
252252
file.writeText(jsonString)
253253
} catch (e: Exception) {
254-
Log.e("ConversationStore", "Failed to save conversation", e)
254+
Timber.e(e, "Failed to save conversation")
255255
}
256256
}
257257

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/data/ModelList.kt

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.runanywhere.runanywhereai.data
22

3-
import android.util.Log
3+
import timber.log.Timber
44
import com.runanywhere.runanywhereai.data.models.AppModel
55
import com.runanywhere.sdk.core.onnx.ONNX
66
import com.runanywhere.sdk.core.types.InferenceFramework
@@ -15,8 +15,6 @@ import com.runanywhere.sdk.public.extensions.registerModel
1515
import com.runanywhere.sdk.public.extensions.registerMultiFileModel
1616

1717
object ModelList {
18-
private const val TAG = "ModelList"
19-
2018
// LLM Models
2119
private val llmModels = listOf(
2220
AppModel(id = "smollm2-360m-q8_0", name = "SmolLM2 360M Q8_0",
@@ -150,13 +148,13 @@ object ModelList {
150148
)
151149

152150
fun setupModels() {
153-
Log.i(TAG, "Registering backends and models...")
151+
Timber.i("Registering backends and models...")
154152
try {
155153
LlamaCPP.register(priority = 100)
156154
ONNX.register(priority = 100)
157-
Log.i(TAG, "Backends registered")
155+
Timber.i("Backends registered")
158156
} catch (e: Exception) {
159-
Log.e(TAG, "Failed to register backends", e)
157+
Timber.e(e, "Failed to register backends")
160158
return
161159
}
162160

@@ -190,20 +188,20 @@ object ModelList {
190188
)
191189
}
192190
} catch (e: Exception) {
193-
Log.e(TAG, "Failed to register model: ${model.id}", e)
191+
Timber.e(e, "Failed to register model: ${model.id}")
194192
}
195193
}
196-
Log.i(TAG, "$label models registered (${models.size})")
194+
Timber.i("$label models registered (${models.size})")
197195
}
198196

199197
for (adapter in loraAdapters) {
200198
try {
201199
RunAnywhere.registerLoraAdapter(adapter)
202200
} catch (e: Exception) {
203-
Log.e(TAG, "Failed to register LoRA adapter: ${adapter.id}", e)
201+
Timber.e(e, "Failed to register LoRA adapter: ${adapter.id}")
204202
}
205203
}
206-
Log.i(TAG, "LoRA adapters registered (${loraAdapters.size})")
207-
Log.i(TAG, "All models registered")
204+
Timber.i("LoRA adapters registered (${loraAdapters.size})")
205+
Timber.i("All models registered")
208206
}
209207
}

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/domain/services/AudioCaptureService.kt

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import android.content.pm.PackageManager
66
import android.media.AudioFormat
77
import android.media.AudioRecord
88
import android.media.MediaRecorder
9-
import android.util.Log
9+
import timber.log.Timber
1010
import androidx.core.app.ActivityCompat
1111
import kotlinx.coroutines.Dispatchers
1212
import kotlinx.coroutines.channels.awaitClose
@@ -21,8 +21,6 @@ import java.nio.ByteBuffer
2121
import java.nio.ByteOrder
2222
import kotlin.math.sqrt
2323

24-
private const val TAG = "AudioCaptureService"
25-
2624
/**
2725
* Service for capturing audio from the device microphone
2826
*
@@ -74,7 +72,7 @@ class AudioCaptureService(
7472
fun startCapture(): Flow<ByteArray> =
7573
callbackFlow {
7674
if (!hasRecordPermission()) {
77-
Log.e(TAG, "No RECORD_AUDIO permission")
75+
Timber.e("No RECORD_AUDIO permission")
7876
close(SecurityException("RECORD_AUDIO permission not granted"))
7977
return@callbackFlow
8078
}
@@ -93,14 +91,14 @@ class AudioCaptureService(
9391
)
9492

9593
if (audioRecord?.state != AudioRecord.STATE_INITIALIZED) {
96-
Log.e(TAG, "AudioRecord failed to initialize")
94+
Timber.e("AudioRecord failed to initialize")
9795
close(IllegalStateException("AudioRecord initialization failed"))
9896
return@callbackFlow
9997
}
10098

10199
audioRecord?.startRecording()
102100
_isRecording.value = true
103-
Log.i(TAG, "Audio capture started (${SAMPLE_RATE}Hz, chunk size: $chunkSize)")
101+
Timber.i("Audio capture started (${SAMPLE_RATE}Hz, chunk size: $chunkSize)")
104102

105103
// Launch a coroutine on IO dispatcher to read audio
106104
val readJob =
@@ -120,20 +118,20 @@ class AudioCaptureService(
120118
// trySend is safe to call from any context in callbackFlow
121119
trySend(chunk)
122120
} else if (bytesRead < 0) {
123-
Log.w(TAG, "AudioRecord read error: $bytesRead")
121+
Timber.w("AudioRecord read error: $bytesRead")
124122
break
125123
}
126124
}
127125
}
128126

129127
// Wait for cancellation
130128
awaitClose {
131-
Log.d(TAG, "Flow closing, stopping audio capture")
129+
Timber.d("Flow closing, stopping audio capture")
132130
readJob.cancel()
133131
stopCaptureInternal()
134132
}
135133
} catch (e: Exception) {
136-
Log.e(TAG, "Error in audio capture: ${e.message}")
134+
Timber.e("Error in audio capture: ${e.message}")
137135
stopCaptureInternal()
138136
close(e)
139137
}
@@ -154,9 +152,9 @@ class AudioCaptureService(
154152
audioRecord = null
155153
_isRecording.value = false
156154
_audioLevel.value = 0f
157-
Log.d(TAG, "Audio capture stopped")
155+
Timber.d("Audio capture stopped")
158156
} catch (e: Exception) {
159-
Log.w(TAG, "Error stopping audio capture: ${e.message}")
157+
Timber.w("Error stopping audio capture: ${e.message}")
160158
}
161159
}
162160

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/benchmarks/models/BenchmarkTypes.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import androidx.compose.material.icons.Icons
44
import androidx.compose.material.icons.filled.ChatBubble
55
import androidx.compose.material.icons.filled.GraphicEq
66
import androidx.compose.material.icons.filled.Visibility
7-
import androidx.compose.material.icons.filled.VolumeUp
7+
import androidx.compose.material.icons.automirrored.filled.VolumeUp
88
import androidx.compose.ui.graphics.vector.ImageVector
99
import com.runanywhere.sdk.public.extensions.Models.ModelCategory
1010
import com.runanywhere.sdk.public.extensions.Models.ModelInfo
@@ -34,7 +34,7 @@ enum class BenchmarkCategory(val value: String) {
3434
get() = when (this) {
3535
LLM -> Icons.Filled.ChatBubble
3636
STT -> Icons.Filled.GraphicEq
37-
TTS -> Icons.Filled.VolumeUp
37+
TTS -> Icons.AutoMirrored.Filled.VolumeUp
3838
VLM -> Icons.Filled.Visibility
3939
}
4040

0 commit comments

Comments
 (0)