DownloadMenuSheet: Allow to export downloaded files

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2024-04-16 12:04:32 +05:30
parent 5f714e624b
commit 92771bbaec
5 changed files with 67 additions and 8 deletions

View File

@@ -33,7 +33,7 @@ object ApkCopier {
private const val TAG = "ApkCopier" private const val TAG = "ApkCopier"
fun copy(context: Context, packageName: String, uri: Uri) { fun copyInstalledApp(context: Context, packageName: String, uri: Uri) {
val packageInfo = getPackageInfo(context, packageName, PackageManager.GET_META_DATA) val packageInfo = getPackageInfo(context, packageName, PackageManager.GET_META_DATA)
val baseApk = getBaseApk(packageInfo) val baseApk = getBaseApk(packageInfo)
val fileList: MutableList<File?> = mutableListOf() val fileList: MutableList<File?> = mutableListOf()
@@ -47,6 +47,14 @@ object ApkCopier {
bundleAllAPKs(context, fileList.filterNotNull(), uri) bundleAllAPKs(context, fileList.filterNotNull(), uri)
} }
fun copyDownloadedApp(context: Context, packageName: String, versionCode: Int, uri: Uri) {
return bundleAllAPKs(
context,
PathUtil.getAppDownloadDir(context, packageName, versionCode).listFiles()!!.toList(),
uri
)
}
private fun getBaseApk(packageInfo: PackageInfo?): File? { private fun getBaseApk(packageInfo: PackageInfo?): File? {
return if (packageInfo?.applicationInfo != null) { return if (packageInfo?.applicationInfo != null) {
File(packageInfo.applicationInfo.sourceDir) File(packageInfo.applicationInfo.sourceDir)

View File

@@ -57,7 +57,7 @@ class AppMenuSheet : BottomSheetDialogFragment(R.layout.sheet_app_menu) {
private val requestDocumentCreation = private val requestDocumentCreation =
registerForActivityResult(ActivityResultContracts.CreateDocument(exportMimeType)) { registerForActivityResult(ActivityResultContracts.CreateDocument(exportMimeType)) {
if (it != null) { if (it != null) {
viewModel.copyApk(requireContext(), args.app.packageName, it) viewModel.copyInstalledApp(requireContext(), args.app.packageName, it)
} else { } else {
toast(R.string.failed_apk_export) toast(R.string.failed_apk_export)
} }

View File

@@ -22,6 +22,8 @@ package com.aurora.store.view.ui.sheets
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.View import android.view.View
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.viewModels
import androidx.lifecycle.findViewTreeLifecycleOwner import androidx.lifecycle.findViewTreeLifecycleOwner
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
@@ -32,6 +34,8 @@ import com.aurora.store.data.installer.AppInstaller
import com.aurora.store.data.model.DownloadStatus import com.aurora.store.data.model.DownloadStatus
import com.aurora.store.databinding.SheetDownloadMenuBinding import com.aurora.store.databinding.SheetDownloadMenuBinding
import com.aurora.store.util.DownloadWorkerUtil import com.aurora.store.util.DownloadWorkerUtil
import com.aurora.store.util.PathUtil
import com.aurora.store.viewmodel.sheets.SheetsViewModel
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
@@ -46,9 +50,27 @@ class DownloadMenuSheet : BottomSheetDialogFragment(R.layout.sheet_download_menu
private var _binding: SheetDownloadMenuBinding? = null private var _binding: SheetDownloadMenuBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
private val viewModel: SheetsViewModel by viewModels()
private val args: DownloadMenuSheetArgs by navArgs() private val args: DownloadMenuSheetArgs by navArgs()
private val playStoreURL = "https://play.google.com/store/apps/details?id=" private val playStoreURL = "https://play.google.com/store/apps/details?id="
private val exportMimeType = "application/zip"
private val requestDocumentCreation =
registerForActivityResult(ActivityResultContracts.CreateDocument(exportMimeType)) {
if (it != null) {
viewModel.copyDownloadedApp(
requireContext(),
args.download.packageName,
args.download.versionCode,
it
)
} else {
toast(R.string.failed_apk_export)
}
dismissAllowingStateLoss()
}
@Inject @Inject
lateinit var downloadWorkerUtil: DownloadWorkerUtil lateinit var downloadWorkerUtil: DownloadWorkerUtil
@@ -60,24 +82,37 @@ class DownloadMenuSheet : BottomSheetDialogFragment(R.layout.sheet_download_menu
_binding = SheetDownloadMenuBinding.bind(view) _binding = SheetDownloadMenuBinding.bind(view)
with(binding.navigationView) { with(binding.navigationView) {
val downloadCompleted = args.download.downloadStatus == DownloadStatus.COMPLETED
val downloadDir = PathUtil.getAppDownloadDir(
requireContext(),
args.download.packageName,
args.download.versionCode
)
menu.findItem(R.id.action_cancel).isVisible = !args.download.isFinished menu.findItem(R.id.action_cancel).isVisible = !args.download.isFinished
menu.findItem(R.id.action_clear).isVisible = args.download.isFinished menu.findItem(R.id.action_clear).isVisible = args.download.isFinished
menu.findItem(R.id.action_install).isVisible = menu.findItem(R.id.action_install).isVisible = downloadCompleted
args.download.downloadStatus == DownloadStatus.COMPLETED menu.findItem(R.id.action_local).isVisible =
downloadCompleted && downloadDir.listFiles() != null
setNavigationItemSelectedListener { item -> setNavigationItemSelectedListener { item ->
when (item.itemId) { when (item.itemId) {
R.id.action_install -> install() R.id.action_install -> {
install()
dismissAllowingStateLoss()
}
R.id.action_copy -> { R.id.action_copy -> {
requireContext().copyToClipBoard( requireContext().copyToClipBoard(
"${playStoreURL}${args.download.packageName}" "${playStoreURL}${args.download.packageName}"
) )
requireContext().toast(requireContext().getString(R.string.toast_clipboard_copied)) requireContext().toast(requireContext().getString(R.string.toast_clipboard_copied))
dismissAllowingStateLoss()
} }
R.id.action_cancel -> { R.id.action_cancel -> {
findViewTreeLifecycleOwner()?.lifecycleScope?.launch(NonCancellable) { findViewTreeLifecycleOwner()?.lifecycleScope?.launch(NonCancellable) {
downloadWorkerUtil.cancelDownload(args.download.packageName) downloadWorkerUtil.cancelDownload(args.download.packageName)
} }
dismissAllowingStateLoss()
} }
R.id.action_clear -> { R.id.action_clear -> {
findViewTreeLifecycleOwner()?.lifecycleScope?.launch(NonCancellable) { findViewTreeLifecycleOwner()?.lifecycleScope?.launch(NonCancellable) {
@@ -86,9 +121,12 @@ class DownloadMenuSheet : BottomSheetDialogFragment(R.layout.sheet_download_menu
args.download.versionCode args.download.versionCode
) )
} }
dismissAllowingStateLoss()
}
R.id.action_local -> {
requestDocumentCreation.launch("${args.download.packageName}.zip")
} }
} }
dismissAllowingStateLoss()
false false
} }
} }

View File

@@ -40,9 +40,19 @@ class SheetsViewModel : ViewModel() {
} }
} }
fun copyApk(context: Context, packageName: String, uri: Uri) { fun copyInstalledApp(context: Context, packageName: String, uri: Uri) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
ApkCopier.copy(context, packageName, uri) ApkCopier.copyInstalledApp(context, packageName, uri)
}
}
fun copyDownloadedApp(context: Context, packageName: String, versionCode: Int, uri: Uri) {
viewModelScope.launch(Dispatchers.IO) {
try {
ApkCopier.copyDownloadedApp(context, packageName, versionCode, uri)
} catch (exception: Exception) {
Log.e(TAG, "Failed to copy downloads", exception)
}
} }
} }
} }

View File

@@ -18,6 +18,9 @@
--> -->
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_local"
android:title="@string/action_get_local_apk" />
<item <item
android:id="@+id/action_install" android:id="@+id/action_install"
android:title="@string/action_install" /> android:title="@string/action_install" />