diff --git a/app/src/main/java/foundation/e/apps/MainActivity.kt b/app/src/main/java/foundation/e/apps/MainActivity.kt index f884e11ae6c3814ed6c3f02f7c496062ad094d45..9ff89f1e3d4473150bb7504a7b840e7d5918e865 100644 --- a/app/src/main/java/foundation/e/apps/MainActivity.kt +++ b/app/src/main/java/foundation/e/apps/MainActivity.kt @@ -18,8 +18,12 @@ package foundation.e.apps +import android.app.usage.StorageStatsManager import android.os.Build import android.os.Bundle +import android.os.Environment +import android.os.StatFs +import android.os.storage.StorageManager import android.util.Log import android.view.View import androidx.appcompat.app.AppCompatActivity @@ -34,6 +38,7 @@ import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint import foundation.e.apps.application.subFrags.ApplicationDialogFragment import foundation.e.apps.databinding.ActivityMainBinding +import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.workmanager.InstallWorkManager import foundation.e.apps.purchase.AppPurchaseFragmentDirections import foundation.e.apps.setup.signin.SignInViewModel @@ -42,6 +47,8 @@ import foundation.e.apps.utils.enums.Status import foundation.e.apps.utils.enums.User import foundation.e.apps.utils.modules.CommonUtilsModule import kotlinx.coroutines.launch +import java.io.File +import java.util.* @AndroidEntryPoint class MainActivity : AppCompatActivity() { @@ -161,11 +168,7 @@ class MainActivity : AppCompatActivity() { viewModel.downloadList.observe(this) { list -> list.forEach { if (it.status == Status.QUEUED) { - lifecycleScope.launch { - viewModel.updateAwaiting(it) - InstallWorkManager.enqueueWork(applicationContext, it) - Log.d(TAG, "===> onCreate: AWAITING ${it.name}") - } + handleFusedDownloadQueued(it, viewModel) } } } @@ -213,6 +216,27 @@ class MainActivity : AppCompatActivity() { } } + private fun handleFusedDownloadQueued( + it: FusedDownload, + viewModel: MainActivityViewModel + ) { + lifecycleScope.launch { + if (!isStorageAvailable(it)) { + showSnackbarMessage(getString(R.string.not_enough_storage)) + viewModel.updateUnAvailable(it) + return@launch + } + if (viewModel.internetConnection.value == false) { + showNoInternet() + viewModel.updateUnAvailable(it) + return@launch + } + viewModel.updateAwaiting(it) + InstallWorkManager.enqueueWork(applicationContext, it) + Log.d(TAG, "===> onCreate: AWAITING ${it.name}") + } + } + private fun startInstallationOfPurchasedApp( viewModel: MainActivityViewModel, it: String @@ -235,4 +259,39 @@ class MainActivity : AppCompatActivity() { binding.noInternet.visibility = View.VISIBLE binding.fragment.visibility = View.GONE } + + // TODO: move storage availability code to FileManager Class + private fun isStorageAvailable(fusedDownload: FusedDownload): Boolean { + var availableSpace = 0L + availableSpace = calculateAvailableDiskSpace() + return availableSpace > fusedDownload.appSize + (500 * (1000 * 1000)) + } + + private fun calculateAvailableDiskSpace(): Long { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val storageManager = getSystemService(STORAGE_SERVICE) as StorageManager + val statsManager = getSystemService(STORAGE_STATS_SERVICE) as StorageStatsManager + val uuid = storageManager.primaryStorageVolume.uuid + try { + if (uuid != null) { + statsManager.getFreeBytes(UUID.fromString(uuid)) + } else { + statsManager.getFreeBytes(StorageManager.UUID_DEFAULT) + } + } catch (e: Exception) { + Log.e(TAG, "calculateAvailableDiskSpace: ${e.stackTraceToString()}") + getAvailableInternalMemorySize() + } + } else { + getAvailableInternalMemorySize() + } + } + + private fun getAvailableInternalMemorySize(): Long { + val path: File = Environment.getDataDirectory() + val stat = StatFs(path.path) + val blockSize = stat.blockSizeLong + val availableBlocks = stat.availableBlocksLong + return availableBlocks * blockSize + } } diff --git a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt index 98820cb767e90e5ca06d79aa8ea9af76fb14a1bf..e6b4c91fa208287ca39ad198e7df354487c28ee1 100644 --- a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +++ b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt @@ -159,7 +159,8 @@ class MainActivityViewModel @Inject constructor( appIcon, app.latest_version_code, app.offer_type, - app.isFree + app.isFree, + app.originalSize ) updateFusedDownloadWithAppDownloadLink(app, fusedDownload) } catch (e: Exception) { @@ -196,7 +197,8 @@ class MainActivityViewModel @Inject constructor( appIcon, app.latest_version_code, app.offer_type, - app.isFree + app.isFree, + app.originalSize ) viewModelScope.launch { fusedManagerRepository.addFusedDownloadPurchaseNeeded(fusedDownload) @@ -208,6 +210,10 @@ class MainActivityViewModel @Inject constructor( fusedManagerRepository.updateAwaiting(fusedDownload) } + suspend fun updateUnAvailable(fusedDownload: FusedDownload) { + fusedManagerRepository.updateUnavailable(fusedDownload) + } + suspend fun updateAwaitingForPurchasedApp(packageName: String): FusedDownload? { val fusedDownload = fusedManagerRepository.getFusedDownload(packageName = packageName) authData.value?.let { diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt index 7e850ad7321000b06a3bcdd500d19fbdc214574d..1a6cc16cc7e54d9c8413e114ad0a068ff70213b3 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt @@ -632,6 +632,7 @@ class FusedAPIImpl @Inject constructor( offer_type = this.offerType, origin = Origin.GPLAY, shareUrl = this.shareUrl, + originalSize = this.size, appSize = Formatter.formatFileSize(context, this.size), isFree = this.isFree, price = this.price diff --git a/app/src/main/java/foundation/e/apps/api/fused/data/FusedApp.kt b/app/src/main/java/foundation/e/apps/api/fused/data/FusedApp.kt index c676eeed2b8dbe60716bfab5757833e8f3c5f43d..b654cb64516b08f641c9cfbd82398bba8f343400 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/data/FusedApp.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/data/FusedApp.kt @@ -42,6 +42,7 @@ data class FusedApp( var status: Status = Status.UNAVAILABLE, var origin: Origin = Origin.CLEANAPK, val shareUrl: String = String(), + val originalSize: Long = 0, val appSize: String = String(), var source: String = String(), val price: String = String(), diff --git a/app/src/main/java/foundation/e/apps/manager/database/fusedDownload/FusedDownload.kt b/app/src/main/java/foundation/e/apps/manager/database/fusedDownload/FusedDownload.kt index 097539429cb256c61faa811f5684441982104e77..269298dd463b89a71811b4a1a434d5f650a7e4e0 100644 --- a/app/src/main/java/foundation/e/apps/manager/database/fusedDownload/FusedDownload.kt +++ b/app/src/main/java/foundation/e/apps/manager/database/fusedDownload/FusedDownload.kt @@ -22,5 +22,6 @@ data class FusedDownload( val versionCode: Int = 1, val offerType: Int = -1, val isFree: Boolean = true, + val appSize: Long = 0, var files: List = mutableListOf() ) diff --git a/app/src/main/java/foundation/e/apps/updates/manager/UpdatesWorker.kt b/app/src/main/java/foundation/e/apps/updates/manager/UpdatesWorker.kt index 5f410400213225a9d9505119dab355ac302cd95f..2aa21aa8a9d3111f1096a288b33d6faef3b8952c 100644 --- a/app/src/main/java/foundation/e/apps/updates/manager/UpdatesWorker.kt +++ b/app/src/main/java/foundation/e/apps/updates/manager/UpdatesWorker.kt @@ -134,7 +134,8 @@ class UpdatesWorker @AssistedInject constructor( iconBase64, fusedApp.latest_version_code, fusedApp.offer_type, - fusedApp.isFree + fusedApp.isFree, + fusedApp.originalSize ) updateFusedDownloadWithAppDownloadLink(fusedApp, authData, fusedDownload) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f1a6ac7c4059690df9d6a95f6d20dfefbf85d464..2293cc8b99612eee60e33c3dda3150710ba05aeb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -102,6 +102,7 @@ Paid apps are not supported in App Lounge yet. Just a little more patience, it will soon be the case. This app will be available later! Unknown Error! + There is not enough space available to download this application! Update All