Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ import android.os.Build
import android.os.Bundle
import com.itsaky.androidide.app.configuration.CpuArch
import com.itsaky.androidide.app.configuration.IDEBuildConfigProvider
import com.itsaky.androidide.ui.showLowStorageDialog
import com.itsaky.androidide.utils.FeatureFlags
import com.itsaky.androidide.utils.hasEnoughStorageAvailable
import kotlin.system.exitProcess

/**
Expand All @@ -33,6 +35,11 @@ class SplashActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

if (!hasEnoughStorageAvailable()) {
showLowStorageDialog()
return
}

val isX86 = Build.SUPPORTED_ABIS.firstOrNull() in listOf(CpuArch.X86_64.abi, CpuArch.X86.abi)

if (isX86 && (!IDEBuildConfigProvider.getInstance().supportsCpuAbi() || !FeatureFlags.isEmulatorUseEnabled)) {
Expand Down
33 changes: 33 additions & 0 deletions app/src/main/java/com/itsaky/androidide/ui/StorageDialog.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.itsaky.androidide.ui

import android.app.Activity
import android.app.AlertDialog
import android.content.ActivityNotFoundException
import android.content.Intent
import android.provider.Settings
import com.itsaky.androidide.resources.R
import com.itsaky.androidide.utils.getMinimumStorageNeeded


fun Activity.showLowStorageDialog() {
val appName = getString(R.string.app_name)
val minSpace = getMinimumStorageNeeded()

AlertDialog.Builder(this)
.setTitle(R.string.err_insufficient_storage_title)
.setMessage(getString(R.string.err_insufficient_storage_msg, appName, minSpace))
.setCancelable(false)
.setPositiveButton(getString(R.string.action_close_app, appName)) { _, _ ->
finishAndRemoveTask()
}
.setNegativeButton(R.string.action_free_up_space) { _, _ ->
val intent = Intent(Settings.ACTION_INTERNAL_STORAGE_SETTINGS)
try {
startActivity(intent)
} catch (_: ActivityNotFoundException) {
startActivity(Intent(Settings.ACTION_SETTINGS))
}
finishAffinity()
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
.show()
}
23 changes: 23 additions & 0 deletions app/src/main/java/com/itsaky/androidide/utils/StorageUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.itsaky.androidide.utils

import android.os.Environment
import android.os.StatFs

fun hasEnoughStorageAvailable(): Boolean {
return try {
val dataDir = Environment.getDataDirectory()
val stat = StatFs(dataDir.path)
val availableBytes = stat.availableBlocksLong * stat.blockSizeLong
availableBytes > getMinimumStorageNeeded().gigabytesToBytes()
} catch (_: Exception) { false }
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

fun getMinimumStorageNeeded(): Long {
val minimumStorageStableGB = 4L
val minimumStorageExperimentalGB = 6L

if (FeatureFlags.isExperimentsEnabled) {
return minimumStorageExperimentalGB;
}
return minimumStorageStableGB;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import com.itsaky.androidide.events.InstallationEvent
import com.itsaky.androidide.models.StorageInfo
import com.itsaky.androidide.resources.R
import com.itsaky.androidide.utils.Environment
import com.itsaky.androidide.utils.FeatureFlags
import com.itsaky.androidide.utils.bytesToGigabytes
import com.itsaky.androidide.utils.getMinimumStorageNeeded
import com.itsaky.androidide.utils.gigabytesToBytes
import com.itsaky.androidide.utils.withStopWatch
import com.itsaky.androidide.viewmodel.InstallationState.InstallationComplete
Expand All @@ -34,17 +34,6 @@ import kotlinx.coroutines.withContext
import org.slf4j.LoggerFactory

class InstallationViewModel : ViewModel() {
companion object {
private const val MINIMUM_STORAGE_STABLE_GB = 4L
private const val MINIMUM_STORAGE_EXPERIMENTAL_GB = 6L
}

private val minimumStorageNeeded: Long
get() = if (FeatureFlags.isExperimentsEnabled) {
MINIMUM_STORAGE_EXPERIMENTAL_GB
} else {
MINIMUM_STORAGE_STABLE_GB
}

private val log = LoggerFactory.getLogger(InstallationViewModel::class.java)

Expand Down Expand Up @@ -148,7 +137,7 @@ class InstallationViewModel : ViewModel() {
val stat = StatFs(internalStoragePath)

val availableStorageInBytes = stat.availableBlocksLong * stat.blockSizeLong
val requiredStorageInBytes = minimumStorageNeeded.gigabytesToBytes()
val requiredStorageInBytes = getMinimumStorageNeeded().gigabytesToBytes()

val isLowStorage = availableStorageInBytes < requiredStorageInBytes

Expand Down
4 changes: 4 additions & 0 deletions resources/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
<string name="app_logs">App Logs</string>
<string name="ide_logs">IDE Logs</string>
<string name="default_tooltip">General information about this feature.</string>
<string name="err_insufficient_storage_title">Insufficient Storage</string>
<string name="err_insufficient_storage_msg">%1$s requires at least %2$dGB of free space to run and extract the necessary tools.\n\nPlease free up space on your device and try again.</string>
<string name="action_close_app">Close %1$s</string>
<string name="action_free_up_space">Free Up Space</string>

<!-- Agent -->
<string name="agent_backend_selected">🤖 System: %1$s backend selected.</string>
Expand Down