mirror of
https://github.com/Aviortheking/Neo-Store.git
synced 2025-04-23 19:32:16 +00:00
Update: Merge AppSheet's Installed into main Installed
This commit is contained in:
parent
099b1bdf28
commit
1477fba932
@ -68,9 +68,29 @@ class MainApplication : Application(), ImageLoaderFactory {
|
|||||||
addDataScheme("package")
|
addDataScheme("package")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
val launcherActivitiesMap =
|
||||||
|
packageManager
|
||||||
|
.queryIntentActivities(
|
||||||
|
Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER),
|
||||||
|
0
|
||||||
|
)
|
||||||
|
.mapNotNull { resolveInfo -> resolveInfo.activityInfo }
|
||||||
|
.groupBy { it.packageName }
|
||||||
|
.mapNotNull { (packageName, activityInfos) ->
|
||||||
|
val aiNameLabels = activityInfos.mapNotNull {
|
||||||
|
val label = try {
|
||||||
|
it.loadLabel(packageManager).toString()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
null
|
||||||
|
}
|
||||||
|
label?.let { label -> Pair(it.name, label) }
|
||||||
|
}
|
||||||
|
Pair(packageName, aiNameLabels)
|
||||||
|
}.toMap()
|
||||||
val installedItems = packageManager
|
val installedItems = packageManager
|
||||||
.getInstalledPackages(Android.PackageManager.signaturesFlag)
|
.getInstalledPackages(Android.PackageManager.signaturesFlag)
|
||||||
.map { it.toInstalledItem() }
|
.map { it.toInstalledItem(launcherActivitiesMap[it.packageName].orEmpty()) }
|
||||||
CoroutineScope(Dispatchers.Default).launch {
|
CoroutineScope(Dispatchers.Default).launch {
|
||||||
db.installedDao.emptyTable()
|
db.installedDao.emptyTable()
|
||||||
db.installedDao.put(*installedItems.toTypedArray())
|
db.installedDao.put(*installedItems.toTypedArray())
|
||||||
|
@ -21,6 +21,23 @@ object Converters {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun toByteArray(list: List<String>): ByteArray = list.toString().toByteArray()
|
fun toByteArray(list: List<String>): ByteArray = list.toString().toByteArray()
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
@JvmStatic
|
||||||
|
fun toPairStringList(byteArray: ByteArray): List<Pair<String, String>> {
|
||||||
|
val string = String(byteArray)
|
||||||
|
return if (string == "") emptyList()
|
||||||
|
else string.removeSurrounding("[", "]").split(",").filter(String::isNotEmpty).map {
|
||||||
|
val pairs = it.split("|")
|
||||||
|
Pair(pairs[0], pairs[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmName("pairStringListToByteArray")
|
||||||
|
@TypeConverter
|
||||||
|
@JvmStatic
|
||||||
|
fun toByteArray(list: List<Pair<String, String>>): ByteArray =
|
||||||
|
list.map { it.toList().joinToString("|") }.toString().toByteArray()
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun toAuthor(byteArray: ByteArray) = Author.fromJson(String(byteArray))
|
fun toAuthor(byteArray: ByteArray) = Author.fromJson(String(byteArray))
|
||||||
|
@ -21,7 +21,7 @@ import kotlinx.coroutines.launch
|
|||||||
CategoryTemp::class,
|
CategoryTemp::class,
|
||||||
Installed::class,
|
Installed::class,
|
||||||
Ignored::class
|
Ignored::class
|
||||||
], version = 6
|
], version = 7
|
||||||
)
|
)
|
||||||
@TypeConverters(Converters::class)
|
@TypeConverters(Converters::class)
|
||||||
abstract class DatabaseX : RoomDatabase() {
|
abstract class DatabaseX : RoomDatabase() {
|
||||||
|
@ -10,5 +10,7 @@ data class Installed(
|
|||||||
var packageName: String = "",
|
var packageName: String = "",
|
||||||
var version: String = "",
|
var version: String = "",
|
||||||
var versionCode: Long = 0L,
|
var versionCode: Long = 0L,
|
||||||
var signature: String = ""
|
var signature: String = "",
|
||||||
|
var isSystem: Boolean = false,
|
||||||
|
val launcherActivities: List<Pair<String, String>> = emptyList()
|
||||||
)
|
)
|
@ -6,6 +6,7 @@ import android.content.Intent
|
|||||||
import com.looker.droidify.database.DatabaseX
|
import com.looker.droidify.database.DatabaseX
|
||||||
import com.looker.droidify.utility.Utils.toInstalledItem
|
import com.looker.droidify.utility.Utils.toInstalledItem
|
||||||
import com.looker.droidify.utility.extension.android.Android
|
import com.looker.droidify.utility.extension.android.Android
|
||||||
|
import com.looker.droidify.utility.getLaunchActivities
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -29,8 +30,10 @@ class PackageChangedReceiver : BroadcastReceiver() {
|
|||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
val launcherActivities = context.packageManager.getLaunchActivities(packageName)
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
if (packageInfo != null) db.installedDao.insertReplace(packageInfo.toInstalledItem())
|
if (packageInfo != null) db.installedDao
|
||||||
|
.insertReplace(packageInfo.toInstalledItem(launcherActivities))
|
||||||
else db.installedDao.delete(packageName)
|
else db.installedDao.delete(packageName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package com.looker.droidify.ui.fragments
|
package com.looker.droidify.ui.fragments
|
||||||
|
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.ComponentName
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.ApplicationInfo
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
@ -18,6 +16,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.looker.droidify.R
|
import com.looker.droidify.R
|
||||||
import com.looker.droidify.content.ProductPreferences
|
import com.looker.droidify.content.ProductPreferences
|
||||||
|
import com.looker.droidify.database.entity.Installed
|
||||||
import com.looker.droidify.database.entity.Product
|
import com.looker.droidify.database.entity.Product
|
||||||
import com.looker.droidify.database.entity.Release
|
import com.looker.droidify.database.entity.Release
|
||||||
import com.looker.droidify.database.entity.Repository
|
import com.looker.droidify.database.entity.Repository
|
||||||
@ -108,46 +107,7 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), AppDetailAdapter.Call
|
|||||||
override fun setupLayout() {
|
override fun setupLayout() {
|
||||||
// TODO simplify observing and updating
|
// TODO simplify observing and updating
|
||||||
viewModel.installedItem.observe(viewLifecycleOwner) {
|
viewModel.installedItem.observe(viewLifecycleOwner) {
|
||||||
installed = it?.let {
|
installed = it
|
||||||
val isSystem = try {
|
|
||||||
((requireContext().packageManager.getApplicationInfo(packageName, 0).flags)
|
|
||||||
and ApplicationInfo.FLAG_SYSTEM) != 0
|
|
||||||
} catch (e: Exception) {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
val launcherActivities =
|
|
||||||
if (packageName != context?.packageName && context != null) {
|
|
||||||
val packageManager = requireContext().packageManager
|
|
||||||
packageManager
|
|
||||||
.queryIntentActivities(
|
|
||||||
Intent(Intent.ACTION_MAIN).addCategory(
|
|
||||||
Intent.CATEGORY_LAUNCHER
|
|
||||||
), 0
|
|
||||||
)
|
|
||||||
.asSequence()
|
|
||||||
.mapNotNull { resolveInfo -> resolveInfo.activityInfo }
|
|
||||||
.filter { activityInfo -> activityInfo.packageName == packageName }
|
|
||||||
.mapNotNull { activityInfo ->
|
|
||||||
val label = try {
|
|
||||||
activityInfo.loadLabel(packageManager).toString()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
null
|
|
||||||
}
|
|
||||||
label?.let { labelName ->
|
|
||||||
Pair(
|
|
||||||
activityInfo.name,
|
|
||||||
labelName
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.toList()
|
|
||||||
} else {
|
|
||||||
// Don't allow to launch self
|
|
||||||
emptyList()
|
|
||||||
}
|
|
||||||
Installed(it, isSystem, launcherActivities)
|
|
||||||
}
|
|
||||||
updateSheet()
|
updateSheet()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +135,7 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), AppDetailAdapter.Call
|
|||||||
binding.recyclerView.context,
|
binding.recyclerView.context,
|
||||||
packageName,
|
packageName,
|
||||||
this,
|
this,
|
||||||
installed?.data
|
installed
|
||||||
)
|
)
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
updateButtons()
|
updateButtons()
|
||||||
@ -205,12 +165,12 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), AppDetailAdapter.Call
|
|||||||
private suspend fun updateButtons(preference: ProductPreference) =
|
private suspend fun updateButtons(preference: ProductPreference) =
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
val installed = installed
|
val installed = installed
|
||||||
val product = findSuggestedProduct(productRepos, installed?.data) { it.first }?.first
|
val product = findSuggestedProduct(productRepos, installed) { it.first }?.first
|
||||||
val compatible = product != null && product.selectedReleases.firstOrNull()
|
val compatible = product != null && product.selectedReleases.firstOrNull()
|
||||||
.let { it != null && it.incompatibilities.isEmpty() }
|
.let { it != null && it.incompatibilities.isEmpty() }
|
||||||
val canInstall = product != null && installed == null && compatible
|
val canInstall = product != null && installed == null && compatible
|
||||||
val canUpdate =
|
val canUpdate =
|
||||||
product != null && compatible && product.canUpdate(installed?.data) &&
|
product != null && compatible && product.canUpdate(installed) &&
|
||||||
!preference.shouldIgnoreUpdate(product.versionCode)
|
!preference.shouldIgnoreUpdate(product.versionCode)
|
||||||
val canUninstall = product != null && installed != null && !installed.isSystem
|
val canUninstall = product != null && installed != null && !installed.isSystem
|
||||||
val canLaunch =
|
val canLaunch =
|
||||||
@ -303,7 +263,7 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), AppDetailAdapter.Call
|
|||||||
AppDetailAdapter.Action.INSTALL,
|
AppDetailAdapter.Action.INSTALL,
|
||||||
AppDetailAdapter.Action.UPDATE,
|
AppDetailAdapter.Action.UPDATE,
|
||||||
-> {
|
-> {
|
||||||
val installedItem = installed?.data
|
val installedItem = installed
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
startUpdate(
|
startUpdate(
|
||||||
packageName,
|
packageName,
|
||||||
@ -408,7 +368,7 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), AppDetailAdapter.Call
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onReleaseClick(release: Release) {
|
override fun onReleaseClick(release: Release) {
|
||||||
val installedItem = installed?.data
|
val installedItem = installed
|
||||||
when {
|
when {
|
||||||
release.incompatibilities.isNotEmpty() -> {
|
release.incompatibilities.isNotEmpty() -> {
|
||||||
MessageDialog(
|
MessageDialog(
|
||||||
@ -494,9 +454,4 @@ class AppSheetX() : FullscreenBottomSheetDialogFragment(), AppDetailAdapter.Call
|
|||||||
UNINSTALL(5, AppDetailAdapter.Action.UNINSTALL),
|
UNINSTALL(5, AppDetailAdapter.Action.UNINSTALL),
|
||||||
SHARE(6, AppDetailAdapter.Action.SHARE)
|
SHARE(6, AppDetailAdapter.Action.SHARE)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Installed(
|
|
||||||
val data: com.looker.droidify.database.entity.Installed, val isSystem: Boolean,
|
|
||||||
val launcherActivities: List<Pair<String, String>>,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,9 @@ import android.content.ActivityNotFoundException
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.ApplicationInfo
|
||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.content.pm.Signature
|
import android.content.pm.Signature
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
@ -37,9 +39,16 @@ import java.security.cert.CertificateEncodingException
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
object Utils {
|
object Utils {
|
||||||
fun PackageInfo.toInstalledItem(): Installed {
|
fun PackageInfo.toInstalledItem(launcherActivities: List<Pair<String, String>> = emptyList()): Installed {
|
||||||
val signatureString = singleSignature?.let(Utils::calculateHash).orEmpty()
|
val signatureString = singleSignature?.let(Utils::calculateHash).orEmpty()
|
||||||
return Installed(packageName, versionName.orEmpty(), versionCodeCompat, signatureString)
|
return Installed(
|
||||||
|
packageName,
|
||||||
|
versionName.orEmpty(),
|
||||||
|
versionCodeCompat,
|
||||||
|
signatureString,
|
||||||
|
applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM == ApplicationInfo.FLAG_SYSTEM,
|
||||||
|
launcherActivities
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDefaultApplicationIcon(context: Context): Drawable =
|
fun getDefaultApplicationIcon(context: Context): Drawable =
|
||||||
@ -224,4 +233,25 @@ fun Context.showBatteryOptimizationDialog() {
|
|||||||
Preferences[Preferences.Key.IgnoreIgnoreBatteryOptimization] = true
|
Preferences[Preferences.Key.IgnoreIgnoreBatteryOptimization] = true
|
||||||
}
|
}
|
||||||
.show()
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun PackageManager.getLaunchActivities(packageName: String): List<Pair<String, String>> =
|
||||||
|
queryIntentActivities(Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER), 0)
|
||||||
|
.mapNotNull { resolveInfo -> resolveInfo.activityInfo }
|
||||||
|
.filter { activityInfo -> activityInfo.packageName == packageName }
|
||||||
|
.mapNotNull { activityInfo ->
|
||||||
|
val label = try {
|
||||||
|
activityInfo.loadLabel(this).toString()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
null
|
||||||
|
}
|
||||||
|
label?.let { labelName ->
|
||||||
|
Pair(
|
||||||
|
activityInfo.name,
|
||||||
|
labelName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.toList()
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user