Loading app/src/main/java/foundation/e/apps/MainActivity.kt +64 −5 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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() { Loading Loading @@ -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) } } } Loading Loading @@ -213,6 +216,27 @@ class MainActivity : AppCompatActivity() { } } private fun handleFusedDownloadQueued( it: FusedDownload, viewModel: MainActivityViewModel ) { lifecycleScope.launch { if (!checkStorageAvailability(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 Loading @@ -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 checkStorageAvailability(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 } } app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +8 −2 Original line number Diff line number Diff line Loading @@ -162,7 +162,8 @@ class MainActivityViewModel @Inject constructor( appIcon, app.latest_version_code, app.offer_type, app.isFree app.isFree, app.originalSize ) } catch (e: Exception) { if (e is ApiException.AppNotPurchased) { Loading Loading @@ -198,7 +199,8 @@ class MainActivityViewModel @Inject constructor( appIcon, app.latest_version_code, app.offer_type, app.isFree app.isFree, app.originalSize ) viewModelScope.launch { fusedManagerRepository.addFusedDownloadPurchaseNeeded(fusedDownload) Loading @@ -210,6 +212,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 { Loading app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +1 −0 Original line number Diff line number Diff line Loading @@ -639,6 +639,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 Loading app/src/main/java/foundation/e/apps/api/fused/data/FusedApp.kt +1 −0 Original line number Diff line number Diff line Loading @@ -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(), Loading app/src/main/java/foundation/e/apps/manager/database/fusedDownload/FusedDownload.kt +2 −1 Original line number Diff line number Diff line Loading @@ -20,5 +20,6 @@ data class FusedDownload( val iconByteArray: String = String(), val versionCode: Int = 1, val offerType: Int = -1, val isFree: Boolean = true val isFree: Boolean = true, val appSize: Long = 0 ) Loading
app/src/main/java/foundation/e/apps/MainActivity.kt +64 −5 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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() { Loading Loading @@ -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) } } } Loading Loading @@ -213,6 +216,27 @@ class MainActivity : AppCompatActivity() { } } private fun handleFusedDownloadQueued( it: FusedDownload, viewModel: MainActivityViewModel ) { lifecycleScope.launch { if (!checkStorageAvailability(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 Loading @@ -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 checkStorageAvailability(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 } }
app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +8 −2 Original line number Diff line number Diff line Loading @@ -162,7 +162,8 @@ class MainActivityViewModel @Inject constructor( appIcon, app.latest_version_code, app.offer_type, app.isFree app.isFree, app.originalSize ) } catch (e: Exception) { if (e is ApiException.AppNotPurchased) { Loading Loading @@ -198,7 +199,8 @@ class MainActivityViewModel @Inject constructor( appIcon, app.latest_version_code, app.offer_type, app.isFree app.isFree, app.originalSize ) viewModelScope.launch { fusedManagerRepository.addFusedDownloadPurchaseNeeded(fusedDownload) Loading @@ -210,6 +212,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 { Loading
app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +1 −0 Original line number Diff line number Diff line Loading @@ -639,6 +639,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 Loading
app/src/main/java/foundation/e/apps/api/fused/data/FusedApp.kt +1 −0 Original line number Diff line number Diff line Loading @@ -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(), Loading
app/src/main/java/foundation/e/apps/manager/database/fusedDownload/FusedDownload.kt +2 −1 Original line number Diff line number Diff line Loading @@ -20,5 +20,6 @@ data class FusedDownload( val iconByteArray: String = String(), val versionCode: Int = 1, val offerType: Int = -1, val isFree: Boolean = true val isFree: Boolean = true, val appSize: Long = 0 )