From b51a3f695eb35934725b5b17695914c7e862df9c Mon Sep 17 00:00:00 2001 From: frknkrc44 Date: Thu, 11 Sep 2025 03:46:37 +0300 Subject: [PATCH] Add "Show presets" option, fix backup/restore config buttons, update translations --- .../hidemyapplist/service/ConfigManager.kt | 1 + .../hidemyapplist/service/ServiceClient.kt | 3 + .../ui/fragment/AppSelectFragment.kt | 28 ++++--- .../ui/fragment/TemplateManageFragment.kt | 4 +- .../hidemyapplist/util/PackageHelper.kt | 36 ++++++--- .../hma_oss/ui/adapter/AppPresetAdapter.kt | 58 ++++++++++++++ .../ui/adapter/AppPresetListAdapter.kt | 75 +++++++++++++++++++ .../hma_oss/ui/fragment/AppPresetFragment.kt | 50 +++++++++++++ .../hma_oss/ui/fragment/HomeFragment.kt | 8 ++ .../ui/fragment/PresetManageFragment.kt | 73 ++++++++++++++++++ app/src/main/res/layout/fragment_home.xml | 8 ++ .../res/layout/fragment_preset_manage.xml | 32 ++++++++ .../main/res/navigation/home_nav_graph.xml | 14 ++++ app/src/main/res/values/dimens.xml | 1 + app/src/main/res/values/strings.xml | 4 +- .../hidemyapplist/common/IHMAService.aidl | 2 + .../common/app_presets/BasePreset.kt | 2 + gradle/libs.versions.toml | 3 +- .../hidemyapplist/xposed/HMAService.kt | 3 + .../hidemyapplist/xposed/XposedEntry.kt | 3 - .../xposed/hook/PmsHookTarget28.kt | 4 - .../xposed/hook/PmsHookTarget30.kt | 1 - .../xposed/hook/PmsHookTarget33.kt | 5 -- .../xposed/hook/PmsHookTarget34.kt | 1 - 24 files changed, 380 insertions(+), 39 deletions(-) create mode 100644 app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/AppPresetAdapter.kt create mode 100644 app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/AppPresetListAdapter.kt create mode 100644 app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/AppPresetFragment.kt create mode 100644 app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/PresetManageFragment.kt create mode 100644 app/src/main/res/layout/fragment_preset_manage.xml diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/service/ConfigManager.kt b/app/src/main/java/icu/nullptr/hidemyapplist/service/ConfigManager.kt index e3ebdb1..76021b4 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/service/ConfigManager.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/service/ConfigManager.kt @@ -12,6 +12,7 @@ import java.io.File object ConfigManager { data class TemplateInfo(val name: String?, val isWhiteList: Boolean) + data class PresetInfo(val name: String, val translation: String) private const val TAG = "ConfigManager" private lateinit var config: JsonConfig diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/service/ServiceClient.kt b/app/src/main/java/icu/nullptr/hidemyapplist/service/ServiceClient.kt index 18e735e..6061701 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/service/ServiceClient.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/service/ServiceClient.kt @@ -88,6 +88,9 @@ object ServiceClient : IHMAService, IBinder.DeathRecipient { getServiceLegacy()?.handlePackageEvent(eventType, packageName) } + override fun getPackagesForPreset(presetName: String) = + getServiceLegacy()?.getPackagesForPreset(presetName) + override fun syncConfig(json: String) { getServiceLegacy()?.syncConfig(json) } diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/AppSelectFragment.kt b/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/AppSelectFragment.kt index 4f3845d..45627d4 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/AppSelectFragment.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/AppSelectFragment.kt @@ -4,7 +4,6 @@ import android.os.Build import android.os.Bundle import android.view.MenuItem import android.view.View -import android.view.ViewGroup import android.view.WindowInsets import android.widget.TextView import androidx.activity.addCallback @@ -23,6 +22,7 @@ import icu.nullptr.hidemyapplist.util.PackageHelper import kotlinx.coroutines.launch import org.frknkrc44.hma_oss.R import org.frknkrc44.hma_oss.databinding.FragmentAppSelectBinding +import org.frknkrc44.hma_oss.ui.fragment.AppPresetFragment abstract class AppSelectFragment : Fragment(R.layout.fragment_app_select) { @@ -37,11 +37,11 @@ abstract class AppSelectFragment : Fragment(R.layout.fragment_app_select) { navController.navigateUp() } - private fun applyFilter() { + protected fun applyFilter() { adapter.filter.filter(search) } - private fun sortList() { + protected open fun sortList() { lifecycleScope.launch { PackageHelper.sortList(firstComparator) applyFilter() @@ -78,11 +78,13 @@ abstract class AppSelectFragment : Fragment(R.layout.fragment_app_select) { sortList() } + open fun getFragmentTitle() = getString(R.string.title_app_select) + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { onBack() } setupToolbar( toolbar = binding.toolbar, - title = getString(R.string.title_app_select), + title = getFragmentTitle(), navigationIcon = R.drawable.baseline_arrow_back_24, navigationOnClick = { onBack() }, menuRes = R.menu.menu_app_list, @@ -161,17 +163,23 @@ abstract class AppSelectFragment : Fragment(R.layout.fragment_app_select) { private val recyclerView: RecyclerView, private val emptyView: View ): RecyclerView.AdapterDataObserver() { - private val isScopeFragment = this@AppSelectFragment.javaClass == ScopeFragment::class.java + private val fragmentType by lazy { + when(this@AppSelectFragment.javaClass) { + ScopeFragment::class.java -> 0 + AppPresetFragment::class.java -> 1 + else -> 2 + } + } private fun checkIfEmpty() { - val emptyViewVisible = recyclerView.adapter!!.itemCount < if (isScopeFragment) 1 else 2 + val emptyViewVisible = recyclerView.adapter!!.itemCount < if (fragmentType < 2) 1 else 2 emptyView.visibility = if (emptyViewVisible) View.VISIBLE else View.GONE if (emptyViewVisible) { emptyView.findViewById(R.id.list_empty_text).text = getString( - if (isScopeFragment) { - R.string.list_empty_no_enabled - } else { - R.string.list_empty_no_apps + when (fragmentType) { + 0 -> R.string.list_empty_no_enabled + 1 -> R.string.list_empty_preset + else -> R.string.list_empty_no_apps } ) } diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/TemplateManageFragment.kt b/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/TemplateManageFragment.kt index 649cb7b..2537a3c 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/TemplateManageFragment.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/ui/fragment/TemplateManageFragment.kt @@ -1,6 +1,5 @@ package icu.nullptr.hidemyapplist.ui.fragment -import android.graphics.Color import android.os.Build import android.os.Bundle import android.view.View @@ -12,7 +11,6 @@ import androidx.fragment.app.setFragmentResultListener import androidx.navigation.fragment.FragmentNavigatorExtras import androidx.recyclerview.widget.LinearLayoutManager import by.kirich1409.viewbindingdelegate.viewBinding -import com.google.android.material.transition.MaterialContainerTransform import icu.nullptr.hidemyapplist.common.JsonConfig import icu.nullptr.hidemyapplist.service.ConfigManager import icu.nullptr.hidemyapplist.ui.adapter.TemplateAdapter @@ -28,10 +26,12 @@ class TemplateManageFragment : Fragment(R.layout.fragment_template_manage) { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + /* sharedElementEnterTransition = MaterialContainerTransform().apply { drawingViewId = R.id.nav_host_fragment scrimColor = Color.TRANSPARENT } + */ } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/util/PackageHelper.kt b/app/src/main/java/icu/nullptr/hidemyapplist/util/PackageHelper.kt index d360147..950fbb2 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/util/PackageHelper.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/util/PackageHelper.kt @@ -26,11 +26,15 @@ object PackageHelper { val icon: Bitmap ) - private object Comparators { + object Comparators { val byLabel = Comparator { o1, o2 -> - val n1 = loadAppLabel(o1).lowercase(Locale.getDefault()) - val n2 = loadAppLabel(o2).lowercase(Locale.getDefault()) - Collator.getInstance(Locale.getDefault()).compare(n1, n2) + try { + val n1 = loadAppLabel(o1).lowercase(Locale.getDefault()) + val n2 = loadAppLabel(o2).lowercase(Locale.getDefault()) + Collator.getInstance(Locale.getDefault()).compare(n1, n2) + } catch (_: Throwable) { + byPackageName.compare(o1, o2) + } } val byPackageName = Comparator { o1, o2 -> val n1 = o1.lowercase(Locale.getDefault()) @@ -38,14 +42,22 @@ object PackageHelper { Collator.getInstance(Locale.getDefault()).compare(n1, n2) } val byInstallTime = Comparator { o1, o2 -> - val n1 = loadPackageInfo(o1).firstInstallTime - val n2 = loadPackageInfo(o2).firstInstallTime - n2.compareTo(n1) + try { + val n1 = loadPackageInfo(o1).firstInstallTime + val n2 = loadPackageInfo(o2).firstInstallTime + n2.compareTo(n1) + } catch (_: Throwable) { + byPackageName.compare(o1, o2) + } } val byUpdateTime = Comparator { o1, o2 -> - val n1 = loadPackageInfo(o1).lastUpdateTime - val n2 = loadPackageInfo(o2).lastUpdateTime - n2.compareTo(n1) + try { + val n1 = loadPackageInfo(o1).lastUpdateTime + val n2 = loadPackageInfo(o2).lastUpdateTime + n2.compareTo(n1) + } catch (_: Throwable) { + byPackageName.compare(o1, o2) + } } } @@ -99,6 +111,10 @@ object PackageHelper { mAppList.emit(list) } + fun exists(packageName: String) = runBlocking { + packageCache.first().contains(packageName) + } + fun loadPackageInfo(packageName: String): PackageInfo = runBlocking { packageCache.first()[packageName]!!.info } diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/AppPresetAdapter.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/AppPresetAdapter.kt new file mode 100644 index 0000000..89381ad --- /dev/null +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/AppPresetAdapter.kt @@ -0,0 +1,58 @@ +package org.frknkrc44.hma_oss.ui.adapter + +import android.view.ViewGroup +import android.widget.Filter +import icu.nullptr.hidemyapplist.service.ServiceClient +import icu.nullptr.hidemyapplist.ui.adapter.AppSelectAdapter +import icu.nullptr.hidemyapplist.ui.view.AppItemView +import icu.nullptr.hidemyapplist.util.PackageHelper +import kotlinx.coroutines.runBlocking + +class AppPresetAdapter( + private val presetName: String +) : AppSelectAdapter() { + val packages by lazy { ServiceClient.getPackagesForPreset(presetName)?.toMutableList() ?: mutableListOf() } + + inner class ViewHolder(view: AppItemView) : AppSelectAdapter.ViewHolder(view) { + override fun bind(packageName: String) { + (itemView as AppItemView).let { + it.load(packageName) + it.alpha = if (!PackageHelper.exists(packageName)) 0.5f else 1.0f + } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val view = AppItemView(parent.context, false) + view.layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + return ViewHolder(view) + } + + private inner class PresetFilter : Filter() { + override fun performFiltering(constraint: CharSequence): FilterResults { + return runBlocking { + val constraintLowered = constraint.toString().lowercase() + val filteredList = packages.filter { + if (constraintLowered.isEmpty()) return@filter true + val label = PackageHelper.loadAppLabel(it) + label.lowercase().contains(constraintLowered) || it.lowercase().contains(constraintLowered) + } + + FilterResults().also { it.values = filteredList } + } + } + + @Suppress("UNCHECKED_CAST", "NotifyDataSetChanged") + override fun publishResults(constraint: CharSequence, results: FilterResults) { + filteredList = results.values as List + notifyDataSetChanged() + } + } + + private val mFilter = PresetFilter() + + override fun getFilter(): Filter = mFilter +} diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/AppPresetListAdapter.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/AppPresetListAdapter.kt new file mode 100644 index 0000000..b27062b --- /dev/null +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/adapter/AppPresetListAdapter.kt @@ -0,0 +1,75 @@ +package org.frknkrc44.hma_oss.ui.adapter + +import android.annotation.SuppressLint +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import icu.nullptr.hidemyapplist.common.AppPresets +import icu.nullptr.hidemyapplist.hmaApp +import icu.nullptr.hidemyapplist.service.ConfigManager +import icu.nullptr.hidemyapplist.ui.view.ListItemView +import org.frknkrc44.hma_oss.BuildConfig +import org.frknkrc44.hma_oss.R + +class AppPresetListAdapter( + private val onClickListener: ((ConfigManager.PresetInfo) -> Unit)? +) : RecyclerView.Adapter() { + + private lateinit var list: List + + init { + updateList() + } + + inner class ViewHolder(view: ListItemView) : RecyclerView.ViewHolder(view) { + init { + view.setOnClickListener { + onClickListener?.invoke(list[absoluteAdapterPosition]) + } + } + + fun bind(presetName: String) { + with(itemView as ListItemView) { + setIcon(R.drawable.baseline_assignment_24) + text = presetName + } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val view = ListItemView(parent.context) + view.layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + return ViewHolder(view) + } + + override fun getItemCount() = list.size + + override fun getItemId(position: Int) = list[position].name.hashCode().toLong() + + override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(list[position].translation) + + @SuppressLint("NotifyDataSetChanged") + fun updateList() { + val presetNames = AppPresets.instance.getAllPresetNames() + val presetTranslations = presetNames.map { name -> + try { + val id = hmaApp.resources.getIdentifier( + "preset_${name}", + "string", + BuildConfig.APPLICATION_ID + ) + + return@map if (id != 0) { hmaApp.resources.getString(id) } else { name } + } catch (_: Throwable) {} + + name + } + + list = presetNames + .map { ConfigManager.PresetInfo(it, presetTranslations[presetNames.indexOf(it)]) } + .sortedWith { a, b -> a.translation.lowercase().compareTo(b.translation.lowercase()) } + notifyDataSetChanged() + } +} diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/AppPresetFragment.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/AppPresetFragment.kt new file mode 100644 index 0000000..43225a3 --- /dev/null +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/AppPresetFragment.kt @@ -0,0 +1,50 @@ +package org.frknkrc44.hma_oss.ui.fragment + +import android.os.Bundle +import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.navArgs +import icu.nullptr.hidemyapplist.service.PrefManager +import icu.nullptr.hidemyapplist.ui.fragment.AppSelectFragment +import icu.nullptr.hidemyapplist.util.PackageHelper +import icu.nullptr.hidemyapplist.util.PackageHelper.Comparators +import kotlinx.coroutines.launch +import org.frknkrc44.hma_oss.ui.adapter.AppPresetAdapter + +class AppPresetFragment() : AppSelectFragment() { + + override val firstComparator = Comparator.comparing(PackageHelper::exists).reversed() + + override val adapter by lazy { + val args by navArgs() + AppPresetAdapter(args.presetName) + } + + override fun getFragmentTitle(): String { + val args by navArgs() + return args.presetTitle + } + + override fun sortList() { + lifecycleScope.launch { + sortPresetList() + applyFilter() + } + } + + fun sortPresetList() { + var comparator = when (PrefManager.appFilter_sortMethod) { + PrefManager.SortMethod.BY_LABEL -> Comparators.byLabel + PrefManager.SortMethod.BY_PACKAGE_NAME -> Comparators.byPackageName + PrefManager.SortMethod.BY_INSTALL_TIME -> Comparators.byInstallTime + PrefManager.SortMethod.BY_UPDATE_TIME -> Comparators.byUpdateTime + } + if (PrefManager.appFilter_reverseOrder) comparator = comparator.reversed() + adapter.packages.sortWith(firstComparator.then(comparator)) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + // enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true) + // returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/HomeFragment.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/HomeFragment.kt index 62fc204..68b0a8c 100644 --- a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/HomeFragment.kt +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/HomeFragment.kt @@ -267,6 +267,14 @@ class HomeFragment : Fragment(R.layout.fragment_home) { } } + with(binding.managePresets) { + text1.text = getString(R.string.title_preset_manage) + icon.setImageResource(R.drawable.baseline_my_location_24) + root.setOnClickListener { + navigate(R.id.nav_presets) + } + } + with(binding.navLogs) { text1.text = getString(R.string.title_logs) icon.setImageResource(R.drawable.outline_assignment_24) diff --git a/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/PresetManageFragment.kt b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/PresetManageFragment.kt new file mode 100644 index 0000000..d57c65b --- /dev/null +++ b/app/src/main/java/org/frknkrc44/hma_oss/ui/fragment/PresetManageFragment.kt @@ -0,0 +1,73 @@ +package org.frknkrc44.hma_oss.ui.fragment + +import android.os.Build +import android.os.Bundle +import android.view.View +import android.view.WindowInsets +import androidx.core.view.doOnPreDraw +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager +import by.kirich1409.viewbindingdelegate.viewBinding +import icu.nullptr.hidemyapplist.service.ConfigManager +import icu.nullptr.hidemyapplist.ui.util.navController +import icu.nullptr.hidemyapplist.ui.util.setupToolbar +import org.frknkrc44.hma_oss.R +import org.frknkrc44.hma_oss.databinding.FragmentPresetManageBinding +import org.frknkrc44.hma_oss.ui.adapter.AppPresetListAdapter + +class PresetManageFragment : Fragment(R.layout.fragment_preset_manage) { + + private val binding by viewBinding() + private val adapter = AppPresetListAdapter(this::navigateToPreset) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + /* + sharedElementEnterTransition = MaterialContainerTransform().apply { + drawingViewId = R.id.nav_host_fragment + scrimColor = Color.TRANSPARENT + } + */ + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + setupToolbar( + toolbar = binding.toolbar, + title = getString(R.string.title_preset_manage), + navigationIcon = R.drawable.baseline_arrow_back_24, + navigationOnClick = { navController.navigateUp() } + ) + postponeEnterTransition() + view.doOnPreDraw { startPostponedEnterTransition() } + + binding.presetList.layoutManager = LinearLayoutManager(context) + binding.presetList.adapter = adapter + + binding.root.setOnApplyWindowInsetsListener { v, insets -> + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + val barInsets = insets.getInsets(WindowInsets.Type.systemBars()) + binding.root.setPadding( + barInsets.left, + barInsets.top, + barInsets.right, + barInsets.bottom, + ) + } else { + @Suppress("deprecation") + binding.root.setPadding( + insets.systemWindowInsetLeft, + insets.systemWindowInsetTop, + insets.systemWindowInsetRight, + insets.systemWindowInsetBottom, + ) + } + + insets + } + } + + private fun navigateToPreset(presetInfo: ConfigManager.PresetInfo) { + val args = AppPresetFragmentArgs(presetInfo.name, presetInfo.translation) + navController.navigate(R.id.nav_preset_inner_manage, args.toBundle()) + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 798f570..5f03305 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -54,6 +54,10 @@ android:id="@+id/manage_templates" layout="@layout/view_home_item" /> + + @@ -75,6 +79,8 @@ android:id="@+id/backup_config" app:icon="@drawable/outline_backup_24" android:text="@string/home_backup_config" + android:maxLines="1" + android:ellipsize="end" android:layout_marginRight="8dp" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -84,6 +90,8 @@ android:id="@+id/restore_config" app:icon="@drawable/outline_settings_backup_restore_24" android:text="@string/home_restore_config" + android:maxLines="1" + android:ellipsize="end" android:layout_marginLeft="8dp" android:layout_width="match_parent" android:layout_height="wrap_content" diff --git a/app/src/main/res/layout/fragment_preset_manage.xml b/app/src/main/res/layout/fragment_preset_manage.xml new file mode 100644 index 0000000..2544f26 --- /dev/null +++ b/app/src/main/res/layout/fragment_preset_manage.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/navigation/home_nav_graph.xml b/app/src/main/res/navigation/home_nav_graph.xml index 914c535..3f8d60e 100644 --- a/app/src/main/res/navigation/home_nav_graph.xml +++ b/app/src/main/res/navigation/home_nav_graph.xml @@ -22,6 +22,10 @@ android:id="@+id/nav_template_manage" android:name="icu.nullptr.hidemyapplist.ui.fragment.TemplateManageFragment" android:label="@string/title_template_manage" /> + + + + + 6dp 1dp + 16dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0cc8451..8e0c3bb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -67,6 +67,7 @@ By update time Try enabling hiding for apps with this template\'s work mode and apps will appear here No applications found, maybe you didn\'t allow this app to query all packages + No applications added in this preset Establish templates for \"restless\" apps, controlling applist they can obtain.\n\nBlacklist (recommended): the apps selected in the template will be invisible to the apps applying the template.\nWhitelist: the apps not selected in the template will be invisible to the apps applying the template. @@ -106,7 +107,8 @@ You can enable it if this app is not available at Play Store Don\'t forget to force stop the target app after saving the configuration - + + Show presets LSPosed/Xposed modules Root managers/Rooted apps Custom ROM apps diff --git a/common/src/main/aidl/icu/nullptr/hidemyapplist/common/IHMAService.aidl b/common/src/main/aidl/icu/nullptr/hidemyapplist/common/IHMAService.aidl index 42a8607..12c19cb 100644 --- a/common/src/main/aidl/icu/nullptr/hidemyapplist/common/IHMAService.aidl +++ b/common/src/main/aidl/icu/nullptr/hidemyapplist/common/IHMAService.aidl @@ -15,4 +15,6 @@ interface IHMAService { void clearLogs() = 5; void handlePackageEvent(String eventType, String packageName) = 6; + + String[] getPackagesForPreset(String presetName) = 7; } diff --git a/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/BasePreset.kt b/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/BasePreset.kt index d317c34..43782d7 100644 --- a/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/BasePreset.kt +++ b/common/src/main/java/icu/nullptr/hidemyapplist/common/app_presets/BasePreset.kt @@ -12,6 +12,8 @@ abstract class BasePreset(val name: String) { fun containsPackage(packageName: String) = exactPackageNames.contains(packageName) || packageNames.contains(packageName) + val packages get() = packageNames + exactPackageNames + fun addPackageInfoPreset(appInfo: ApplicationInfo): Boolean { val packageName = appInfo.packageName if (!exactPackageNames.contains(packageName) && canBeAddedIntoPreset(appInfo)) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5889b09..13c7777 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.12.1" +agp = "8.13.0" kotlin = "2.1.10" material = "1.13.0-rc01" rxhttp = "3.3.1" @@ -13,7 +13,6 @@ kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", versi ksp = { id = "com.google.devtools.ksp", version = "2.1.10-1.0.31" } nav-safeargs-kotlin = { id = "androidx.navigation.safeargs.kotlin", version = "2.8.8" } autoresconfig = { id = "dev.rikka.tools.autoresconfig", version = "1.2.2" } -materialthemebuilder = { id = "dev.rikka.tools.materialthemebuilder", version = "1.5.1" } refine = { id = "dev.rikka.tools.refine", version = "4.4.0" } [libraries] diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/HMAService.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/HMAService.kt index 9777bf0..4d0d17e 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/HMAService.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/HMAService.kt @@ -277,4 +277,7 @@ class HMAService(val pms: IPackageManager) : IHMAService.Stub() { Intent.ACTION_PACKAGE_REMOVED -> AppPresets.instance.handlePackageRemoved(packageName) } } + + override fun getPackagesForPreset(presetName: String) = + AppPresets.instance.getPresetByName(presetName)?.packages?.toTypedArray() } diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/XposedEntry.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/XposedEntry.kt index f691005..0764690 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/XposedEntry.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/XposedEntry.kt @@ -3,14 +3,11 @@ package icu.nullptr.hidemyapplist.xposed import android.content.pm.IPackageManager import com.github.kyuubiran.ezxhelper.init.EzXHelperInit import com.github.kyuubiran.ezxhelper.utils.findMethod -import com.github.kyuubiran.ezxhelper.utils.getFieldByDesc -import com.github.kyuubiran.ezxhelper.utils.hookAllConstructorAfter import com.github.kyuubiran.ezxhelper.utils.hookBefore import de.robv.android.xposed.IXposedHookLoadPackage import de.robv.android.xposed.IXposedHookZygoteInit import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.callbacks.XC_LoadPackage -import icu.nullptr.hidemyapplist.common.Constants import kotlin.concurrent.thread private const val TAG = "HMA-XposedEntry" diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget28.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget28.kt index 873947a..12ab1bb 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget28.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget28.kt @@ -1,20 +1,16 @@ package icu.nullptr.hidemyapplist.xposed.hook import android.content.pm.ResolveInfo -import android.os.Binder import com.github.kyuubiran.ezxhelper.utils.findMethod import com.github.kyuubiran.ezxhelper.utils.hookAfter import com.github.kyuubiran.ezxhelper.utils.hookBefore -import de.robv.android.xposed.XC_MethodHook import icu.nullptr.hidemyapplist.common.Constants -import icu.nullptr.hidemyapplist.common.Constants.VENDING_PACKAGE_NAME import icu.nullptr.hidemyapplist.common.Utils import icu.nullptr.hidemyapplist.xposed.HMAService import icu.nullptr.hidemyapplist.xposed.Utils4Xposed import icu.nullptr.hidemyapplist.xposed.logD import icu.nullptr.hidemyapplist.xposed.logE import icu.nullptr.hidemyapplist.xposed.logI -import java.util.concurrent.atomic.AtomicReference class PmsHookTarget28(service: HMAService) : PmsHookTargetBase(service) { diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget30.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget30.kt index e33585b..7de7691 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget30.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget30.kt @@ -1,6 +1,5 @@ package icu.nullptr.hidemyapplist.xposed.hook -import android.content.pm.PackageManager import android.os.Build import androidx.annotation.RequiresApi import com.github.kyuubiran.ezxhelper.utils.findConstructor diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget33.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget33.kt index a5688a7..71fe3f9 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget33.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget33.kt @@ -1,16 +1,12 @@ package icu.nullptr.hidemyapplist.xposed.hook import android.content.pm.PackageInstaller -import android.content.pm.PackageManager -import android.os.Binder import android.os.Build import androidx.annotation.RequiresApi import com.github.kyuubiran.ezxhelper.utils.findConstructor import com.github.kyuubiran.ezxhelper.utils.findMethod -import com.github.kyuubiran.ezxhelper.utils.findMethodOrNull import com.github.kyuubiran.ezxhelper.utils.hookBefore import com.github.kyuubiran.ezxhelper.utils.paramCount -import de.robv.android.xposed.XC_MethodHook import icu.nullptr.hidemyapplist.common.Constants import icu.nullptr.hidemyapplist.common.Constants.VENDING_PACKAGE_NAME import icu.nullptr.hidemyapplist.common.Utils @@ -19,7 +15,6 @@ import icu.nullptr.hidemyapplist.xposed.Utils4Xposed import icu.nullptr.hidemyapplist.xposed.logD import icu.nullptr.hidemyapplist.xposed.logE import icu.nullptr.hidemyapplist.xposed.logI -import java.util.concurrent.atomic.AtomicReference @RequiresApi(Build.VERSION_CODES.TIRAMISU) class PmsHookTarget33(service: HMAService) : PmsHookTargetBase(service) { diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget34.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget34.kt index 5e67c86..5b8de07 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget34.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget34.kt @@ -1,7 +1,6 @@ package icu.nullptr.hidemyapplist.xposed.hook import android.content.pm.PackageInstaller -import android.content.pm.PackageManager import android.os.Binder import android.os.Build import androidx.annotation.RequiresApi