├── .github ├── FUNDING.yml └── workflows │ └── android.yml ├── .gitignore ├── LICENSE.md ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── aidl │ └── sunilpaulmathew │ │ └── appvaultx │ │ └── IShellService.aidl │ ├── assets │ └── uad_lists.json │ ├── ic_launcher-playstore.png │ ├── java │ └── in │ │ └── sunilpaulmathew │ │ └── appvaultx │ │ ├── activities │ │ ├── AppVaultXActivity.java │ │ └── InstallerActivity.java │ │ ├── adapters │ │ ├── BatchAdapter.java │ │ ├── BottomMenuAdapter.java │ │ ├── InstalledPackagesAdapter.java │ │ ├── LabelsAdapter.java │ │ ├── PolicyAdapter.java │ │ ├── RemovedPackagesAdapter.java │ │ └── SettingsAdapter.java │ │ ├── dialogs │ │ ├── AccessDeniedDialog.java │ │ ├── AccessUnavilableDialog.java │ │ ├── BatchDialog.java │ │ ├── BottomMenuDialog.java │ │ ├── InstallerDialog.java │ │ ├── PolicyDialog.java │ │ ├── ProgressDialog.java │ │ ├── SingleChoiceDialog.java │ │ └── WelcomeDialog.java │ │ ├── fragments │ │ ├── InstalledPackagesFragment.java │ │ ├── RemovedPackagesFragment.java │ │ └── SettingsFragment.java │ │ ├── serializable │ │ ├── DebloaterEntry.java │ │ ├── MenuEntry.java │ │ ├── PackagesEntry.java │ │ ├── PolicyEntry.java │ │ └── SettingsEntry.java │ │ ├── services │ │ └── ShellService.java │ │ └── utils │ │ ├── Async.java │ │ ├── Packages.java │ │ ├── Settings.java │ │ ├── ShizukuPermissionChecker.java │ │ ├── ShizukuShell.java │ │ └── Utils.java │ └── res │ ├── drawable │ ├── app_icon_bg.xml │ ├── ic_apps.xml │ ├── ic_cancel.xml │ ├── ic_check.xml │ ├── ic_delete.xml │ ├── ic_download.xml │ ├── ic_email.xml │ ├── ic_github.xml │ ├── ic_launcher_foreground.xml │ ├── ic_learn.xml │ ├── ic_menu.xml │ ├── ic_open.xml │ ├── ic_power.xml │ ├── ic_privacy.xml │ ├── ic_reset.xml │ ├── ic_save.xml │ ├── ic_search.xml │ ├── ic_select.xml │ ├── ic_settings.xml │ ├── ic_sort.xml │ ├── ic_sort_az.xml │ ├── ic_theme.xml │ ├── ic_translate.xml │ ├── ic_user.xml │ └── ic_warning.xml │ ├── layout │ ├── activity_main.xml │ ├── fragment_packages.xml │ ├── fragment_settings.xml │ ├── layout_about.xml │ ├── layout_app_data.xml │ ├── layout_batch.xml │ ├── layout_bottom_menu.xml │ ├── layout_installer.xml │ ├── layout_privacy_policy.xml │ ├── layout_progress.xml │ ├── layout_welcome.xml │ ├── recycle_view_batch.xml │ ├── recycle_view_bottom_menu.xml │ ├── recycle_view_labels.xml │ ├── recycle_view_packages.xml │ ├── recycle_view_policy.xml │ └── recycle_view_settings.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.webp │ ├── ic_launcher_background.webp │ └── ic_launcher_round.webp │ ├── mipmap-mdpi │ ├── ic_launcher.webp │ ├── ic_launcher_background.webp │ └── ic_launcher_round.webp │ ├── mipmap-xhdpi │ ├── ic_launcher.webp │ ├── ic_launcher_background.webp │ └── ic_launcher_round.webp │ ├── mipmap-xxhdpi │ ├── ic_launcher.webp │ ├── ic_launcher_background.webp │ └── ic_launcher_round.webp │ ├── mipmap-xxxhdpi │ ├── ic_launcher.webp │ ├── ic_launcher_background.webp │ └── ic_launcher_round.webp │ ├── values-ar │ └── strings.xml │ ├── values-de-rBE │ └── strings.xml │ ├── values-de │ └── strings.xml │ ├── values-el │ └── strings.xml │ ├── values-es-rMX │ └── strings.xml │ ├── values-es │ └── strings.xml │ ├── values-fr │ └── strings.xml │ ├── values-hu │ └── strings.xml │ ├── values-in │ └── strings.xml │ ├── values-ja │ └── strings.xml │ ├── values-ko │ └── strings.xml │ ├── values-pl │ └── strings.xml │ ├── values-pt-rBR │ └── strings.xml │ ├── values-pt-rPT │ └── strings.xml │ ├── values-ru │ └── strings.xml │ ├── values-tr │ └── strings.xml │ ├── values-v35 │ └── theme.xml │ ├── values-vi │ └── strings.xml │ ├── values-zh-rCN │ └── strings.xml │ ├── values-zh-rHK │ └── strings.xml │ ├── values-zh-rTW │ └── strings.xml │ ├── values │ ├── colors.xml │ ├── strings.xml │ └── theme.xml │ └── xml │ ├── backup_rules.xml │ └── data_extraction_rules.xml ├── build.gradle ├── fastlane └── metadata │ └── android │ └── en-US │ ├── changelogs │ └── 1.txt │ ├── full_description.txt │ ├── images │ ├── icon.png │ └── phoneScreenshots │ │ ├── 1.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ └── 5.png │ └── short_description.txt ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: sunilpaulmathew 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ['https://www.paypal.me/menacherry', 'https://play.google.com/store/apps/details?id=com.smartpack.donate'] 13 | -------------------------------------------------------------------------------- /.github/workflows/android.yml: -------------------------------------------------------------------------------- 1 | name: Android CI 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | 17 | # Set Current Date As Env Variable 18 | - name: Set current date as env variable 19 | run: echo "date_today=$(date +'%Y-%m-%d')" >> $GITHUB_ENV 20 | 21 | # Set App Name As Env Variable 22 | - name: Set repository name as env variable 23 | run: echo "repository_name=AppVaultX" >> $GITHUB_ENV 24 | 25 | - name: set up JDK 17 26 | uses: actions/setup-java@v4 27 | with: 28 | java-version: '17' 29 | distribution: 'temurin' 30 | cache: gradle 31 | 32 | - name: Grant execute permission for gradlew 33 | run: chmod +x ./gradlew 34 | 35 | # Run Tests Build 36 | - name: Run gradle tests 37 | run: ./gradlew test 38 | 39 | # Run Build Project 40 | - name: Build gradle project 41 | run: ./gradlew build 42 | 43 | # Create APK Release 44 | - name: Build apk release project (APK) - ${{ env.main_project_module }} module 45 | run: ./gradlew assemble 46 | 47 | # Upload Artifact Build 48 | - name: Upload APK Release - ${{ env.repository_name }} 49 | uses: actions/upload-artifact@v4 50 | with: 51 | name: ${{ env.repository_name }} - ${{ env.date_today }} - APK release generated 52 | path: app/build/outputs/apk/release/ -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | .idea/ 5 | /.idea/.name 6 | /.idea/caches 7 | /.idea/libraries 8 | /.idea/modules.xml 9 | /.idea/workspace.xml 10 | /.idea/navEditor.xml 11 | /.idea/assetWizardSettings.xml 12 | .DS_Store 13 | /build 14 | /captures 15 | .externalNativeBuild 16 | .cxx 17 | local.properties 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🚀 AppVaultX — App Control Made Easy 2 | 3 | ### ⚙️ Requirements 4 | - A fully working [**Shizuku**](https://shizuku.rikka.app/) environment to unlock full system-level control. 5 | 6 | --- 7 | 8 | ## ✨ Features 9 | 10 | ### 🔍 Smart App Recommendations 11 | - Categorizes installed apps as **Recommended**, **Advanced**, **Expert**, or **Unsafe** 12 | - Powered by trusted data from the **[Universal Android Debloater Next Generation](https://github.com/0x192/universal-android-debloater)** project 13 | 14 | ### 🛠️ App Management with Shizuku Support 15 | Unlock powerful system-level tools when Shizuku is available: 16 | - 🧩 **Force Close Apps** – safely stop any running app 17 | - 🧹 **Clear Data & Cache** – free storage and reset apps 18 | - 📦 **Backup APKs & Icons** – save app files and icons for future use 19 | - 🗑️ **Uninstall Apps (Individual or Batch)** – remove unwanted apps efficiently 20 | - ♻️ **Restore Removed System Apps** – safely recover system apps 21 | 22 | ### 📱 Standard App Management (Without Shizuku) 23 | Enjoy core app control features even without elevated permissions: 24 | - 🔍 **Package Viewer** – explore installed apps and details 25 | - ▶️ **Open Apps** – launch any installed app directly 26 | - 💾 **Save APKs & Icons** – backup apps locally 27 | - ⚙️ **Access System Settings** – quick shortcuts to app-related settings 28 | 29 | ### 💎 User Experience 30 | - 🎨 **Modern Material Design UI** – sleek, clean, and intuitive 31 | - 🧺 **Batch Operations** – manage multiple apps effortlessly 32 | 33 | --- 34 | 35 | ## ❤️ Support Development 36 | 37 | If you appreciate the developer’s effort in keeping this app **free**, **ad-free**, and **open-source**, please consider supporting the project. 38 | Your contributions — even small ones — help maintain and improve AppVaultX. 39 | 40 |

41 | 42 | Donate via Liberapay 43 | 44 | 45 | Donate via PayPal 46 | 47 | 48 | Donate via Ko-fi 49 | 50 | 51 | Support via Play Store 52 | 53 |

54 | 55 | **Donation Links** 56 | - 🟡 **Liberapay** → [liberapay.com/sunilpaulmathew/donate](https://liberapay.com/sunilpaulmathew/donate) 57 | - 💙 **PayPal** → [paypal.me/menacherry](https://www.paypal.me/menacherry) 58 | - 📧 **PayPal Email** → [sunil.kde@gmail.com](mailto:sunil.kde@gmail.com) 59 | - ☕ **Ko-fi** → [ko-fi.com/sunilpaulmathew](https://ko-fi.com/sunilpaulmathew) 60 | 61 | --- 62 | 63 | ### 🤝 Other Ways to Support 64 | 1. 🧠 Contribute code to improve this project. 65 | 2. 🌍 [Translate](https://poeditor.com/join/project/9RjHEoKPIK) AppVaultX into your local language (or refine existing translations). 66 | 3. 📢 Spread the word — share AppVaultX with friends, family, and Android communities. 67 | 68 | --- 69 | 70 | ## 📄 License 71 | 72 | Copyright (C) 2025 sunilpaulmathew 73 | 74 | AppVaultX is a free softwares: you can redistribute it and/or modify it 75 | under the terms of the GNU General Public License as published by the 76 | Free Software Foundation, either version 3 of the License, or (at 77 | your option) any later version. 78 | 79 | AppVaultX is distributed in the hope that it will be useful, but WITHOUT 80 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 81 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 82 | for more details. 83 | 84 | You should have received a copy of the GNU General Public License along 85 | with AppVaultX. If not, see . -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /release 3 | *.jks -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.androidApplication) 3 | } 4 | 5 | def keystoreFile = rootProject.file("app/sp.jks") 6 | 7 | android { 8 | if (keystoreFile.exists()) { 9 | signingConfigs { 10 | release { 11 | storeFile file("sp.jks") 12 | storePassword "smartpack" 13 | keyAlias "sp_key1" 14 | keyPassword "smartpack" 15 | } 16 | } 17 | } 18 | 19 | dependenciesInfo { 20 | includeInApk = false 21 | includeInBundle = false 22 | } 23 | 24 | namespace 'in.sunilpaulmathew.appvaultx' 25 | compileSdk 36 26 | 27 | defaultConfig { 28 | applicationId "in.sunilpaulmathew.appvaultx" 29 | minSdk 24 30 | targetSdk 35 31 | versionCode 1 32 | versionName "beta-v0.1" 33 | } 34 | 35 | buildTypes { 36 | debug { 37 | applicationIdSuffix '.debug' 38 | } 39 | release { 40 | if (keystoreFile.exists()) { 41 | signingConfig signingConfigs.release 42 | } 43 | minifyEnabled true 44 | shrinkResources true 45 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 46 | } 47 | } 48 | buildFeatures { 49 | viewBinding = true 50 | buildConfig = true 51 | aidl true 52 | } 53 | } 54 | 55 | dependencies { 56 | implementation libs.material 57 | implementation libs.preference 58 | implementation libs.shizukuApi 59 | implementation libs.shizukuProvider 60 | } 61 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | -keep class in.sunilpaulmathew.appvaultx.services.ShellService -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 7 | 9 | 11 | 12 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/aidl/sunilpaulmathew/appvaultx/IShellService.aidl: -------------------------------------------------------------------------------- 1 | package sunilpaulmathew.appvaultx; 2 | 3 | interface IShellService { 4 | String runCommand(String command) = 0; 5 | void runCommands(String commands) = 1; 6 | void writeToFile(in ParcelFileDescriptor pfd, String path) = 2; 7 | void destroyProcess() = 3; 8 | } -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/activities/AppVaultXActivity.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.activities; 2 | 3 | import android.content.ComponentName; 4 | import android.content.pm.PackageManager; 5 | import android.os.Bundle; 6 | import android.view.Menu; 7 | 8 | import androidx.appcompat.app.AppCompatActivity; 9 | import androidx.fragment.app.Fragment; 10 | 11 | import com.google.android.material.bottomnavigation.BottomNavigationView; 12 | 13 | import in.sunilpaulmathew.appvaultx.R; 14 | import in.sunilpaulmathew.appvaultx.dialogs.AccessUnavilableDialog; 15 | import in.sunilpaulmathew.appvaultx.dialogs.WelcomeDialog; 16 | import in.sunilpaulmathew.appvaultx.fragments.InstalledPackagesFragment; 17 | import in.sunilpaulmathew.appvaultx.fragments.SettingsFragment; 18 | import in.sunilpaulmathew.appvaultx.fragments.RemovedPackagesFragment; 19 | import in.sunilpaulmathew.appvaultx.utils.Settings; 20 | import in.sunilpaulmathew.appvaultx.utils.ShizukuPermissionChecker; 21 | import in.sunilpaulmathew.appvaultx.utils.ShizukuShell; 22 | import in.sunilpaulmathew.appvaultx.utils.Utils; 23 | import rikka.shizuku.Shizuku; 24 | 25 | /* 26 | * Created by sunilpaulmathew on October 18, 2025 27 | */ 28 | public class AppVaultXActivity extends AppCompatActivity { 29 | 30 | private final Shizuku.OnRequestPermissionResultListener REQUEST_PERMISSION_RESULT_LISTENER = this::onRequestPermissionsResult; 31 | 32 | @Override 33 | protected void onCreate(Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | 36 | // Initialize App Theme 37 | Settings.initializeAppTheme(this); 38 | 39 | setContentView(R.layout.activity_main); 40 | 41 | updateInstallerActivityState(); 42 | 43 | BottomNavigationView bottomNav = findViewById(R.id.bottom_navigation); 44 | 45 | Menu menu = bottomNav.getMenu(); 46 | menu.add(Menu.NONE, 0, Menu.NONE, null).setIcon(R.drawable.ic_apps); 47 | menu.add(Menu.NONE, 1, Menu.NONE, null).setIcon(R.drawable.ic_delete); 48 | menu.add(Menu.NONE, 2, Menu.NONE, null).setIcon(R.drawable.ic_menu); 49 | 50 | bottomNav.setOnItemSelectedListener(item -> { 51 | Fragment fragment = null; 52 | if (item.getItemId() == 0) fragment = new InstalledPackagesFragment(); 53 | else if (item.getItemId() == 1) fragment = new RemovedPackagesFragment(); 54 | else if (item.getItemId() == 2) fragment = new SettingsFragment(); 55 | 56 | if (fragment != null) { 57 | getSupportFragmentManager() 58 | .beginTransaction() 59 | .replace(R.id.fragment_container, fragment) 60 | .commitAllowingStateLoss(); 61 | } 62 | return true; 63 | }); 64 | 65 | if (savedInstanceState == null) { 66 | bottomNav.setSelectedItemId(0); 67 | } 68 | 69 | if (!Utils.getBoolean("welcome_dialog_viewed", false, this)) { 70 | new WelcomeDialog(this); 71 | } 72 | 73 | if (!Settings.isShizukuIgnored(this)) { 74 | if (Shizuku.pingBinder() && Shizuku.getVersion() >= 11) { 75 | new ShizukuPermissionChecker(this) { 76 | @Override 77 | public void onRequestingPermission() { 78 | // Request permission 79 | Shizuku.addRequestPermissionResultListener(REQUEST_PERMISSION_RESULT_LISTENER); 80 | Shizuku.requestPermission(0); 81 | } 82 | 83 | @Override 84 | public void onFinished() { 85 | } 86 | }; 87 | } else { 88 | new AccessUnavilableDialog(this).show(); 89 | } 90 | } 91 | } 92 | 93 | private void updateInstallerActivityState() { 94 | boolean shizukuAvailable = Shizuku.pingBinder() && Shizuku.getVersion() >= 11 && Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED; 95 | boolean shouldEnable = !Utils.isGooglePlayVersion(this) && shizukuAvailable; 96 | 97 | ComponentName installerActivity = new ComponentName(this, InstallerActivity.class); 98 | PackageManager pm = getPackageManager(); 99 | 100 | int currentState = pm.getComponentEnabledSetting(installerActivity); 101 | int desiredState = shouldEnable ? 102 | PackageManager.COMPONENT_ENABLED_STATE_ENABLED : 103 | PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 104 | 105 | if (currentState != desiredState) { 106 | pm.setComponentEnabledSetting( 107 | installerActivity, 108 | desiredState, 109 | PackageManager.DONT_KILL_APP 110 | ); 111 | } 112 | } 113 | 114 | private void onRequestPermissionsResult(int requestCode, int grantResult) { 115 | if (requestCode == 0 && grantResult == PackageManager.PERMISSION_GRANTED) { 116 | Utils.toast("AppVaultX got access to Shizuku service", this).show(); 117 | ShizukuShell.ensureUserService(null); 118 | } else { 119 | Utils.toast(getString(R.string.shizuku_access_denied_title), this).show(); 120 | } 121 | Shizuku.removeRequestPermissionResultListener(REQUEST_PERMISSION_RESULT_LISTENER); 122 | } 123 | 124 | @Override 125 | public void onDestroy() { 126 | super.onDestroy(); 127 | Shizuku.removeRequestPermissionResultListener(REQUEST_PERMISSION_RESULT_LISTENER); 128 | ShizukuShell.destroy(); 129 | } 130 | 131 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/adapters/BatchAdapter.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.adapters; 2 | 3 | import android.view.LayoutInflater; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | 7 | import androidx.annotation.NonNull; 8 | import androidx.appcompat.widget.AppCompatImageButton; 9 | import androidx.recyclerview.widget.RecyclerView; 10 | 11 | import com.google.android.material.checkbox.MaterialCheckBox; 12 | import com.google.android.material.textview.MaterialTextView; 13 | 14 | import java.util.List; 15 | 16 | import in.sunilpaulmathew.appvaultx.R; 17 | import in.sunilpaulmathew.appvaultx.serializable.PackagesEntry; 18 | 19 | /* 20 | * Created by sunilpaulmathew on October 18, 2025 21 | */ 22 | public class BatchAdapter extends RecyclerView.Adapter { 23 | 24 | private final List data; 25 | 26 | public BatchAdapter(List data) { 27 | this.data = data; 28 | } 29 | 30 | @NonNull 31 | @Override 32 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 33 | View rowItem = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycle_view_batch, parent, false); 34 | return new ViewHolder(rowItem); 35 | } 36 | 37 | @Override 38 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) { 39 | this.data.get(position).loadPackageInfo(holder.priority, holder.appIcon, holder.appName, holder.packageName); 40 | holder.checkBox.setChecked(this.data.get(position).isSelected()); 41 | 42 | holder.checkBox.setOnClickListener(v -> this.data.get(position).setSelected(holder.checkBox.isChecked())); 43 | } 44 | 45 | @Override 46 | public int getItemCount() { 47 | return data.size(); 48 | } 49 | 50 | public class ViewHolder extends RecyclerView.ViewHolder { 51 | private final AppCompatImageButton appIcon; 52 | private final MaterialCheckBox checkBox; 53 | private final MaterialTextView appName, packageName; 54 | private final RecyclerView priority; 55 | 56 | public ViewHolder(View view) { 57 | super(view); 58 | this.appIcon = view.findViewById(R.id.app_icon); 59 | this.checkBox = view.findViewById(R.id.checkbox); 60 | this.priority = view.findViewById(R.id.priority_list); 61 | this.appName = view.findViewById(R.id.app_name); 62 | this.packageName = view.findViewById(R.id.package_name); 63 | 64 | view.setOnClickListener(v -> data.get(getBindingAdapterPosition()).setSelected(checkBox.isChecked())); 65 | } 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/adapters/BottomMenuAdapter.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.adapters; 2 | 3 | import android.view.LayoutInflater; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | 7 | import androidx.annotation.NonNull; 8 | import androidx.appcompat.widget.AppCompatImageButton; 9 | import androidx.recyclerview.widget.RecyclerView; 10 | 11 | import com.google.android.material.textview.MaterialTextView; 12 | 13 | import java.util.List; 14 | 15 | import in.sunilpaulmathew.appvaultx.R; 16 | import in.sunilpaulmathew.appvaultx.serializable.MenuEntry; 17 | 18 | /* 19 | * Created by sunilpaulmathew on October 18, 2025 20 | */ 21 | public class BottomMenuAdapter extends RecyclerView.Adapter { 22 | 23 | private final List data; 24 | private final OnItemClickListener listener; 25 | 26 | public BottomMenuAdapter(List items, OnItemClickListener listener) { 27 | this.data = items; 28 | this.listener = listener; 29 | } 30 | 31 | @NonNull 32 | @Override 33 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 34 | View rowItem = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycle_view_bottom_menu, parent, false); 35 | return new ViewHolder(rowItem); 36 | } 37 | 38 | @Override 39 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) { 40 | MenuEntry item = this.data.get(position); 41 | holder.text.setText(item.getTile(holder.text.getContext())); 42 | holder.icon.setImageResource(item.getIcon()); 43 | } 44 | 45 | @Override 46 | public int getItemCount() { 47 | return data.size(); 48 | } 49 | 50 | public class ViewHolder extends RecyclerView.ViewHolder { 51 | private final AppCompatImageButton icon; 52 | private final MaterialTextView text; 53 | ViewHolder(@NonNull View view) { 54 | super(view); 55 | icon = view.findViewById(R.id.icon); 56 | text = view.findViewById(R.id.text); 57 | 58 | view.setOnClickListener(v -> listener.onItemClick(data.get(getBindingAdapterPosition()).getID())); 59 | } 60 | } 61 | 62 | public interface OnItemClickListener { 63 | void onItemClick(int id); 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/adapters/PolicyAdapter.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.adapters; 2 | 3 | import android.view.LayoutInflater; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | 7 | import androidx.annotation.NonNull; 8 | import androidx.recyclerview.widget.RecyclerView; 9 | 10 | import com.google.android.material.textview.MaterialTextView; 11 | 12 | import java.util.List; 13 | 14 | import in.sunilpaulmathew.appvaultx.R; 15 | import in.sunilpaulmathew.appvaultx.serializable.PolicyEntry; 16 | import in.sunilpaulmathew.appvaultx.utils.Settings; 17 | 18 | /* 19 | * Created by sunilpaulmathew on October 18, 2025 20 | */ 21 | public class PolicyAdapter extends RecyclerView.Adapter { 22 | 23 | private final List data; 24 | 25 | public PolicyAdapter(List data) { 26 | this.data = data; 27 | } 28 | 29 | @NonNull 30 | @Override 31 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 32 | View rowItem = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycle_view_policy, parent, false); 33 | return new ViewHolder(rowItem); 34 | } 35 | 36 | @Override 37 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) { 38 | holder.mTitle.setText(data.get(position).getTitle()); 39 | holder.mText.setText(data.get(position).getSummary()); 40 | holder.mText.setTextColor(holder.mText.getHintTextColors()); 41 | 42 | Settings.setSlideInAnimation(holder.itemView, position); 43 | } 44 | 45 | @Override 46 | public int getItemCount() { 47 | return data.size(); 48 | } 49 | 50 | public static class ViewHolder extends RecyclerView.ViewHolder { 51 | 52 | private final MaterialTextView mText, mTitle; 53 | 54 | public ViewHolder(View view) { 55 | super(view); 56 | this.mText = view.findViewById(R.id.text); 57 | this.mTitle = view.findViewById(R.id.title); 58 | view.setOnClickListener(v -> { 59 | if (mText.getMaxLines() == 1) { 60 | mText.setSingleLine(false); 61 | } else { 62 | mText.setMaxLines(1); 63 | } 64 | }); 65 | } 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/adapters/RemovedPackagesAdapter.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.adapters; 2 | 3 | import static android.view.View.GONE; 4 | import static android.view.View.VISIBLE; 5 | 6 | import android.annotation.SuppressLint; 7 | import android.content.pm.PackageManager; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | import androidx.annotation.NonNull; 13 | import androidx.appcompat.widget.AppCompatImageButton; 14 | import androidx.recyclerview.widget.RecyclerView; 15 | 16 | import com.google.android.material.button.MaterialButton; 17 | import com.google.android.material.checkbox.MaterialCheckBox; 18 | import com.google.android.material.dialog.MaterialAlertDialogBuilder; 19 | import com.google.android.material.textview.MaterialTextView; 20 | 21 | import java.util.List; 22 | 23 | import in.sunilpaulmathew.appvaultx.R; 24 | import in.sunilpaulmathew.appvaultx.dialogs.ProgressDialog; 25 | import in.sunilpaulmathew.appvaultx.serializable.PackagesEntry; 26 | import in.sunilpaulmathew.appvaultx.utils.Async; 27 | import in.sunilpaulmathew.appvaultx.utils.Packages; 28 | import in.sunilpaulmathew.appvaultx.utils.Settings; 29 | import in.sunilpaulmathew.appvaultx.utils.ShizukuShell; 30 | import rikka.shizuku.Shizuku; 31 | 32 | /* 33 | * Created by sunilpaulmathew on October 18, 2025 34 | */ 35 | public class RemovedPackagesAdapter extends RecyclerView.Adapter { 36 | 37 | private final List data, selectedApps; 38 | private final MaterialButton batchOptions; 39 | 40 | public RemovedPackagesAdapter(List data, List selectedApps, MaterialButton batchOptions) { 41 | this.data = data; 42 | this.selectedApps = selectedApps; 43 | this.batchOptions = batchOptions; 44 | } 45 | 46 | @NonNull 47 | @Override 48 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 49 | View rowItem = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycle_view_packages, parent, false); 50 | return new ViewHolder(rowItem); 51 | } 52 | 53 | @SuppressLint("StringFormatMatches") 54 | @Override 55 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) { 56 | this.data.get(position).loadPackageInfo(holder.priority, holder.appIcon, holder.appName, holder.packageName); 57 | 58 | if (!Settings.isShizukuIgnored(holder.appIcon.getContext()) && Shizuku.pingBinder() && Shizuku.getVersion() >= 11 && Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) { 59 | holder.appIcon.setClickable(true); 60 | if (selectedApps.contains(this.data.get(position))) { 61 | holder.checkBox.setChecked(selectedApps.contains(this.data.get(position))); 62 | holder.checkBox.setVisibility(VISIBLE); 63 | holder.appIcon.setVisibility(GONE); 64 | } else { 65 | holder.checkBox.setVisibility(GONE); 66 | holder.appIcon.setVisibility(VISIBLE); 67 | } 68 | 69 | if (selectedApps.isEmpty()) { 70 | batchOptions.setVisibility(GONE); 71 | } else { 72 | batchOptions.setText(batchOptions.getContext().getString(R.string.restore_selected, selectedApps.size())); 73 | batchOptions.setVisibility(VISIBLE); 74 | } 75 | 76 | holder.appIcon.setOnClickListener(v -> { 77 | holder.appIcon.setVisibility(GONE); 78 | holder.checkBox.setVisibility(VISIBLE); 79 | selectedApps.add(this.data.get(position)); 80 | notifyItemChanged(position); 81 | }); 82 | 83 | holder.checkBox.setOnClickListener(v -> { 84 | holder.appIcon.setVisibility(VISIBLE); 85 | holder.checkBox.setVisibility(GONE); 86 | selectedApps.remove(this.data.get(position)); 87 | notifyItemChanged(position); 88 | }); 89 | } else { 90 | holder.appIcon.setClickable(false); 91 | } 92 | 93 | Settings.setSlideInAnimation(holder.itemView, position); 94 | } 95 | 96 | @Override 97 | public int getItemCount() { 98 | return data.size(); 99 | } 100 | 101 | public class ViewHolder extends RecyclerView.ViewHolder { 102 | private final AppCompatImageButton appIcon; 103 | private final MaterialCheckBox checkBox; 104 | private final MaterialTextView appName, packageName; 105 | private final RecyclerView priority; 106 | 107 | public ViewHolder(View view) { 108 | super(view); 109 | this.appIcon = view.findViewById(R.id.app_icon); 110 | this.checkBox = view.findViewById(R.id.checkbox); 111 | this.priority = view.findViewById(R.id.priority_list); 112 | this.appName = view.findViewById(R.id.app_name); 113 | this.packageName = view.findViewById(R.id.package_name); 114 | 115 | view.setOnClickListener(v -> { 116 | if (!Settings.isShizukuIgnored(v.getContext()) && Shizuku.pingBinder() && Shizuku.getVersion() >= 11 && Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) { 117 | PackagesEntry packageItems = data.get(getBindingAdapterPosition()); 118 | if (!selectedApps.isEmpty()) { 119 | if (selectedApps.contains(packageItems)) { 120 | selectedApps.remove(packageItems); 121 | } else { 122 | selectedApps.add(packageItems); 123 | } 124 | notifyItemChanged(getBindingAdapterPosition()); 125 | return; 126 | } 127 | new MaterialAlertDialogBuilder(v.getContext()) 128 | .setIcon(packageItems.getAppIcon()) 129 | .setTitle(v.getContext().getString(R.string.restore_question, packageItems.getAppName())) 130 | .setNegativeButton(R.string.cancel, (dialogInterface, i) -> { 131 | }) 132 | .setPositiveButton(R.string.yes, (dialogInterface, i) -> 133 | new Async() { 134 | private ProgressDialog progressDialog; 135 | private String result; 136 | 137 | @Override 138 | public void onPreExecute() { 139 | progressDialog = new ProgressDialog(v.getContext()); 140 | progressDialog.setProgressStatus(R.string.applying); 141 | progressDialog.startDialog(); 142 | } 143 | 144 | @Override 145 | public void doInBackground() { 146 | result = ShizukuShell.runCommand("cmd package install-existing " + packageItems.getPackageName()); 147 | Packages.getUninstalledPackages().remove(packageItems); 148 | Packages.getPackages().add(new PackagesEntry(packageItems.getPackageName(), packageItems.getAPKPath(), packageItems.getRemovalRecommendation(), packageItems.getUADDescription(), packageItems.getAppType(), true)); 149 | } 150 | 151 | @Override 152 | public void onPostExecute() { 153 | progressDialog.dismissDialog(); 154 | data.remove(packageItems); 155 | notifyItemRemoved(getBindingAdapterPosition()); 156 | if (result != null && !result.trim().isEmpty()) { 157 | new MaterialAlertDialogBuilder(v.getContext()) 158 | .setIcon(packageItems.getAppIcon()) 159 | .setTitle(packageItems.getAppName()) 160 | .setTitle(result) 161 | .setPositiveButton(R.string.cancel, (dialogInterface, i) -> { 162 | }).show(); 163 | } 164 | } 165 | }.execute() 166 | ).show(); 167 | } 168 | }); 169 | } 170 | } 171 | 172 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/dialogs/AccessDeniedDialog.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.dialogs; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.content.pm.PackageManager; 6 | 7 | import com.google.android.material.dialog.MaterialAlertDialogBuilder; 8 | 9 | import in.sunilpaulmathew.appvaultx.R; 10 | import in.sunilpaulmathew.appvaultx.utils.Utils; 11 | 12 | /* 13 | * Created by sunilpaulmathew on October 18, 2025 14 | */ 15 | public class AccessDeniedDialog extends MaterialAlertDialogBuilder { 16 | 17 | public AccessDeniedDialog(Context context) { 18 | super(context); 19 | setCancelable(false); 20 | setIcon(R.mipmap.ic_launcher); 21 | setTitle(context.getString(R.string.shizuku_access_denied_title)); 22 | setMessage(context.getString(R.string.shizuku_access_denied_description) + "\n\n" + context.getString(R.string.shizuku_app_open_description)); 23 | setNeutralButton(R.string.ignore, (dialogInterface, i) -> Utils.saveInt("shizuku_mode", 1, context)); 24 | setPositiveButton(R.string.shizuku_open, (dialogInterface, i) -> { 25 | PackageManager pm = context.getPackageManager(); 26 | Intent launchIntent = pm.getLaunchIntentForPackage("moe.shizuku.privileged.api"); 27 | context.startActivity(launchIntent); 28 | }); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/dialogs/AccessUnavilableDialog.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.dialogs; 2 | 3 | import android.content.Context; 4 | 5 | import com.google.android.material.dialog.MaterialAlertDialogBuilder; 6 | 7 | import in.sunilpaulmathew.appvaultx.R; 8 | import in.sunilpaulmathew.appvaultx.utils.Utils; 9 | 10 | /* 11 | * Created by sunilpaulmathew on October 18, 2025 12 | */ 13 | public class AccessUnavilableDialog extends MaterialAlertDialogBuilder { 14 | 15 | public AccessUnavilableDialog(Context context) { 16 | super(context); 17 | setCancelable(false); 18 | setIcon(R.mipmap.ic_launcher); 19 | setTitle(context.getString(R.string.shizuku_unavailable_title)); 20 | setMessage(context.getString(R.string.shizuku_unavailable_description)); 21 | setNeutralButton(R.string.ignore, (dialogInterface, i) -> Utils.saveInt("shizuku_mode", 1, context)); 22 | setPositiveButton(R.string.shizuku_learn, (dialogInterface, i) -> 23 | Utils.loadUrl("https://shizuku.rikka.app/", context) 24 | ); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/dialogs/BatchDialog.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.dialogs; 2 | 3 | import android.content.Context; 4 | import android.graphics.drawable.Drawable; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.FrameLayout; 8 | 9 | import androidx.recyclerview.widget.DividerItemDecoration; 10 | import androidx.recyclerview.widget.LinearLayoutManager; 11 | import androidx.recyclerview.widget.RecyclerView; 12 | 13 | import com.google.android.material.bottomsheet.BottomSheetBehavior; 14 | import com.google.android.material.bottomsheet.BottomSheetDialog; 15 | import com.google.android.material.button.MaterialButton; 16 | 17 | import java.util.List; 18 | import java.util.concurrent.CopyOnWriteArrayList; 19 | 20 | import in.sunilpaulmathew.appvaultx.R; 21 | import in.sunilpaulmathew.appvaultx.adapters.BatchAdapter; 22 | import in.sunilpaulmathew.appvaultx.serializable.PackagesEntry; 23 | import in.sunilpaulmathew.appvaultx.utils.Async; 24 | 25 | /* 26 | * Created by sunilpaulmathew on October 18, 2025 27 | */ 28 | public abstract class BatchDialog extends BottomSheetDialog { 29 | 30 | public BatchDialog(List selectedApps, Drawable headerIcon, String headerText, String positiveButtonText, Context context) { 31 | super(context); 32 | 33 | View root = View.inflate(context, R.layout.layout_batch, null); 34 | 35 | MaterialButton title = root.findViewById(R.id.title); 36 | MaterialButton apply = root.findViewById(R.id.apply); 37 | MaterialButton cancel = root.findViewById(R.id.cancel); 38 | RecyclerView recyclerView = root.findViewById(R.id.recycler_view); 39 | 40 | recyclerView.setLayoutManager(new LinearLayoutManager(context)); 41 | recyclerView.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL)); 42 | recyclerView.setAdapter(new BatchAdapter(selectedApps)); 43 | 44 | title.setText(headerText); 45 | title.setIcon(headerIcon); 46 | apply.setText(positiveButtonText); 47 | 48 | setContentView(root); 49 | show(); 50 | 51 | root.post(() -> { 52 | FrameLayout bottomSheet = findViewById(com.google.android.material.R.id.design_bottom_sheet); 53 | if (bottomSheet != null) { 54 | bottomSheet.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT; 55 | 56 | BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet); 57 | behavior.setState(BottomSheetBehavior.STATE_EXPANDED); 58 | behavior.setSkipCollapsed(true); 59 | behavior.setFitToContents(true); 60 | } 61 | }); 62 | 63 | cancel.setOnClickListener(v -> dismiss()); 64 | 65 | apply.setOnClickListener(v -> new Async() { 66 | private List apps; 67 | @Override 68 | public void onPreExecute() { 69 | apps = new CopyOnWriteArrayList<>(); 70 | 71 | } 72 | 73 | @Override 74 | public void doInBackground() { 75 | for (PackagesEntry entry : selectedApps) { 76 | if (entry.isSelected()) { 77 | apps.add(entry.getPackageName()); 78 | } 79 | } 80 | } 81 | 82 | @Override 83 | public void onPostExecute() { 84 | if (!apps.isEmpty()) { 85 | positiveButtonListener(apps); 86 | } 87 | dismiss(); 88 | } 89 | }.execute() 90 | ); 91 | } 92 | 93 | public abstract void positiveButtonListener(List packageNames); 94 | 95 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/dialogs/BottomMenuDialog.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.dialogs; 2 | 3 | import android.content.Context; 4 | import android.graphics.drawable.Drawable; 5 | import android.view.View; 6 | 7 | import androidx.appcompat.widget.AppCompatImageButton; 8 | import androidx.recyclerview.widget.DividerItemDecoration; 9 | import androidx.recyclerview.widget.LinearLayoutManager; 10 | import androidx.recyclerview.widget.RecyclerView; 11 | 12 | import com.google.android.material.bottomsheet.BottomSheetDialog; 13 | import com.google.android.material.textview.MaterialTextView; 14 | 15 | import java.util.List; 16 | 17 | import in.sunilpaulmathew.appvaultx.R; 18 | import in.sunilpaulmathew.appvaultx.adapters.BottomMenuAdapter; 19 | import in.sunilpaulmathew.appvaultx.serializable.MenuEntry; 20 | 21 | /* 22 | * Created by sunilpaulmathew on October 18, 2025 23 | */ 24 | public abstract class BottomMenuDialog extends BottomSheetDialog { 25 | 26 | public BottomMenuDialog(List menuItems, Drawable headerIcon, String headerTitle, String headerDescription, Context context) { 27 | super(context); 28 | 29 | View rootView = View.inflate(context, R.layout.layout_bottom_menu, null); 30 | AppCompatImageButton icon = rootView.findViewById(R.id.app_icon); 31 | MaterialTextView title = rootView.findViewById(R.id.app_name); 32 | MaterialTextView description = rootView.findViewById(R.id.package_name); 33 | RecyclerView recyclerView = rootView.findViewById(R.id.recycler_view); 34 | 35 | title.setText(headerTitle); 36 | description.setText(headerDescription); 37 | icon.setImageDrawable(headerIcon); 38 | 39 | recyclerView.setItemAnimator(null); 40 | recyclerView.setLayoutManager(new LinearLayoutManager(context)); 41 | recyclerView.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL)); 42 | recyclerView.setAdapter(new BottomMenuAdapter(menuItems, id -> { 43 | onMenuItemClicked(id); 44 | dismiss(); 45 | })); 46 | setContentView(rootView); 47 | show(); 48 | } 49 | 50 | public abstract void onMenuItemClicked(int menuID); 51 | 52 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/dialogs/InstallerDialog.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.dialogs; 2 | 3 | import static android.view.View.VISIBLE; 4 | 5 | import android.app.Activity; 6 | import android.graphics.drawable.Drawable; 7 | import android.view.View; 8 | 9 | import androidx.appcompat.widget.AppCompatImageButton; 10 | 11 | import com.google.android.material.dialog.MaterialAlertDialogBuilder; 12 | import com.google.android.material.textview.MaterialTextView; 13 | 14 | import in.sunilpaulmathew.appvaultx.R; 15 | 16 | /* 17 | * Created by sunilpaulmathew on October 18, 2025 18 | */ 19 | public abstract class InstallerDialog extends MaterialAlertDialogBuilder { 20 | 21 | public InstallerDialog(Drawable appIcon, String appName, String packageName, String summary, boolean update, boolean downgrade, Activity activity) { 22 | super(activity); 23 | 24 | View rootView = View.inflate(activity, R.layout.layout_installer, null); 25 | AppCompatImageButton app_Icon = rootView.findViewById(R.id.app_icon); 26 | MaterialTextView app_Name = rootView.findViewById(R.id.app_name); 27 | MaterialTextView package_Name = rootView.findViewById(R.id.package_name); 28 | MaterialTextView app_summary = rootView.findViewById(R.id.summary); 29 | MaterialTextView install_question = rootView.findViewById(R.id.question); 30 | 31 | app_Name.setText(appName); 32 | package_Name.setText(packageName); 33 | app_Icon.setImageDrawable(appIcon); 34 | app_summary.setText(summary); 35 | install_question.setText(activity.getString(R.string.install_question, activity.getString(update ? downgrade ? R.string.downgrade : R.string.update : R.string.install))); 36 | install_question.setVisibility(VISIBLE); 37 | 38 | setView(rootView); 39 | setCancelable(false); 40 | setNeutralButton(R.string.cancel, (dialog, which) -> activity.finish()); 41 | setPositiveButton(activity.getString(update ? downgrade ? R.string.downgrade : R.string.update : R.string.install), (dialog, which) -> onInstall()); 42 | show(); 43 | } 44 | 45 | public abstract void onInstall(); 46 | 47 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/dialogs/PolicyDialog.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.dialogs; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | 6 | import androidx.recyclerview.widget.LinearLayoutManager; 7 | import androidx.recyclerview.widget.RecyclerView; 8 | 9 | import com.google.android.material.dialog.MaterialAlertDialogBuilder; 10 | import com.google.android.material.textview.MaterialTextView; 11 | 12 | import in.sunilpaulmathew.appvaultx.BuildConfig; 13 | import in.sunilpaulmathew.appvaultx.R; 14 | import in.sunilpaulmathew.appvaultx.adapters.PolicyAdapter; 15 | import in.sunilpaulmathew.appvaultx.utils.Settings; 16 | 17 | /* 18 | * Created by sunilpaulmathew on October 18, 2025 19 | */ 20 | public class PolicyDialog extends MaterialAlertDialogBuilder { 21 | 22 | public PolicyDialog(Context context) { 23 | super(context); 24 | 25 | View root = View.inflate(context, R.layout.layout_privacy_policy, null); 26 | MaterialTextView version = root.findViewById(R.id.title); 27 | RecyclerView recyclerView = root.findViewById(R.id.recycler_view); 28 | version.setText(context.getString(R.string.app_version, BuildConfig.VERSION_NAME)); 29 | recyclerView.setLayoutManager(new LinearLayoutManager(context)); 30 | recyclerView.setAdapter(new PolicyAdapter(Settings.getPolicyData())); 31 | setView(root); 32 | setPositiveButton(R.string.cancel, (dialog, id) -> { 33 | }); 34 | show(); 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/dialogs/ProgressDialog.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.dialogs; 2 | 3 | import android.content.Context; 4 | import android.graphics.drawable.Drawable; 5 | import android.view.View; 6 | 7 | import androidx.appcompat.app.AlertDialog; 8 | import androidx.appcompat.widget.AppCompatImageButton; 9 | import androidx.core.widget.ContentLoadingProgressBar; 10 | 11 | import com.google.android.material.dialog.MaterialAlertDialogBuilder; 12 | import com.google.android.material.textview.MaterialTextView; 13 | 14 | import in.sunilpaulmathew.appvaultx.R; 15 | import in.sunilpaulmathew.appvaultx.utils.Utils; 16 | 17 | /* 18 | * Created by sunilpaulmathew on October 18, 2025 19 | */ 20 | public class ProgressDialog extends MaterialAlertDialogBuilder { 21 | 22 | private final AlertDialog mAlertDialog; 23 | private final AppCompatImageButton mIcon; 24 | private final ContentLoadingProgressBar mProgressBar; 25 | private final MaterialTextView mTitle; 26 | 27 | public ProgressDialog(Context context) { 28 | super(context); 29 | 30 | View progressLayout = View.inflate(context, R.layout.layout_progress, null); 31 | mProgressBar = progressLayout.findViewById(R.id.progress); 32 | mIcon = progressLayout.findViewById(R.id.icon); 33 | mTitle = progressLayout.findViewById(R.id.title); 34 | 35 | mAlertDialog = new MaterialAlertDialogBuilder(context) 36 | .setView(progressLayout) 37 | .setCancelable(false) 38 | .create(); 39 | } 40 | 41 | public void setProgressIcon(Drawable drawable) { 42 | mIcon.setImageDrawable(drawable); 43 | } 44 | 45 | public void setProgressIcon(int resource) { 46 | mIcon.setImageDrawable(Utils.getDrawable(resource, mIcon.getContext())); 47 | } 48 | 49 | public void setProgressStatus(int resource) { 50 | mTitle.setText(mTitle.getContext().getString(resource)); 51 | } 52 | 53 | public void setProgressStatus(String title) { 54 | mTitle.setText(title); 55 | } 56 | 57 | public void startDialog() { 58 | if (!mAlertDialog.isShowing()) { 59 | mAlertDialog.show(); 60 | } 61 | } 62 | 63 | public void dismissDialog() { 64 | if (mAlertDialog.isShowing()) { 65 | mAlertDialog.dismiss(); 66 | } 67 | } 68 | 69 | public void updateProgress(int progress) { 70 | mProgressBar.setProgress(mProgressBar.getProgress() + progress); 71 | } 72 | 73 | public void setProgressMax(int max) { 74 | mProgressBar.setIndeterminate(false); 75 | mProgressBar.setMax(max); 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/dialogs/SingleChoiceDialog.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.dialogs; 2 | 3 | import android.content.Context; 4 | 5 | import com.google.android.material.dialog.MaterialAlertDialogBuilder; 6 | 7 | /* 8 | * Created by sunilpaulmathew on October 18, 2025 9 | */ 10 | public abstract class SingleChoiceDialog { 11 | 12 | private final int mIcon; 13 | private final int mPosition; 14 | private final MaterialAlertDialogBuilder mDialogBuilder; 15 | private final String mTitle; 16 | private final String[] mSingleChoiceItems; 17 | 18 | public SingleChoiceDialog(int icon, String title, String[] singleChoiceItems, 19 | int position, Context context) { 20 | this.mIcon = icon; 21 | this.mTitle = title; 22 | this.mSingleChoiceItems = singleChoiceItems; 23 | this.mPosition = position; 24 | this.mDialogBuilder = new MaterialAlertDialogBuilder(context); 25 | } 26 | 27 | private void startDialog() { 28 | if (mIcon > Integer.MIN_VALUE) { 29 | mDialogBuilder.setIcon(mIcon); 30 | } 31 | if (mTitle != null) { 32 | mDialogBuilder.setTitle(mTitle); 33 | } 34 | mDialogBuilder.setSingleChoiceItems(mSingleChoiceItems, mPosition, (dialog, itemPosition) -> { 35 | onItemSelected(itemPosition); 36 | dialog.dismiss(); 37 | }).show(); 38 | } 39 | 40 | public void show() { 41 | startDialog(); 42 | } 43 | 44 | public abstract void onItemSelected(int position); 45 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/dialogs/WelcomeDialog.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.dialogs; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.graphics.text.LineBreaker; 6 | import android.os.Build; 7 | import android.text.Html; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.FrameLayout; 11 | 12 | import com.google.android.material.bottomsheet.BottomSheetBehavior; 13 | import com.google.android.material.bottomsheet.BottomSheetDialog; 14 | import com.google.android.material.button.MaterialButton; 15 | import com.google.android.material.switchmaterial.SwitchMaterial; 16 | import com.google.android.material.textview.MaterialTextView; 17 | 18 | import in.sunilpaulmathew.appvaultx.BuildConfig; 19 | import in.sunilpaulmathew.appvaultx.R; 20 | import in.sunilpaulmathew.appvaultx.utils.Utils; 21 | 22 | /* 23 | * Created by sunilpaulmathew on October 18, 2025 24 | */ 25 | public class WelcomeDialog extends BottomSheetDialog { 26 | 27 | @SuppressLint("SourceLockedOrientationActivity") 28 | public WelcomeDialog(Context context) { 29 | super(context); 30 | 31 | //activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 32 | 33 | View root = View.inflate(context, R.layout.layout_welcome, null); 34 | 35 | MaterialTextView title = root.findViewById(R.id.title); 36 | MaterialTextView summary = root.findViewById(R.id.summary); 37 | SwitchMaterial neverShow = root.findViewById(R.id.never_show); 38 | MaterialButton start = root.findViewById(R.id.start); 39 | MaterialButton learnShizuku = root.findViewById(R.id.shizuku_learn); 40 | 41 | title.setText(context.getString(R.string.app_version, BuildConfig.VERSION_NAME)); 42 | summary.setText(Html.fromHtml(getSummaryText(), Html.FROM_HTML_MODE_LEGACY)); 43 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { 44 | summary.setJustificationMode(LineBreaker.JUSTIFICATION_MODE_INTER_WORD); 45 | } 46 | 47 | neverShow.setChecked(false); 48 | 49 | root.post(() -> { 50 | FrameLayout bottomSheet = findViewById(com.google.android.material.R.id.design_bottom_sheet); 51 | if (bottomSheet != null) { 52 | bottomSheet.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT; 53 | 54 | BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet); 55 | behavior.setState(BottomSheetBehavior.STATE_EXPANDED); 56 | behavior.setSkipCollapsed(true); 57 | behavior.setFitToContents(true); 58 | } 59 | }); 60 | 61 | setCancelable(false); 62 | setContentView(root); 63 | show(); 64 | 65 | learnShizuku.setOnClickListener(v -> { 66 | Utils.loadUrl("https://shizuku.rikka.app/", v.getContext()); 67 | dismiss(); 68 | }); 69 | 70 | start.setOnClickListener(v -> dismiss()); 71 | 72 | neverShow.setOnCheckedChangeListener((buttonView, isChecked) -> Utils.saveBoolean("welcome_dialog_viewed", isChecked, context)); 73 | } 74 | 75 | private static String getSummaryText() { 76 | return "Welcome to AppVaultX - App Control Made Easy
" + 77 | "
" + 78 | "\uD83D\uDCA1 AppVaultX helps you take control of your Android device with smart recommendations on which apps are safe to remove. Each app is categorized as Recommended, Advanced, Expert, or Unsafe, using trusted data from the Universal Android Debloater Next Generation project.
" + 79 | "
" + 80 | "⚡ With Shizuku support, AppVaultX unlocks powerful system-level tools — all within a sleek, modern Material Design interface. You can force close apps, clear data and cache, back up APKs and icons, uninstall apps individually or in batches, and even restore removed system apps with ease.
" + 81 | "
" + 82 | "\uD83D\uDCA1 Without Shizuku, AppVaultX works as a handy package viewer, letting you open installed apps, save APKs and icons, and access system settings.
" + 83 | "
" + 84 | "Important Notes
" + 85 | "
" + 86 | "\uD83C\uDF10 Open Source: AppVaultX is free and open-source. Contributions, bug reports, and translations are always welcome.
" + 87 | "
" + 88 | "⚠️ Disclaimer: Use AppVaultX at your own risk. The developers are not responsible for any data loss, system instability, or device damage."; 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/fragments/SettingsFragment.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.fragments; 2 | 3 | import android.content.Intent; 4 | import android.content.pm.PackageManager; 5 | import android.net.Uri; 6 | import android.os.Bundle; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | 11 | import androidx.activity.OnBackPressedCallback; 12 | import androidx.annotation.Nullable; 13 | import androidx.appcompat.widget.LinearLayoutCompat; 14 | import androidx.fragment.app.Fragment; 15 | import androidx.recyclerview.widget.LinearLayoutManager; 16 | import androidx.recyclerview.widget.RecyclerView; 17 | 18 | import com.google.android.material.textview.MaterialTextView; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | import in.sunilpaulmathew.appvaultx.BuildConfig; 24 | import in.sunilpaulmathew.appvaultx.R; 25 | import in.sunilpaulmathew.appvaultx.adapters.SettingsAdapter; 26 | import in.sunilpaulmathew.appvaultx.serializable.SettingsEntry; 27 | import in.sunilpaulmathew.appvaultx.utils.Settings; 28 | import in.sunilpaulmathew.appvaultx.utils.ShizukuShell; 29 | import in.sunilpaulmathew.appvaultx.utils.Utils; 30 | import rikka.shizuku.Shizuku; 31 | 32 | /* 33 | * Created by sunilpaulmathew on October 18, 2025 34 | */ 35 | public class SettingsFragment extends Fragment { 36 | 37 | private final Shizuku.OnRequestPermissionResultListener REQUEST_PERMISSION_RESULT_LISTENER = this::onRequestPermissionsResult; 38 | 39 | @Nullable 40 | @Override 41 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 42 | View mRootView = inflater.inflate(R.layout.fragment_settings, container, false); 43 | 44 | LinearLayoutCompat titleLayout = mRootView.findViewById(R.id.title_layout); 45 | MaterialTextView title = mRootView.findViewById(R.id.title); 46 | RecyclerView recyclerView = mRootView.findViewById(R.id.recycler_view); 47 | 48 | String titleText = getString(R.string.app_name) + " " + BuildConfig.VERSION_NAME; 49 | title.setText(titleText); 50 | 51 | recyclerView.setItemAnimator(null); 52 | 53 | recyclerView.setLayoutManager(new LinearLayoutManager(requireActivity())); 54 | 55 | recyclerView.setAdapter(new SettingsAdapter(getData(), REQUEST_PERMISSION_RESULT_LISTENER)); 56 | 57 | titleLayout.setOnClickListener(v -> { 58 | Intent settings = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 59 | settings.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 60 | Uri uri = Uri.fromParts("package", BuildConfig.APPLICATION_ID, null); 61 | settings.setData(uri); 62 | startActivity(settings); 63 | }); 64 | 65 | requireActivity().getOnBackPressedDispatcher().addCallback(new OnBackPressedCallback(true) { 66 | @Override 67 | public void handleOnBackPressed() { 68 | Settings.navigateToFragment(0, requireActivity()); 69 | } 70 | }); 71 | 72 | return mRootView; 73 | } 74 | 75 | private List getData() { 76 | List mData = new ArrayList<>(); 77 | mData.add(new SettingsEntry(getString(R.string.user_interface))); 78 | mData.add(new SettingsEntry(1, R.drawable.ic_theme, getString(R.string.app_theme), Settings.getAppTheme(requireActivity()))); 79 | mData.add(new SettingsEntry(getString(R.string.general))); 80 | mData.add(new SettingsEntry(2, R.drawable.ic_power, getString(R.string.shizuku_mode), Settings.getShizukuMode(requireActivity()))); 81 | mData.add(new SettingsEntry(getString(R.string.miscellaneous))); 82 | mData.add(new SettingsEntry(3, R.drawable.ic_github, getString(R.string.source_code), getString(R.string.source_code_description))); 83 | mData.add(new SettingsEntry(4, R.drawable.ic_learn, getString(R.string.shizuku_learn), getString(R.string.shizuku_learn_description))); 84 | mData.add(new SettingsEntry(5, R.drawable.ic_learn, getString(R.string.uad_learn), getString(R.string.uad_learn_description))); 85 | mData.add(new SettingsEntry(6, R.drawable.ic_translate, getString(R.string.translations), getString(R.string.translations_description))); 86 | mData.add(new SettingsEntry(7, R.drawable.ic_privacy, getString(R.string.privacy_policy), getString(R.string.privacy_policy_description))); 87 | mData.add(new SettingsEntry(8, R.drawable.ic_email, getString(R.string.developer_contact), getString(R.string.developer_contact_description))); 88 | return mData; 89 | } 90 | 91 | private void onRequestPermissionsResult(int requestCode, int grantResult) { 92 | if (requestCode == 0 && grantResult == PackageManager.PERMISSION_GRANTED) { 93 | Utils.toast("AppVaultX got access to Shizuku service", requireActivity()).show(); 94 | ShizukuShell.ensureUserService(null); 95 | requireActivity().recreate(); 96 | } else { 97 | Utils.toast(getString(R.string.shizuku_access_denied_title), requireActivity()).show(); 98 | } 99 | Shizuku.removeRequestPermissionResultListener(REQUEST_PERMISSION_RESULT_LISTENER); 100 | } 101 | 102 | @Override 103 | public void onDestroy() { 104 | super.onDestroy(); 105 | Shizuku.removeRequestPermissionResultListener(REQUEST_PERMISSION_RESULT_LISTENER); 106 | ShizukuShell.destroy(); 107 | } 108 | 109 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/serializable/DebloaterEntry.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.serializable; 2 | 3 | import org.json.JSONArray; 4 | 5 | import java.io.Serializable; 6 | 7 | /* 8 | * Created by sunilpaulmathew on October 18, 2025 9 | */ 10 | public class DebloaterEntry implements Serializable { 11 | 12 | private final JSONArray dependencies, neededBy, labels; 13 | private final String packageName, list, description, removal; 14 | 15 | public DebloaterEntry(String packageName, String list, String description, JSONArray dependencies, JSONArray neededBy, JSONArray labels, String removal) { 16 | this.packageName = packageName; 17 | this.list = list; 18 | this.description = description; 19 | this.dependencies = dependencies; 20 | this.neededBy = neededBy; 21 | this.labels = labels; 22 | this.removal = removal; 23 | } 24 | 25 | public String getPackageName() { 26 | return packageName; 27 | } 28 | 29 | public String getList() { 30 | return list; 31 | } 32 | 33 | public JSONArray getDependencies() { 34 | return dependencies; 35 | } 36 | 37 | public String getDescription() { 38 | return description; 39 | } 40 | 41 | public JSONArray neededBy() { 42 | return neededBy; 43 | } 44 | 45 | public JSONArray getLabels() { 46 | return labels; 47 | } 48 | 49 | public String getRemovalStatus() { 50 | return removal; 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/serializable/MenuEntry.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.serializable; 2 | 3 | import android.content.Context; 4 | 5 | import java.io.Serializable; 6 | 7 | /* 8 | * Created by sunilpaulmathew on October 18, 2025 9 | */ 10 | public class MenuEntry implements Serializable { 11 | 12 | private final int titleRes; 13 | private final int iconRes; 14 | private final int id; 15 | 16 | public MenuEntry(int titleRes, int iconRes, int id) { 17 | this.titleRes = titleRes; 18 | this.iconRes = iconRes; 19 | this.id = id; 20 | } 21 | 22 | public int getIcon() { 23 | return iconRes; 24 | } 25 | 26 | public int getID() { 27 | return id; 28 | } 29 | 30 | public String getTile(Context context) { 31 | return context.getString(titleRes); 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/serializable/PackagesEntry.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.serializable; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.content.pm.ApplicationInfo; 6 | import android.content.pm.PackageInfo; 7 | import android.content.pm.PackageManager; 8 | import android.graphics.drawable.Drawable; 9 | import android.os.Handler; 10 | import android.os.Looper; 11 | import android.widget.ImageView; 12 | import android.widget.TextView; 13 | 14 | import androidx.recyclerview.widget.LinearLayoutManager; 15 | import androidx.recyclerview.widget.RecyclerView; 16 | 17 | import java.io.File; 18 | import java.io.Serializable; 19 | import java.util.List; 20 | import java.util.Objects; 21 | import java.util.concurrent.CopyOnWriteArrayList; 22 | import java.util.concurrent.ExecutorService; 23 | import java.util.concurrent.Executors; 24 | 25 | import in.sunilpaulmathew.appvaultx.adapters.LabelsAdapter; 26 | 27 | /* 28 | * Created by sunilpaulmathew on October 18, 2025 29 | */ 30 | public class PackagesEntry implements Serializable { 31 | 32 | private boolean selected; 33 | private Drawable appIcon; 34 | private final boolean installed; 35 | private final int appType; 36 | private final String uadDes, removalRec, packageName, apkPath; 37 | private String appName; 38 | 39 | public PackagesEntry(String packageName, String apkPath, String removalRec, String uadDes, int appType, boolean installed) { 40 | this.packageName = packageName; 41 | this.apkPath = apkPath; 42 | this.removalRec = removalRec; 43 | this.uadDes = uadDes; 44 | this.appType = appType; 45 | this.installed = installed; 46 | this.selected = true; 47 | } 48 | 49 | public boolean isSelected() { 50 | return selected; 51 | } 52 | 53 | @Override 54 | public boolean equals(Object o) { 55 | if (this == o) return true; 56 | if (!(o instanceof PackagesEntry)) return false; 57 | PackagesEntry that = (PackagesEntry) o; 58 | return packageName.equals(that.packageName); 59 | } 60 | 61 | public boolean isInstalled() { 62 | return installed; 63 | } 64 | 65 | public boolean isSystemApp() { 66 | return appType == 1 || appType == 2 || appType == 4 || appType == 5; 67 | } 68 | 69 | public Drawable getAppIcon() { 70 | return appIcon; 71 | } 72 | 73 | @Override 74 | public int hashCode() { 75 | return packageName.hashCode(); 76 | } 77 | 78 | public int getAppType() { 79 | return appType; 80 | } 81 | 82 | public Intent launchIntent(Context context) { 83 | return context.getPackageManager().getLaunchIntentForPackage(packageName); 84 | } 85 | 86 | public String getAPKPath() { 87 | return apkPath; 88 | } 89 | 90 | public File getParentFile() { 91 | return new File(apkPath).getParentFile(); 92 | } 93 | 94 | public String getAppName() { 95 | return appName; 96 | } 97 | 98 | public String getPackageName() { 99 | return packageName; 100 | } 101 | 102 | public String getRemovalRecommendation() { 103 | return removalRec; 104 | } 105 | 106 | public String getUADDescription() { 107 | return uadDes; 108 | } 109 | 110 | public void setSelected(boolean selected) { 111 | this.selected = selected; 112 | } 113 | 114 | public void loadPackageInfo(RecyclerView priority, ImageView icon, TextView name, TextView summary) { 115 | try (ExecutorService executor = Executors.newSingleThreadExecutor()) { 116 | Handler handler = new Handler(Looper.getMainLooper()); 117 | List labels = new CopyOnWriteArrayList<>(); 118 | executor.execute(() -> { 119 | 120 | if (removalRec != null) labels.add(removalRec); 121 | 122 | switch (appType) { 123 | case 6: 124 | labels.add("Debuggable"); 125 | break; 126 | case 5: 127 | labels.add("System"); 128 | labels.add("Disabled"); 129 | break; 130 | case 4: 131 | labels.add("Updated system"); 132 | labels.add("Disabled"); 133 | break; 134 | case 3: 135 | labels.add("User"); 136 | labels.add("Disabled"); 137 | break; 138 | case 2: 139 | labels.add("System"); 140 | break; 141 | case 1: 142 | labels.add("Updated system"); 143 | break; 144 | default: 145 | labels.add("User"); 146 | break; 147 | } 148 | 149 | PackageManager pm = icon.getContext().getPackageManager(); 150 | ApplicationInfo ai = null; 151 | 152 | try { 153 | if (installed) { 154 | ai = pm.getApplicationInfo(packageName, 0); 155 | } else { 156 | PackageInfo pi = pm.getPackageArchiveInfo(apkPath, 0); 157 | if (pi != null) { 158 | ai = pi.applicationInfo; 159 | Objects.requireNonNull(ai).sourceDir = apkPath; 160 | ai.publicSourceDir = apkPath; 161 | } 162 | } 163 | 164 | if (ai != null) { 165 | appName = pm.getApplicationLabel(ai).toString(); 166 | appIcon = pm.getApplicationIcon(ai); 167 | } 168 | } catch (PackageManager.NameNotFoundException ignored) { 169 | } 170 | 171 | handler.post(() -> { 172 | priority.setItemAnimator(null); 173 | priority.setAdapter(new LabelsAdapter(labels, appIcon, appName, packageName, uadDes)); 174 | priority.setLayoutManager(new LinearLayoutManager(priority.getContext(), LinearLayoutManager.HORIZONTAL, false)); 175 | name.setText(appName); 176 | summary.setText(packageName); 177 | icon.setImageDrawable(appIcon); 178 | }); 179 | }); 180 | } 181 | } 182 | 183 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/serializable/PolicyEntry.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.serializable; 2 | 3 | import java.io.Serializable; 4 | 5 | /* 6 | * Created by sunilpaulmathew on October 18, 2025 7 | */ 8 | public class PolicyEntry implements Serializable { 9 | 10 | private final String mTitle, mSummary; 11 | 12 | public PolicyEntry(String title, String summary) { 13 | this.mTitle = title; 14 | this.mSummary = summary; 15 | } 16 | 17 | public String getTitle() { 18 | return mTitle; 19 | } 20 | 21 | public String getSummary() { 22 | return mSummary; 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/serializable/SettingsEntry.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.serializable; 2 | 3 | import java.io.Serializable; 4 | 5 | /* 6 | * Created by sunilpaulmathew on October 18, 2025 7 | */ 8 | public class SettingsEntry implements Serializable { 9 | 10 | private final boolean mEnabled, mSwitch; 11 | private final int mIcon, mPosition; 12 | private final String mTitle; 13 | private String mDescription; 14 | 15 | public SettingsEntry(String title) { 16 | this.mPosition = 0; 17 | this.mIcon = Integer.MIN_VALUE; 18 | this.mTitle = title; 19 | this.mDescription = null; 20 | this.mSwitch = false; 21 | this.mEnabled = false; 22 | } 23 | 24 | public SettingsEntry(int position, int icon, String title, String description) { 25 | this.mPosition = position; 26 | this.mIcon = icon; 27 | this.mTitle = title; 28 | this.mDescription = description; 29 | this.mSwitch = false; 30 | this.mEnabled = false; 31 | } 32 | 33 | public boolean isEnabled() { 34 | return mEnabled; 35 | } 36 | 37 | public boolean isSwitch() { 38 | return mSwitch; 39 | } 40 | 41 | public int getIcon() { 42 | return mIcon; 43 | } 44 | 45 | public int getPosition() { 46 | return mPosition; 47 | } 48 | 49 | public String geTitle() { 50 | return mTitle; 51 | } 52 | 53 | public String getDescription() { 54 | return mDescription; 55 | } 56 | 57 | public void setDescription(String description) { 58 | this.mDescription = description; 59 | } 60 | 61 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/services/ShellService.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.services; 2 | 3 | import android.os.ParcelFileDescriptor; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.FileInputStream; 7 | import java.io.FileOutputStream; 8 | import java.io.IOException; 9 | import java.io.InputStreamReader; 10 | 11 | import sunilpaulmathew.appvaultx.IShellService; 12 | 13 | /* 14 | * Created by sunilpaulmathew on October 18, 2025 15 | */ 16 | public class ShellService extends IShellService.Stub { 17 | 18 | private static Process mProcess = null; 19 | 20 | @Override 21 | public void destroyProcess() { 22 | if (mProcess != null) mProcess.destroy(); 23 | } 24 | 25 | @Override 26 | public String runCommand(String command) { 27 | StringBuilder output = new StringBuilder(); 28 | try { 29 | mProcess = Runtime.getRuntime().exec(command, null, null); 30 | BufferedReader mInput = new BufferedReader(new InputStreamReader(mProcess.getInputStream())); 31 | BufferedReader mError = new BufferedReader(new InputStreamReader(mProcess.getErrorStream())); 32 | 33 | mProcess.waitFor(); 34 | 35 | String line; 36 | while ((line = mInput.readLine()) != null) { 37 | output.append(line).append("\n"); 38 | } 39 | while ((line = mError.readLine()) != null) { 40 | output.append(line).append("\n"); 41 | } 42 | 43 | } 44 | catch (Exception ignored) { 45 | } 46 | finally { 47 | if (mProcess != null) 48 | mProcess.destroy(); 49 | } 50 | return output.toString(); 51 | } 52 | 53 | @Override 54 | public void runCommands(String commands) { 55 | new Thread(() -> { 56 | try { 57 | mProcess = Runtime.getRuntime().exec( 58 | new String[] { 59 | "sh", "-c", commands 60 | } 61 | ); 62 | 63 | mProcess.waitFor(); 64 | } 65 | catch (Exception ignored) { 66 | } 67 | finally { 68 | if (mProcess != null) 69 | mProcess.destroy(); 70 | } 71 | }).start(); 72 | } 73 | 74 | @Override 75 | public void writeToFile(ParcelFileDescriptor pfd, String destinationPath) { 76 | try (FileInputStream in = new FileInputStream(pfd.getFileDescriptor()); 77 | FileOutputStream out = new FileOutputStream(destinationPath)) { 78 | 79 | byte[] buffer = new byte[8192]; 80 | int len; 81 | while ((len = in.read(buffer)) != -1) { 82 | out.write(buffer, 0, len); 83 | } 84 | } catch (IOException ignored) { 85 | } finally { 86 | if (pfd != null) { 87 | try { 88 | pfd.close(); 89 | } catch (IOException ignored) {} 90 | } 91 | } 92 | } 93 | 94 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/utils/Async.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.utils; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | 9 | /* 10 | * Created by sunilpaulmathew on October 18, 2025 11 | */ 12 | public abstract class Async { 13 | 14 | private final ExecutorService executors; 15 | 16 | public Async() { 17 | this.executors = Executors.newSingleThreadExecutor(); 18 | } 19 | 20 | private void startBackground() { 21 | onPreExecute(); 22 | executors.execute(() -> { 23 | doInBackground(); 24 | new Handler(Looper.getMainLooper()).post(() -> { 25 | onPostExecute(); 26 | if (!executors.isShutdown()) executors.shutdown(); 27 | }); 28 | }); 29 | } 30 | 31 | public void execute() { 32 | startBackground(); 33 | } 34 | 35 | public abstract void onPreExecute(); 36 | 37 | public abstract void doInBackground(); 38 | 39 | public abstract void onPostExecute(); 40 | 41 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/utils/Packages.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.utils; 2 | 3 | import android.content.Context; 4 | import android.content.pm.ApplicationInfo; 5 | import android.content.pm.PackageManager; 6 | 7 | import androidx.core.widget.ContentLoadingProgressBar; 8 | 9 | import org.json.JSONArray; 10 | import org.json.JSONObject; 11 | 12 | import java.util.Iterator; 13 | import java.util.List; 14 | import java.util.concurrent.CopyOnWriteArrayList; 15 | 16 | import in.sunilpaulmathew.appvaultx.serializable.DebloaterEntry; 17 | import in.sunilpaulmathew.appvaultx.serializable.PackagesEntry; 18 | 19 | /* 20 | * Created by sunilpaulmathew on Oct. 03, 2025 21 | */ 22 | public class Packages { 23 | 24 | private static List mInstalledPackageItems, mUninstalledPackageItems; 25 | 26 | public static boolean isAppInstalled(String packageName, Context context) { 27 | PackageManager pm = context.getPackageManager(); 28 | try { 29 | pm.getPackageInfo(packageName, 0); 30 | return true; 31 | } catch (PackageManager.NameNotFoundException e) { 32 | return false; 33 | } 34 | } 35 | 36 | private static int getAppType(ApplicationInfo applicationInfo) { 37 | boolean systemApp = (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 38 | boolean updatedSystemApp = (applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0; 39 | boolean debuggable = (applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; 40 | boolean disabled = !applicationInfo.enabled; 41 | int appType; 42 | if (debuggable) { 43 | appType = 6; 44 | } else if (disabled) { 45 | if (systemApp) { 46 | appType = 5; 47 | } else if (updatedSystemApp) { 48 | appType = 4; 49 | } else { 50 | appType = 3; 51 | } 52 | } else { 53 | if (systemApp) { 54 | appType = 2; 55 | } else if (updatedSystemApp) { 56 | appType = 1; 57 | } else { 58 | appType = 0; 59 | } 60 | } 61 | return appType; 62 | } 63 | 64 | public static List getPackages() { 65 | return mInstalledPackageItems; 66 | } 67 | 68 | public static List getUninstalledPackages() { 69 | return mUninstalledPackageItems; 70 | } 71 | 72 | public static void loadPackages(ContentLoadingProgressBar progressBar, Context context) { 73 | List debloaterEntries = getUADList(context); 74 | mInstalledPackageItems = new CopyOnWriteArrayList<>(); 75 | mUninstalledPackageItems = new CopyOnWriteArrayList<>(); 76 | 77 | List packages = context.getPackageManager().getInstalledApplications(PackageManager.MATCH_UNINSTALLED_PACKAGES); 78 | 79 | int totalSIze = packages.size(); 80 | if (progressBar != null) { 81 | progressBar.setIndeterminate(false); 82 | progressBar.setMax(totalSIze); 83 | } 84 | 85 | for (ApplicationInfo packageInfo : packages) { 86 | boolean installed = (packageInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0; 87 | boolean removed = (packageInfo.flags & ApplicationInfo.FLAG_INSTALLED) == 0; 88 | int appType = getAppType(packageInfo); 89 | if (installed) { 90 | mInstalledPackageItems.add(new PackagesEntry(packageInfo.packageName, packageInfo.sourceDir, debloaterEntries.stream() 91 | .filter(entry -> entry.getPackageName().equals(packageInfo.packageName)) 92 | .map(DebloaterEntry::getRemovalStatus) 93 | .findFirst() 94 | .orElse(null), debloaterEntries.stream() 95 | .filter(entry -> entry.getPackageName().equals(packageInfo.packageName)) 96 | .map(DebloaterEntry::getDescription) 97 | .findFirst() 98 | .orElse(null), appType, true) 99 | ); 100 | } else if (removed) { 101 | mUninstalledPackageItems.add(new PackagesEntry(packageInfo.packageName, packageInfo.sourceDir, debloaterEntries.stream() 102 | .filter(entry -> entry.getPackageName().equals(packageInfo.packageName)) 103 | .map(DebloaterEntry::getRemovalStatus) 104 | .findFirst() 105 | .orElse(null), debloaterEntries.stream() 106 | .filter(entry -> entry.getPackageName().equals(packageInfo.packageName)) 107 | .map(DebloaterEntry::getDescription) 108 | .findFirst() 109 | .orElse(null), appType, false) 110 | ); 111 | } 112 | if (progressBar != null) { 113 | if (progressBar.getProgress() < packages.size()) { 114 | progressBar.setProgress(progressBar.getProgress() + 1); 115 | } else { 116 | progressBar.setProgress(0); 117 | } 118 | } 119 | } 120 | } 121 | 122 | private static List getUADList(Context context) { 123 | List debloaterEntries = new CopyOnWriteArrayList<>(); 124 | try { 125 | JSONObject root = new JSONObject(Utils.readAssetFile("uad_lists.json", context)); 126 | 127 | Iterator keys = root.keys(); 128 | while (keys.hasNext()) { 129 | String packageName = keys.next(); 130 | JSONObject packageInfo = root.getJSONObject(packageName); 131 | 132 | String list = packageInfo.getString("list"); 133 | String description = packageInfo.getString("description"); 134 | JSONArray dependencies = packageInfo.getJSONArray("dependencies"); 135 | JSONArray neededBy = packageInfo.getJSONArray("neededBy"); 136 | JSONArray labels = packageInfo.getJSONArray("labels"); 137 | String removal = packageInfo.getString("removal"); 138 | 139 | debloaterEntries.add(new DebloaterEntry(packageName, list, description, dependencies, neededBy, labels, removal)); 140 | } 141 | 142 | } catch (Exception ignored) { 143 | } 144 | return debloaterEntries; 145 | } 146 | 147 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/utils/Settings.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.utils; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.pm.PackageManager; 6 | import android.content.res.Configuration; 7 | import android.content.res.TypedArray; 8 | import android.view.View; 9 | import android.view.animation.DecelerateInterpolator; 10 | 11 | import androidx.appcompat.app.AppCompatDelegate; 12 | 13 | import com.google.android.material.bottomnavigation.BottomNavigationView; 14 | import com.google.android.material.color.DynamicColors; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | 19 | import in.sunilpaulmathew.appvaultx.R; 20 | import in.sunilpaulmathew.appvaultx.serializable.PolicyEntry; 21 | import rikka.shizuku.Shizuku; 22 | 23 | /* 24 | * Created by sunilpaulmathew on October 18, 2025 25 | */ 26 | public class Settings { 27 | 28 | public static boolean isDarkTheme(Context context) { 29 | int currentNightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; 30 | return currentNightMode == Configuration.UI_MODE_NIGHT_YES; 31 | } 32 | 33 | public static boolean isShizukuIgnored(Context context) { 34 | return Utils.getInt("shizuku_mode", 0, context) == 1; 35 | } 36 | 37 | public static int getColorAccent(Context context) { 38 | return getMaterial3Colors(Utils.getColor(R.color.colorBlue, context), context); 39 | } 40 | 41 | public static int getColorText(Context context) { 42 | return Utils.getColor(isDarkTheme(context) ? R.color.colorWhite : R.color.colorBlack, context); 43 | } 44 | 45 | private static int getMaterial3Colors(int defaultColor, Context context) { 46 | int color = defaultColor; 47 | if (DynamicColors.isDynamicColorAvailable()) { 48 | Context dynamicClrCtx = DynamicColors.wrapContextIfAvailable(context, com.google.android.material.R.style.MaterialAlertDialog_Material3); 49 | TypedArray ta = dynamicClrCtx.obtainStyledAttributes(new int[] { 50 | androidx.appcompat.R.attr.colorPrimary 51 | }); 52 | color = ta.getColor(0, defaultColor); 53 | ta.recycle(); 54 | } 55 | return color; 56 | } 57 | 58 | public static int getAppThemePosition(Context context) { 59 | return Utils.getInt("appTheme", 0, context); 60 | } 61 | 62 | public static int getShizukuModePosition(Context context) { 63 | if (isShizukuIgnored(context)) { 64 | return 1; 65 | } 66 | if (Shizuku.pingBinder() && Shizuku.getVersion() >= 11 && Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) { 67 | return 0; 68 | } else { 69 | return 1; 70 | } 71 | } 72 | 73 | public static List getPolicyData() { 74 | List mData = new ArrayList<>(); 75 | mData.add(new PolicyEntry("Introduction", "AppVaultX is developed by one main developer, sunilpaulmathew, leveraging code from various open-source projects. This Privacy Policy outlines how we handle user privacy.")); 76 | mData.add(new PolicyEntry("Scope", "This policy applies exclusively to the original version of AppVaultX published by the developer on IzzyOnDroid and GitHub.")); 77 | mData.add(new PolicyEntry("Personal Information", "We do not collect, store, or share any personal information about our users. User identities remain anonymous. If we inadvertently receive any personal information, we will not disclose or share it with third parties.")); 78 | mData.add(new PolicyEntry("Permissions", "AppVaultX requires the following permissions to deliver its features:" + 79 | "\n\uD83D\uDD10 moe.shizuku.manager.permission.API_V23: Permission required to use Shizuku’s privileged APIs." + 80 | "\n\uD83D\uDCF1 QUERY_ALL_PACKAGES: Allows AppVaultX to view the list of all installed apps and perform app-related management actions." + 81 | "\n\uD83D\uDCC2 WRITE_EXTERNAL_STORAGE: Allows AppVaultX to save APKs and app icons to device storage (applicable only on devices running Android versions below SDK 29 / Android 10).")); 82 | mData.add(new PolicyEntry("Contact Us", "If you have questions or concerns about this Privacy Policy, please contact us at: smartpack.org@gmail.com")); 83 | mData.add(new PolicyEntry("Changes to This Policy", "We may update this policy from time to time. Changes will be posted here.")); 84 | return mData; 85 | } 86 | 87 | public static String getAppTheme(Context context) { 88 | int appTheme = Utils.getInt("appTheme", 0, context); 89 | switch (appTheme) { 90 | case 2: 91 | return context.getString(R.string.app_theme_light); 92 | case 1: 93 | return context.getString(R.string.app_theme_dark); 94 | default: 95 | return context.getString(R.string.app_theme_auto); 96 | } 97 | } 98 | 99 | public static String getShizukuMode(Context context) { 100 | if (isShizukuIgnored(context)) { 101 | return context.getString(R.string.shizuku_mode_ignored); 102 | } else if (Shizuku.pingBinder() && Shizuku.getVersion() >= 11) { 103 | if (Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) { 104 | return context.getString(R.string.shizuku_mode_enabled); 105 | } else { 106 | return context.getString(R.string.shizuku_mode_disabled); 107 | } 108 | } else { 109 | return context.getString(R.string.shizuku_mode_unavailable); 110 | } 111 | } 112 | 113 | public static String[] getAppThemeMenu(Context context) { 114 | return new String[] { 115 | context.getString(R.string.app_theme_auto), 116 | context.getString(R.string.app_theme_dark), 117 | context.getString(R.string.app_theme_light) 118 | }; 119 | } 120 | 121 | public static String[] getShizkuModeMenu(Context context) { 122 | return new String[] { 123 | context.getString(R.string.shizuku_mode_enabled), 124 | context.getString(R.string.shizuku_mode_ignored) 125 | }; 126 | } 127 | 128 | public static void initializeAppTheme(Context context) { 129 | int appTheme = Utils.getInt("appTheme", 0, context); 130 | switch (appTheme) { 131 | case 1: 132 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); 133 | break; 134 | case 2: 135 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); 136 | break; 137 | default: 138 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); 139 | break; 140 | } 141 | context.setTheme(R.style.AppTheme); 142 | } 143 | 144 | public static void navigateToFragment(int position, Activity activity) { 145 | BottomNavigationView bottomNavigationView = activity.findViewById(R.id.bottom_navigation); 146 | bottomNavigationView.setSelectedItemId(position); 147 | } 148 | 149 | public static void setSlideInAnimation(final View viewToAnimate, int position) { 150 | // Only animate items appearing for the first time 151 | if (position > -1) { 152 | viewToAnimate.setTranslationY(50f); 153 | viewToAnimate.setAlpha(0f); 154 | 155 | viewToAnimate.animate() 156 | .translationY(0f) 157 | .alpha(1f) 158 | .setDuration(150) 159 | .setInterpolator(new DecelerateInterpolator()) 160 | .start(); 161 | } else { 162 | // Reset properties to ensure recycled views are displayed correctly 163 | viewToAnimate.setTranslationY(0f); 164 | viewToAnimate.setAlpha(1f); 165 | } 166 | } 167 | 168 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/utils/ShizukuPermissionChecker.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.utils; 2 | 3 | import android.content.Context; 4 | import android.content.pm.PackageManager; 5 | 6 | import com.google.android.material.dialog.MaterialAlertDialogBuilder; 7 | 8 | import in.sunilpaulmathew.appvaultx.R; 9 | import in.sunilpaulmathew.appvaultx.dialogs.AccessDeniedDialog; 10 | import rikka.shizuku.Shizuku; 11 | 12 | /* 13 | * Created by sunilpaulmathew on October 18, 2025 14 | */ 15 | public abstract class ShizukuPermissionChecker { 16 | 17 | public ShizukuPermissionChecker(Context context) { 18 | if (Shizuku.isPreV11()) { 19 | Utils.toast("Pre-v11 is unsupported", context).show(); 20 | return; 21 | } 22 | 23 | if (Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) { 24 | ShizukuShell.ensureUserService(this::onFinished); 25 | } else if (Shizuku.shouldShowRequestPermissionRationale()) { 26 | new AccessDeniedDialog(context).show(); 27 | } else { 28 | new MaterialAlertDialogBuilder(context) 29 | .setIcon(R.mipmap.ic_launcher) 30 | .setTitle("Enable Shizuku Access") 31 | .setMessage(R.string.shizuku_access_requirement_description) 32 | .setNeutralButton(R.string.ignore, (dialogInterface, i) -> Utils.saveInt("shizuku_mode", 1, context)) 33 | .setPositiveButton(R.string.request_permission, (dialogInterface, i) -> onRequestingPermission()).show(); 34 | } 35 | } 36 | 37 | public abstract void onRequestingPermission(); 38 | 39 | public abstract void onFinished(); 40 | 41 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/utils/ShizukuShell.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.utils; 2 | 3 | import android.content.ComponentName; 4 | import android.content.ServiceConnection; 5 | import android.os.Handler; 6 | import android.os.IBinder; 7 | import android.os.Looper; 8 | import android.os.ParcelFileDescriptor; 9 | import android.os.RemoteException; 10 | 11 | import in.sunilpaulmathew.appvaultx.BuildConfig; 12 | import in.sunilpaulmathew.appvaultx.services.ShellService; 13 | import rikka.shizuku.Shizuku; 14 | import sunilpaulmathew.appvaultx.IShellService; 15 | 16 | /* 17 | * Created by sunilpaulmathew on October 18, 2025 18 | */ 19 | public class ShizukuShell { 20 | private static IShellService mShellService; 21 | 22 | public static void ensureUserService(Runnable runnable) { 23 | if (mShellService != null && runnable != null) { 24 | runnable.run(); 25 | return; 26 | } 27 | 28 | Shizuku.UserServiceArgs args = new Shizuku.UserServiceArgs( 29 | new ComponentName(BuildConfig.APPLICATION_ID, ShellService.class.getName())) 30 | .daemon(false) 31 | .processNameSuffix("shizuku_shell") 32 | .debuggable(BuildConfig.DEBUG) 33 | .version(BuildConfig.VERSION_CODE); 34 | 35 | Shizuku.bindUserService(args, new ServiceConnection() { 36 | @Override 37 | public void onServiceConnected(ComponentName name, IBinder binder) { 38 | if (binder == null || !binder.pingBinder()) return; 39 | 40 | mShellService = IShellService.Stub.asInterface(binder); 41 | 42 | if (runnable != null) { 43 | new Handler(Looper.getMainLooper()).post(runnable); 44 | } 45 | } 46 | 47 | @Override 48 | public void onServiceDisconnected(ComponentName name) { 49 | mShellService = null; 50 | } 51 | }); 52 | } 53 | 54 | public static String runCommand(String command) { 55 | if (mShellService != null) { 56 | try { 57 | return mShellService.runCommand(command); 58 | } catch (RemoteException ignored) { 59 | } 60 | } 61 | return ""; 62 | } 63 | 64 | public static void runCommands(String commands) { 65 | if (mShellService != null) { 66 | try { 67 | mShellService.runCommands(commands); 68 | } catch (RemoteException ignored) { 69 | } 70 | } 71 | } 72 | 73 | public static void writeToFile(ParcelFileDescriptor data, String path) { 74 | if (mShellService != null) { 75 | try { 76 | mShellService.writeToFile(data, path); 77 | } catch (RemoteException ignored) { 78 | } 79 | } 80 | } 81 | 82 | public static void destroy() { 83 | try { 84 | if (mShellService != null) mShellService.destroyProcess(); 85 | } catch (RemoteException ignored) { 86 | } 87 | } 88 | 89 | } -------------------------------------------------------------------------------- /app/src/main/java/in/sunilpaulmathew/appvaultx/utils/Utils.java: -------------------------------------------------------------------------------- 1 | package in.sunilpaulmathew.appvaultx.utils; 2 | 3 | import android.content.ActivityNotFoundException; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.graphics.drawable.Drawable; 7 | import android.net.Uri; 8 | import android.os.Build; 9 | import android.os.Environment; 10 | import android.widget.Toast; 11 | 12 | import androidx.core.content.ContextCompat; 13 | import androidx.preference.PreferenceManager; 14 | 15 | import java.io.BufferedInputStream; 16 | import java.io.ByteArrayOutputStream; 17 | import java.io.File; 18 | import java.io.FileInputStream; 19 | import java.io.FileOutputStream; 20 | import java.io.FileWriter; 21 | import java.io.IOException; 22 | import java.io.InputStream; 23 | import java.util.Objects; 24 | 25 | import in.sunilpaulmathew.appvaultx.R; 26 | 27 | /* 28 | * Created by sunilpaulmathew on October 18, 2025 29 | */ 30 | public class Utils { 31 | 32 | public static boolean delete(File file) { 33 | if (file.isDirectory()) { 34 | for (File files : Objects.requireNonNull(file.listFiles())) 35 | delete(files); 36 | } 37 | return file.delete(); 38 | } 39 | 40 | public static boolean getBoolean(String name, boolean defaults, Context context) { 41 | return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(name, defaults); 42 | } 43 | 44 | public static boolean isGooglePlayVersion(Context context) { 45 | String installer = getInstaller(context.getPackageName(), context); 46 | return installer != null && installer.matches("com\\.android\\.vending|com\\.google\\.android\\.feedback"); 47 | } 48 | 49 | public static boolean mkdir(File folder) { 50 | return folder.mkdirs(); 51 | } 52 | 53 | public static Drawable getDrawable(int drawable, Context context) { 54 | return ContextCompat.getDrawable(context, drawable); 55 | } 56 | 57 | public static File getExportPath(Context context) { 58 | File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), 59 | context.getString(R.string.app_name)); 60 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { 61 | if (file.exists() && file.isFile()) { 62 | delete(file); 63 | } 64 | mkdir(file); 65 | } else { 66 | if (!file.exists()) { 67 | mkdir(file); 68 | } 69 | } 70 | return file; 71 | } 72 | 73 | public static int getColor(int color, Context context) { 74 | return ContextCompat.getColor(context, color); 75 | } 76 | 77 | public static int getInt(String name, int defaults, Context context) { 78 | return PreferenceManager.getDefaultSharedPreferences(context).getInt(name, defaults); 79 | } 80 | 81 | public static int getUserID() { 82 | int uid = android.os.Process.myUid(); 83 | return uid / 100000; 84 | } 85 | 86 | private static String getInstaller(String packageName, Context context) { 87 | try { 88 | return context.getPackageManager().getInstallerPackageName(packageName); 89 | } catch (Exception ignored) {} 90 | return null; 91 | } 92 | 93 | public static String readAssetFile(String assetName, Context context) throws IOException { 94 | return read(context.getAssets().open(assetName)); 95 | } 96 | 97 | private static String read(InputStream inputStream) throws IOException { 98 | BufferedInputStream bis = new BufferedInputStream(inputStream); 99 | ByteArrayOutputStream buf = new ByteArrayOutputStream(); 100 | for (int result = bis.read(); result != -1; result = bis.read()) { 101 | buf.write((byte) result); 102 | } 103 | return buf.toString("UTF-8"); 104 | } 105 | 106 | public static Toast toast(String message, Context context) { 107 | return Toast.makeText(context, message, Toast.LENGTH_LONG); 108 | } 109 | 110 | public static void copy(InputStream inputStream, File dest) { 111 | try { 112 | copyStream(Objects.requireNonNull(inputStream), dest); 113 | } catch (IOException ignored) {} 114 | } 115 | 116 | public static void copy(File source, File dest) { 117 | try (FileInputStream fis = new FileInputStream(source)) { 118 | copyStream(fis, dest); 119 | } catch (IOException ignored) {} 120 | } 121 | 122 | public static void copy(Uri uri, File dest, Context context) { 123 | try { 124 | copyStream(Objects.requireNonNull(context.getContentResolver().openInputStream(uri)), dest); 125 | } catch (IOException ignored) {} 126 | } 127 | 128 | private static void copyStream(InputStream from, File dest) throws IOException { 129 | try (FileOutputStream to = new FileOutputStream(dest)) { 130 | byte[] buf = new byte[1024 * 1024]; 131 | int len; 132 | while ((len = from.read(buf)) > 0) { 133 | to.write(buf, 0, len); 134 | } 135 | } 136 | } 137 | 138 | public static void create(String text, File path) { 139 | try { 140 | FileWriter writer = new FileWriter(path); 141 | writer.write(text); 142 | writer.close(); 143 | } catch (IOException ignored) { 144 | } 145 | } 146 | 147 | public static void loadUrl(String url, Context context) { 148 | try { 149 | Intent intent = new Intent(Intent.ACTION_VIEW); 150 | intent.setData(Uri.parse(url)); 151 | context.startActivity(intent); 152 | } catch (ActivityNotFoundException ignored) {} 153 | } 154 | 155 | public static void saveBoolean(String name, boolean value, Context context) { 156 | PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(name, value).apply(); 157 | } 158 | 159 | public static void saveInt(String name, int value, Context context) { 160 | PreferenceManager.getDefaultSharedPreferences(context).edit().putInt(name, value).apply(); 161 | } 162 | 163 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/app_icon_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_apps.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_cancel.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_check.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_delete.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_download.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_email.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_github.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_learn.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_open.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_power.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_privacy.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_reset.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_save.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_search.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_select.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_sort.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_sort_az.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_theme.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_translate.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_user.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_warning.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | 17 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_packages.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 20 | 21 | 27 | 28 | 37 | 38 | 39 | 50 | 51 | 58 | 59 | 67 | 68 | 75 | 76 | 77 | 88 | 89 | 93 | 94 | 105 | 106 | 114 | 115 | 116 | 117 | 126 | 127 | 137 | 138 | 144 | 145 | 146 | 162 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_settings.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_about.xml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 21 | 22 | 26 | 27 | 35 | 36 | 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_app_data.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 18 | 19 | 23 | 24 | 32 | 33 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_batch.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | 16 | 27 | 28 | 36 | 37 | 46 | 47 | 54 | 55 | 59 | 60 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_bottom_menu.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_installer.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 15 | 16 | 20 | 21 | 28 | 29 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_privacy_policy.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_progress.xml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | 19 | 29 | 30 | 39 | 40 | 41 | 50 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_welcome.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 17 | 18 | 25 | 26 | 27 | 35 | 36 | 42 | 43 | 50 | 51 | 55 | 56 | 63 | 64 | -------------------------------------------------------------------------------- /app/src/main/res/layout/recycle_view_batch.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | 17 | 27 | 28 | 35 | 36 | 41 | 42 | 48 | 49 | 50 | 57 | -------------------------------------------------------------------------------- /app/src/main/res/layout/recycle_view_bottom_menu.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 16 | 17 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/recycle_view_labels.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/src/main/res/layout/recycle_view_packages.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 25 | 26 | 32 | 33 | 40 | 41 | 42 | 50 | 51 | 60 | 61 | 69 | 70 | 78 | 79 | -------------------------------------------------------------------------------- /app/src/main/res/layout/recycle_view_policy.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 20 | 21 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/recycle_view_settings.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 15 | 16 | 23 | 24 | 32 | 33 | 40 | 41 | 48 | 49 | 50 | 51 | 56 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_background.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/app/src/main/res/mipmap-hdpi/ic_launcher_background.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_background.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/app/src/main/res/mipmap-mdpi/ic_launcher_background.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_background.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/app/src/main/res/mipmap-xhdpi/ic_launcher_background.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_background.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/values-ar/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | "إلغاء" 4 | "اضغط زر الرجوع مرة أخرى للخروج" 5 | "طلب الاذن" 6 | "ابدأ" 7 | "نعم" 8 | "حقوق الطبع والنشر: © 2025، sunilpaulmathew" 9 | "مظهر التطبيق" 10 | "تلقائي" 11 | "داكن" 12 | "فاتح" 13 | "aShell %s" 14 | "الاتصال بالمطور" 15 | "هل تحتاج إلى مساعدة أو لديك ملاحظات؟ اتصل بالمطور" 16 | "عام" 17 | "سياسة الخصوصية" 18 | "خصوصيتك مهمة: اعرف المزيد" 19 | "الإعدادات" 20 | "رُفض الوصول إلى Shizuku لـ aShell" 21 | "تعلم Shizuku" 22 | "اعرف المزيد عن Shizuku على: shizuku.rikka.app" 23 | "لم يتم العثور على دعم Shizuku" 24 | "الترجمات" 25 | "ساهم في ترجمة التطبيق" 26 | "واجهة المستخدم" 27 | -------------------------------------------------------------------------------- /app/src/main/res/values-de-rBE/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | "Stornieren" 4 | "Drücken Sie erneut „Zurück“, um den Vorgang zu beenden" 5 | "Erlaubnis anfordern" 6 | "Start" 7 | "Ja" 8 | "Urheberrecht: © 2025, sunilpaulmathew" 9 | "App-Design" 10 | "Auto" 11 | "Dunkel" 12 | "Licht" 13 | "eine Shell %s" 14 | "Entwickler kontaktieren" 15 | "Benötigen Sie Hilfe oder haben Sie Feedback? Kontaktieren Sie den Entwickler" 16 | "Allgemein" 17 | "Datenschutzrichtlinie" 18 | "Ihre Privatsphäre ist wichtig: Erfahren Sie mehr" 19 | "Einstellungen" 20 | "Shizuku-Zugriff für aShell verweigert" 21 | "Shizuku lernen" 22 | "Erfahren Sie mehr über Shizuku unter: shizuku.rikka.app" 23 | "Shizuku-Support nicht gefunden" 24 | "Übersetzungen" 25 | "Tragen Sie zur Übersetzung der App bei" 26 | "Benutzeroberfläche" 27 | -------------------------------------------------------------------------------- /app/src/main/res/values-de/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | "Abbruch" 4 | "Drücken Sie erneut auf zurück, um die App zu schließen" 5 | "Berechtigung abfragen" 6 | "Start" 7 | "Ja" 8 | "Urheberrecht: © 2025, sunilpaulmathew" 9 | "App-Design" 10 | "Auto" 11 | "Dunkel" 12 | "Licht" 13 | "eine Shell %s" 14 | "Entwickler kontaktieren" 15 | "Brauchen Sie Hilfe oder haben Sie Feedback? Kontaktieren Sie den Entwickler" 16 | "Allgemein" 17 | "Datenschutzrichtlinie" 18 | "Ihre Privatsphäre ist wichtig: Erfahren Sie mehr" 19 | "Einstellungen" 20 | "Shizuku-Zugriff für aShell verweigert" 21 | "Shizuku lernen" 22 | "Erfahren Sie mehr über Shizuku unter: shizuku.rikka.app" 23 | "Shizuku-Support nicht gefunden" 24 | "Übersetzungen" 25 | "Tragen Sie zur Übersetzung der App bei" 26 | "Benutzeroberfläche" 27 | -------------------------------------------------------------------------------- /app/src/main/res/values-el/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ακύρωση 4 | Copyright: © 2025, sunilpaulmathew 5 | Πατήστε ξανά πίσω για έξοδο 6 | Αίτημα Άδειας 7 | Έναρξη 8 | Ναι 9 | -------------------------------------------------------------------------------- /app/src/main/res/values-es-rMX/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | "Cancelar" 4 | "Presione atrás nuevamente para salir" 5 | "Solicitar permiso" 6 | "Comenzar" 7 | "Sí" 8 | "Derechos de autor: © 2025, sunilpaulmathew" 9 | "Tema de la aplicación" 10 | "Auto" 11 | "Oscuro" 12 | "Luz" 13 | "un Shell %s" 14 | "Contactar al desarrollador" 15 | "¿Necesitas ayuda o tienes algún comentario? Contacta con el desarrollador." 16 | "General" 17 | "Política de privacidad" 18 | "Tu privacidad es importante: Más información" 19 | "Ajustes" 20 | "Acceso denegado a Shizuku para aShell" 21 | "Aprende shizuku" 22 | "Obtenga más información sobre shizuku en: shizuku.rikka.app" 23 | "No se encontró soporte para Shizuku" 24 | "Traducciones" 25 | "Contribuir a la traducción de la aplicación" 26 | "Interfaz de usuario" 27 | -------------------------------------------------------------------------------- /app/src/main/res/values-es/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | "Cancelar" 4 | "Presione atrás de nuevo para salir" 5 | "Solicitar permiso" 6 | "Comenzar" 7 | "Sí" 8 | "Derechos de autor: © 2025, sunilpaulmathew" 9 | "Tema de la aplicación" 10 | "Auto" 11 | "Oscuro" 12 | "Luz" 13 | "un Shell %s" 14 | "Contactar al desarrollador" 15 | "¿Necesitas ayuda o tienes algún comentario? Contacta con el desarrollador." 16 | "General" 17 | "Política de privacidad" 18 | "Tu privacidad es importante: Más información" 19 | "Ajustes" 20 | "Acceso denegado a Shizuku para aShell" 21 | "Aprende shizuku" 22 | "Obtén más información sobre shizuku en: shizuku.rikka.app" 23 | "No se encontró soporte para Shizuku" 24 | "Traducciones" 25 | "Contribuir a la traducción de la aplicación" 26 | "Interfaz de usuario" 27 | -------------------------------------------------------------------------------- /app/src/main/res/values-fr/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | "Annuler" 4 | "Appuyez à nouveau sur la touche arrière pour sortir" 5 | "Demander l'autorisation" 6 | "Commencer" 7 | "Oui" 8 | "Copyright : © 2025, sunilpaulmathew" 9 | "Thème de l'application" 10 | "Automatique" 11 | "Noir" 12 | "Blanc" 13 | "aShell %s" 14 | "Contacter le développeur" 15 | "Besoin d'aide ou un avis à formuler ? Contacter le développeur" 16 | "Général" 17 | "Politique de confidentialité" 18 | "Votre vie privée est importante : En savoir plus" 19 | "Réglages" 20 | "Shizuku : accès refusé pour aShell" 21 | "En apprendre plus sur shizuku" 22 | "Pour en savoir plus sur shizuku : shizuku.rikka.app" 23 | "L'environnement Shizuku n'a pas été détecté" 24 | "Traductions" 25 | "Contribuer à la traduction de l'application" 26 | "Interface utilisateur" 27 | -------------------------------------------------------------------------------- /app/src/main/res/values-hu/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | "App Téma" 4 | "Automatikus" 5 | "Sötét" 6 | "Világos" 7 | "Mégse" 8 | "Nyomja meg ismét a vissza gombot a kilépéshez" 9 | "Engedély kérés" 10 | "Indítás" 11 | "Fordítások" 12 | "Igen" 13 | "Szerzői jog: © 2025, sunilpaulmathew" 14 | -------------------------------------------------------------------------------- /app/src/main/res/values-in/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | "Batal" 4 | "Tekan kembali lagi untuk keluar" 5 | "Meminta izin" 6 | "Mulai" 7 | "Ya" 8 | "Hak cipta © 2025, sunilpaulmathew" 9 | "Tema Aplikasi" 10 | "Otomatis" 11 | "Mode Gelap" 12 | "Mode Terang" 13 | "aShell %s" 14 | "Hubungi pengembang" 15 | "Butuh bantuan atau memiliki saran? Hubungi pengembang sekarang" 16 | "Umum" 17 | "Kebijakan privasi" 18 | "Privasi anda penting: pelajari selengkapnya" 19 | "Pengaturan" 20 | "Akses Shizuku ditolak oleh aShell" 21 | "Pelajari Shizuku" 22 | "Pelajari selengkapnya terkait Shizuku: Shizuku.rikka.app" 23 | "Dukungan Shizuku tidak ditemukan" 24 | "Terjemahkan" 25 | "Berkontribusi penerjemah aplikasi" 26 | "Antarmuka" 27 | -------------------------------------------------------------------------------- /app/src/main/res/values-ja/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | "キャンセル" 4 | "もう一度タップして終了" 5 | "権限を要求する" 6 | "開始" 7 | "はい" 8 | "Copyright: © 2025, sunilpaulmathew" 9 | "アプリテーマ" 10 | "システムのデフォルトに従う" 11 | "ダーク" 12 | "ライト" 13 | "aShell %s" 14 | "開発者に連絡" 15 | "ヘルプやフィードバックが必要な場合は、開発者にお問い合わせください" 16 | "一般" 17 | "プライバシーポリシー" 18 | "プライバシーは重要です: 詳細はこちら" 19 | "設定" 20 | "Shizukuへのアクセスが拒否されました" 21 | "Shizukuについて学ぶ" 22 | "Shizukuの詳細については: shizuku.rikka.app をご覧ください" 23 | "Shizukuが見つかりません" 24 | "翻訳" 25 | "アプリの翻訳に協力する" 26 | "ユーザーインターフェース" 27 | -------------------------------------------------------------------------------- /app/src/main/res/values-ko/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | "취소" 4 | "종료하려면 뒤로가기 버튼을 다시 누르세요" 5 | "권한 요청" 6 | "시작" 7 | "확인" 8 | "저작권: © 2025, sunilpaulmathew" 9 | "앱 테마" 10 | "자동" 11 | "다크" 12 | "라이트" 13 | "aShell %s" 14 | "개발자에게 문의하기" 15 | "도움이 필요하거나 피드백이 있으신가요? 개발자에게 문의하세요" 16 | "일반" 17 | "개인정보 처리방침" 18 | "개인정보는 중요합니다: 자세히 알아보기" 19 | "설정" 20 | "Shizuku가 aShell의 권한을 거부했습니다" 21 | "shizuku 알아보기" 22 | "shizuku에 대한 자세한 정보: shizuku.rikka.app" 23 | "Shizuku 서비스를 찾을 수 없습니다" 24 | "번역" 25 | "앱 번역에 기여하기" 26 | "사용자 환경" 27 | -------------------------------------------------------------------------------- /app/src/main/res/values-pl/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | "Anuluj" 4 | "Naciśnij ponownie wstecz, aby wyjść" 5 | "Żądaj uprawnień" 6 | "Start" 7 | "Tak" 8 | "©2025 sunilpaulmathew, Wszelkie prawa zastrzeżone." 9 | "Motyw aplikacji" 10 | "Automatyczny" 11 | "Ciemny" 12 | "Jasny" 13 | "aShell %s" 14 | "Kontakt z deweloperem" 15 | "Potrzebujesz pomocy lub masz opinię? Skontaktuj się z deweloperem" 16 | "Ogólne" 17 | "Polityka prywatności" 18 | "Twoja prywatność ma znaczenie: Dowiedz się więcej" 19 | "Ustawienia" 20 | "Odmowa dostępu Shizuku dla aShell" 21 | "Dowiedz się więcej o Shizuku" 22 | "Dowiedz się więcej o Shizuku na: shizuku.rikka.app" 23 | "Shizuku niedostępne" 24 | "Tłumaczenie" 25 | "Pomóż w tłumaczeniu aplikacji" 26 | "Interfejs" 27 | -------------------------------------------------------------------------------- /app/src/main/res/values-pt-rBR/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | "Tema do App" 4 | "Escuro" 5 | "Claro" 6 | Cancelar 7 | Pressione voltar novamente para sair 8 | Solicitar Permissão 9 | Iniciar 10 | "Traduções" 11 | Sim 12 | -------------------------------------------------------------------------------- /app/src/main/res/values-pt-rPT/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | "Tema da aplicação" 4 | "Automático" 5 | "Escuro" 6 | "Claro" 7 | "Cancelar" 8 | "Premir novamente para sair" 9 | "Solicitar autorização" 10 | "Iniciar" 11 | "Traduções" 12 | "Sim" 13 | -------------------------------------------------------------------------------- /app/src/main/res/values-ru/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | "Тема приложения" 5 | "Авто" 6 | "Тёмная" 7 | "Светлая" 8 | "Отмена" 9 | "Нажмите ещё раз для выхода" 10 | "Запросить разрешение" 11 | "Начать" 12 | "Переводы" 13 | "Да" 14 | -------------------------------------------------------------------------------- /app/src/main/res/values-tr/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | "İptal" 4 | "Çıkmak için tekrar geri tuşuna basın" 5 | "İzin istemi" 6 | "Başlat" 7 | "Evet" 8 | "Telif hakkı: © 2025, sunilpaulmathew" 9 | "Uygulama teması" 10 | "Otomatik" 11 | "Koyu" 12 | "Açık" 13 | "aShell %s" 14 | "Geliştirici ile iletişim kur" 15 | "Yardıma veya geri bildirime mi ihtiyacınız var? Geliştiriciyle iletişim kurun" 16 | "Genel" 17 | "Gizlilik politikası" 18 | "Gizliliğin önemli: Dahasını öğren" 19 | "Ayarlar" 20 | "aShell için Shizuku erişimi reddedildi" 21 | "Shizuku hakkında" 22 | "Shizuku hakkında dahası için: shizuku.rikka.app" 23 | "Shizuku desteği bulunamadı" 24 | "Çeviriler" 25 | "Bu uygulamanın tercümesine katkıda bulunun" 26 | "Kullanıcı arayüzü" 27 | -------------------------------------------------------------------------------- /app/src/main/res/values-v35/theme.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values-vi/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | "Hủy" 4 | "Nhấn lại lần nữa để thoát" 5 | "Yêu cầu quyền" 6 | "Bắt đầu" 7 | "Đúng" 8 | "Bản quyền: © 2025, sunilpaulmathew" 9 | "Chủ đề ứng dụng" 10 | "Tự động" 11 | "Nền tối" 12 | "Nền sáng" 13 | "aShell %s" 14 | "Liên hệ nhà phát triển" 15 | "Cần trợ giúp hoặc phản hồi? Liên hệ với nhà phát triển" 16 | "Tổng quan" 17 | "Chính sách bảo mật" 18 | "Quyền riêng tư của bạn rất quan trọng: Tìm hiểu thêm" 19 | "Cài đặt" 20 | "Shizuku bị từ chối quyền truy cập vào aShell" 21 | "Tìm hiểu Shizuku" 22 | "Tìm hiểu thêm về shizuku tại: shizuku.rikka.app" 23 | "Shizuku không khả dụng" 24 | "Bản dịch" 25 | "Đóng góp vào bản dịch của ứng dụng" 26 | "Giao diện người dùng" 27 | -------------------------------------------------------------------------------- /app/src/main/res/values-zh-rCN/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | "取消" 5 | "再次点击后退以退出" 6 | "请求权限" 7 | "开始" 8 | "是" 9 | "版权: © 2025, sunilpaulmathew" 10 | "应用主题" 11 | "自动" 12 | "深色" 13 | "浅色" 14 | "aShell %s" 15 | "联系开发者" 16 | "需要帮助或想要反馈?联系开发者" 17 | "通用" 18 | "隐私政策" 19 | "你的隐私很重要:了解更多" 20 | "设置" 21 | "aShell 的 Shizuku 访问被拒绝" 22 | "了解 Shizuku" 23 | "了解更多关于 Shizuku: shizuku.rikka.app" 24 | "没有找到 Shizuku 支持" 25 | "翻译" 26 | "为本应用的翻译作出贡献" 27 | "用户界面" 28 | -------------------------------------------------------------------------------- /app/src/main/res/values-zh-rHK/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | "取消" 5 | "再按一次返回鍵即可關閉" 6 | "權限要求" 7 | "開始" 8 | "是" 9 | "版權所有:© 2025, sunilpaulmathew" 10 | "主題" 11 | "自動" 12 | "深色" 13 | "淺色" 14 | "aShell %s" 15 | "聯絡開發人員" 16 | "需要協助或提供意見嗎?請聯絡我們" 17 | "一般" 18 | "隱私權政策" 19 | "與您的隱私相關:了解更多" 20 | "設定" 21 | "aShell 存取 Shizuku 遭拒" 22 | "認識 Shizuku" 23 | "了解更多關於 Shizuku:shizuku.rikka.app" 24 | "找不到 Shizuku 支援" 25 | "翻譯" 26 | "協助翻譯應用程式" 27 | "介面" 28 | -------------------------------------------------------------------------------- /app/src/main/res/values-zh-rTW/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | "取消" 5 | "再按一次返回鍵即可關閉" 6 | "權限要求" 7 | "開始" 8 | "是" 9 | "版權所有:© 2025, sunilpaulmathew" 10 | "主題" 11 | "自動" 12 | "深色" 13 | "淺色" 14 | "aShell %s" 15 | "聯絡開發人員" 16 | "需要協助或提供意見嗎?請聯絡我們" 17 | "一般" 18 | "隱私權政策" 19 | "與您的隱私相關:了解更多" 20 | "設定" 21 | "aShell 存取 Shizuku 遭拒" 22 | "認識 Shizuku" 23 | "了解更多關於 Shizuku:shizuku.rikka.app" 24 | "找不到 Shizuku 支援" 25 | "翻譯" 26 | "協助翻譯應用程式" 27 | "介面" 28 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #000000 4 | #4285f4 5 | #FFFFFF 6 | 7 | #00B894 8 | #FDCB6E 9 | #E17055 10 | #D63031 11 | 12 | #74B9FF 13 | #A4B0BE 14 | #B2BEC3 15 | #A29BFE 16 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | AppVaultX 3 | 4 | App Theme 5 | Auto 6 | Dark 7 | Light 8 | %s is built for development; may expose debug information. 9 | Debuggable 10 | %s is currently turned off and not active on the device. 11 | Disabled 12 | System 13 | %s is a preinstalled app and is a part of the Android system. 14 | %s is a system app that has been updated with a newer version. 15 | System (Upd.) 16 | %s is installed manually by the user or from the Play Store. 17 | User. 18 | AppVaultX %s 19 | Installed Apps 20 | Removed Apps 21 | Applying… 22 | Cancel 23 | Clear data 24 | Copyright: © 2025, sunilpaulmathew 25 | Contact Developer 26 | Need help or have feedback? Contact the developer 27 | Downgrade 28 | Downgrade required: Yes 29 | Force close 30 | General 31 | Ignore 32 | Install 33 | Installation failed… 34 | Installation completed successfully 35 | Do you want to %s this app? 36 | Installer 37 | Installing %s… 38 | Loading… 39 | Miscellaneous 40 | Never show 41 | Open app 42 | Press back again to exit… 43 | Privacy Policy 44 | Your privacy matters: Learn more 45 | Reverse 46 | Remove 47 | Remove selected (%s) 48 | Request Permission 49 | Restore 50 | Restore %s? 51 | Restore selected (%s) 52 | Save APK\'s 53 | Save icon 54 | The selected item(s) is exported to \'%s\' 55 | Search in %s items… 56 | Settings 57 | Access to Shizuku service is denied for AppVaultX. Many features in AppVaultX won\'t work without a proper Shizuku environment. 58 | Shizuku access denied for AppVaultX 59 | AppVaultX integrates with Shizuku to perform secure system-level actions without root. Granting Shizuku access enables enhanced performance, automation, and advanced features. 60 | To enable Shizuku on this device for AppVaultX:\n\n1. Open the Shizuku app\n2. Go to Authorized applications\n3. Enable access for AppVaultX 61 | Learn Shizuku 62 | Learn more about shizuku at: shizuku.rikka.app 63 | Shizuku Mode 64 | Disabled 65 | Enabled 66 | Ignored 67 | Unavailable 68 | Open Shizuku 69 | Shizuku is not installed or not properly configured on your device. Many features in AppVaultX won\'t work without a proper Shizuku environment. 70 | Shizuku support not found 71 | Source Code 72 | Discover how AppVaultX works — open-source and transparent 73 | Start 74 | Translations 75 | Contribute to the app\'s translation 76 | Learn UAD-NG 77 | AppVaultX uses app removal recommendations sourced from the Universal Android Debloater Next Generation project. Learn more at: github.com/Universal-Debloater-NextGen 78 | %s is safe to remove. 79 | Safe to remove 80 | %s is likely safe to remove. 81 | Likely safe 82 | Removing %s may cause issues. 83 | Likely dangerous 84 | Removing %s is dangerous and not recommended. 85 | Dangerous 86 | Uninstall 87 | Update 88 | User interface 89 | Yes 90 | -------------------------------------------------------------------------------- /app/src/main/res/values/theme.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 | 22 | 23 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | plugins { 3 | alias(libs.plugins.androidApplication) apply false 4 | } -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/changelogs/1.txt: -------------------------------------------------------------------------------- 1 | * Initial release -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/full_description.txt: -------------------------------------------------------------------------------- 1 | Features 2 | 3 | * 🔍 Smart App Recommendations 4 | • Categorizes installed apps as **Recommended**, **Advanced**, **Expert**, or **Unsafe** 5 | • Powered by trusted data from the **[Universal Android Debloater Next Generation](https://github.com/0x192/universal-android-debloater)** project 6 | 7 | * 🛠️ App Management with Shizuku Support 8 | • **Force Close Apps** – safely stop any running app 9 | • **Clear Data & Cache** – free storage and reset apps 10 | • **Backup APKs & Icons** – save app files and icons for future use 11 | • **Uninstall Apps (Individual or Batch)** – remove unwanted apps efficiently 12 | • **Restore Removed System Apps** – safely recover system apps 13 | • **APK Installer** – Seamlessly install, update, or downgrade APKs — including debug builds — directly from your file manager 14 | 15 | * 📱 Standard App Management (Without Shizuku) 16 | • **Package Viewer** – explore installed apps and details 17 | • **Open Apps** – launch any installed app directly 18 | • **Save APKs & Icons** – backup apps locally 19 | • **Access System Settings** – quick shortcuts to app-related settings 20 | 21 | * 💎 User Experience 22 | • **Modern Material Design UI** – sleek, clean, and intuitive 23 | • **Batch Operations** – manage multiple apps effortlessly 24 | 25 | Translations 26 | 27 | Please help me to translate this application via POEditor. -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/fastlane/metadata/android/en-US/images/icon.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/phoneScreenshots/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/phoneScreenshots/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/phoneScreenshots/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/phoneScreenshots/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/images/phoneScreenshots/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png -------------------------------------------------------------------------------- /fastlane/metadata/android/en-US/short_description.txt: -------------------------------------------------------------------------------- 1 | App Control Made Easy -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Enables namespacing of each library's R class so that its R class includes only the 19 | # resources declared in the library itself and none from the library's dependencies, 20 | # thereby reducing the size of the R class for that library 21 | android.nonTransitiveRClass=true 22 | android.defaults.buildfeatures.buildconfig=false 23 | android.nonFinalResIds=false -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | agp = "8.13.0" 3 | material = "1.13.0" 4 | preference = "1.2.1" 5 | shizuku = "13.1.5" 6 | 7 | [libraries] 8 | material = { group = "com.google.android.material", name = "material", version.ref = "material" } 9 | preference = { module = "androidx.preference:preference", version.ref = "preference" } 10 | shizukuApi = { module = "dev.rikka.shizuku:api", version.ref = "shizuku" } 11 | shizukuProvider = { module = "dev.rikka.shizuku:provider", version.ref = "shizuku" } 12 | 13 | [plugins] 14 | androidApplication = { id = "com.android.application", version.ref = "agp" } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunilpaulmathew/AppVaultX/610b124f305c6ad7314bd85e7edb55ce75fb670e/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Oct 28 20:41:01 CEST 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | gradlePluginPortal() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | } 15 | rootProject.name = "AppVaultX" 16 | include ':app' 17 | --------------------------------------------------------------------------------