├── .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 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
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 |
--------------------------------------------------------------------------------