Search in sources :

Example 1 with ScrollableDialogBuilder

use of io.github.muntashirakon.dialog.ScrollableDialogBuilder in project AppManager by MuntashirAkon.

the class AppInfoFragment method setHorizontalActions.

private void setHorizontalActions() {
    mHorizontalLayout.removeAllViews();
    if (mainModel != null && !mainModel.getIsExternalApk()) {
        // Set open
        final Intent launchIntentForPackage = mPackageManager.getLaunchIntentForPackage(mPackageName);
        if (launchIntentForPackage != null) {
            addToHorizontalLayout(R.string.launch_app, R.drawable.ic_open_in_new_black_24dp).setOnClickListener(v -> {
                try {
                    startActivity(launchIntentForPackage);
                } catch (Throwable th) {
                    UIUtils.displayLongToast(th.getLocalizedMessage());
                }
            });
        }
        // Set disable
        if (isRootEnabled || isAdbEnabled) {
            if (mApplicationInfo.enabled) {
                addToHorizontalLayout(R.string.disable, R.drawable.ic_block_black_24dp).setOnClickListener(v -> {
                    if (BuildConfig.APPLICATION_ID.equals(mPackageName)) {
                        new MaterialAlertDialogBuilder(mActivity).setMessage(R.string.are_you_sure).setPositiveButton(R.string.yes, (d, w) -> disable()).setNegativeButton(R.string.no, null).show();
                    } else
                        disable();
                });
            }
        }
        // Set uninstall
        addToHorizontalLayout(R.string.uninstall, R.drawable.ic_trash_can_outline).setOnClickListener(v -> {
            final boolean isSystemApp = (mApplicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
            if (Ops.isPrivileged()) {
                ScrollableDialogBuilder builder = new ScrollableDialogBuilder(mActivity, isSystemApp ? R.string.uninstall_system_app_message : R.string.uninstall_app_message).setCheckboxLabel(R.string.keep_data_and_app_signing_signatures).setTitle(mPackageLabel).setPositiveButton(R.string.uninstall, (dialog, which, keepData) -> executor.submit(() -> {
                    try {
                        PackageInstallerCompat.uninstall(mPackageName, mainModel.getUserHandle(), keepData);
                        runOnUiThread(() -> {
                            displayLongToast(R.string.uninstalled_successfully, mPackageLabel);
                            mActivity.finish();
                        });
                    } catch (Exception e) {
                        Log.e(TAG, e);
                        runOnUiThread(() -> displayLongToast(R.string.failed_to_uninstall, mPackageLabel));
                    }
                })).setNegativeButton(R.string.cancel, (dialog, which, keepData) -> {
                    if (dialog != null)
                        dialog.cancel();
                });
                if ((mApplicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
                    builder.setNeutralButton(R.string.uninstall_updates, (dialog, which, keepData) -> executor.submit(() -> {
                        Runner.Result result = RunnerUtils.uninstallPackageUpdate(mPackageName, mainModel.getUserHandle(), keepData);
                        if (result.isSuccessful()) {
                            runOnUiThread(() -> displayLongToast(R.string.update_uninstalled_successfully, mPackageLabel));
                        } else {
                            runOnUiThread(() -> displayLongToast(R.string.failed_to_uninstall_updates, mPackageLabel));
                        }
                    }));
                }
                builder.show();
            } else {
                Intent uninstallIntent = new Intent(Intent.ACTION_DELETE);
                uninstallIntent.setData(Uri.parse("package:" + mPackageName));
                startActivity(uninstallIntent);
            }
        });
        // Enable/disable app (root/ADB only)
        if (isRootEnabled || isAdbEnabled) {
            if (!mApplicationInfo.enabled) {
                // Enable app
                addToHorizontalLayout(R.string.enable, R.drawable.ic_baseline_get_app_24).setOnClickListener(v -> {
                    try {
                        PackageManagerCompat.setApplicationEnabledSetting(mPackageName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, mainModel.getUserHandle());
                    } catch (RemoteException | SecurityException e) {
                        Log.e(TAG, e);
                        displayLongToast(R.string.failed_to_enable, mPackageLabel);
                    }
                });
            }
        }
        if (isAdbEnabled || isRootEnabled || ServiceHelper.checkIfServiceIsRunning(mActivity, NoRootAccessibilityService.class)) {
            // Force stop
            if ((mApplicationInfo.flags & ApplicationInfo.FLAG_STOPPED) == 0) {
                addToHorizontalLayout(R.string.force_stop, R.drawable.ic_baseline_power_settings_new_24).setOnClickListener(v -> {
                    if (isAdbEnabled || isRootEnabled) {
                        executor.submit(() -> {
                            try {
                                PackageManagerCompat.forceStopPackage(mPackageName, mainModel.getUserHandle());
                                runOnUiThread(this::refreshDetails);
                            } catch (RemoteException | SecurityException e) {
                                Log.e(TAG, e);
                                displayLongToast(R.string.failed_to_stop, mPackageLabel);
                            }
                        });
                    } else {
                        // Use accessibility
                        AccessibilityMultiplexer.getInstance().enableForceStop(true);
                        activityLauncher.launch(IntentUtils.getAppDetailsSettings(mPackageName), result -> {
                            AccessibilityMultiplexer.getInstance().enableForceStop(false);
                            refreshDetails();
                        });
                    }
                });
            }
            // Clear data
            addToHorizontalLayout(R.string.clear_data, R.drawable.ic_trash_can_outline).setOnClickListener(v -> new MaterialAlertDialogBuilder(mActivity).setTitle(mPackageLabel).setMessage(R.string.clear_data_message).setPositiveButton(R.string.clear, (dialog, which) -> {
                if (isAdbEnabled || isRootEnabled) {
                    executor.submit(() -> {
                        if (PackageManagerCompat.clearApplicationUserData(mPackageName, mainModel.getUserHandle())) {
                            runOnUiThread(this::refreshDetails);
                        }
                    });
                } else {
                    // Use accessibility
                    AccessibilityMultiplexer.getInstance().enableNavigateToStorageAndCache(true);
                    AccessibilityMultiplexer.getInstance().enableClearData(true);
                    activityLauncher.launch(IntentUtils.getAppDetailsSettings(mPackageName), result -> {
                        AccessibilityMultiplexer.getInstance().enableNavigateToStorageAndCache(true);
                        AccessibilityMultiplexer.getInstance().enableClearData(false);
                        refreshDetails();
                    });
                }
            }).setNegativeButton(R.string.cancel, null).show());
            // Clear cache
            addToHorizontalLayout(R.string.clear_cache, R.drawable.ic_trash_can_outline).setOnClickListener(v -> {
                if (isAdbEnabled || isRootEnabled) {
                    executor.submit(() -> {
                        if (PackageManagerCompat.deleteApplicationCacheFilesAsUser(mPackageName, mainModel.getUserHandle())) {
                            runOnUiThread(this::refreshDetails);
                        }
                    });
                } else {
                    // Use accessibility
                    AccessibilityMultiplexer.getInstance().enableNavigateToStorageAndCache(true);
                    AccessibilityMultiplexer.getInstance().enableClearCache(true);
                    activityLauncher.launch(IntentUtils.getAppDetailsSettings(mPackageName), result -> {
                        AccessibilityMultiplexer.getInstance().enableNavigateToStorageAndCache(false);
                        AccessibilityMultiplexer.getInstance().enableClearCache(false);
                        refreshDetails();
                    });
                }
            });
        } else {
            // Display Android settings button
            addToHorizontalLayout(R.string.view_in_settings, R.drawable.ic_baseline_settings_24).setOnClickListener(v -> startActivity(IntentUtils.getAppDetailsSettings(mPackageName)));
        }
    } else if (FeatureController.isInstallerEnabled()) {
        if (mInstalledPackageInfo == null) {
            // App not installed
            addToHorizontalLayout(R.string.install, R.drawable.ic_baseline_get_app_24).setOnClickListener(v -> install());
        } else {
            // App is installed
            long installedVersionCode = PackageInfoCompat.getLongVersionCode(mInstalledPackageInfo);
            long thisVersionCode = PackageInfoCompat.getLongVersionCode(mPackageInfo);
            if (installedVersionCode < thisVersionCode) {
                // Needs update
                addToHorizontalLayout(R.string.whats_new, R.drawable.ic_information_variant).setOnClickListener(v -> {
                    Bundle args = new Bundle();
                    args.putParcelable(WhatsNewDialogFragment.ARG_NEW_PKG_INFO, mPackageInfo);
                    args.putParcelable(WhatsNewDialogFragment.ARG_OLD_PKG_INFO, mInstalledPackageInfo);
                    WhatsNewDialogFragment dialogFragment = new WhatsNewDialogFragment();
                    dialogFragment.setArguments(args);
                    dialogFragment.show(mActivity.getSupportFragmentManager(), WhatsNewDialogFragment.TAG);
                });
                addToHorizontalLayout(R.string.update, R.drawable.ic_baseline_get_app_24).setOnClickListener(v -> install());
            } else if (installedVersionCode == thisVersionCode) {
                // Needs reinstall
                addToHorizontalLayout(R.string.reinstall, R.drawable.ic_baseline_get_app_24).setOnClickListener(v -> install());
            } else {
                // Needs downgrade
                if (Ops.isPrivileged()) {
                    addToHorizontalLayout(R.string.downgrade, R.drawable.ic_baseline_get_app_24).setOnClickListener(v -> install());
                }
            }
        }
    }
    // Set manifest
    if (FeatureController.isManifestEnabled()) {
        addToHorizontalLayout(R.string.manifest, R.drawable.ic_package_variant).setOnClickListener(v -> {
            Intent intent = new Intent(mActivity, ManifestViewerActivity.class);
            startActivityForSplit(intent);
        });
    }
    // Set scanner
    if (FeatureController.isScannerEnabled()) {
        addToHorizontalLayout(R.string.scanner, R.drawable.ic_baseline_security_24).setOnClickListener(v -> {
            Intent intent = new Intent(mActivity, ScannerActivity.class);
            intent.putExtra(ScannerActivity.EXTRA_IS_EXTERNAL, isExternalApk);
            startActivityForSplit(intent);
        });
    }
    // Root only features
    if (!mainModel.getIsExternalApk()) {
        // Shared prefs (root only)
        final List<ProxyFile> sharedPrefs = new ArrayList<>();
        ProxyFile[] tmpPaths = getSharedPrefs(mApplicationInfo.dataDir);
        if (tmpPaths != null)
            sharedPrefs.addAll(Arrays.asList(tmpPaths));
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            tmpPaths = getSharedPrefs(mApplicationInfo.deviceProtectedDataDir);
            if (tmpPaths != null)
                sharedPrefs.addAll(Arrays.asList(tmpPaths));
        }
        if (!sharedPrefs.isEmpty()) {
            CharSequence[] sharedPrefNames = new CharSequence[sharedPrefs.size()];
            for (int i = 0; i < sharedPrefs.size(); ++i) {
                sharedPrefNames[i] = sharedPrefs.get(i).getName();
            }
            addToHorizontalLayout(R.string.shared_prefs, R.drawable.ic_view_list_black_24dp).setOnClickListener(v -> new MaterialAlertDialogBuilder(mActivity).setTitle(R.string.shared_prefs).setItems(sharedPrefNames, (dialog, which) -> {
                Intent intent = new Intent(mActivity, SharedPrefsActivity.class);
                intent.putExtra(SharedPrefsActivity.EXTRA_PREF_LOCATION, sharedPrefs.get(which).getAbsolutePath());
                intent.putExtra(SharedPrefsActivity.EXTRA_PREF_LABEL, mPackageLabel);
                startActivity(intent);
            }).setNegativeButton(R.string.ok, null).show());
        }
        // Databases (root only)
        final List<ProxyFile> databases = new ArrayList<>();
        tmpPaths = getDatabases(mApplicationInfo.dataDir);
        if (tmpPaths != null)
            databases.addAll(Arrays.asList(tmpPaths));
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            tmpPaths = getDatabases(mApplicationInfo.deviceProtectedDataDir);
            if (tmpPaths != null)
                databases.addAll(Arrays.asList(tmpPaths));
        }
        if (!databases.isEmpty()) {
            CharSequence[] databases2 = new CharSequence[databases.size()];
            for (int i = 0; i < databases.size(); ++i) {
                databases2[i] = databases.get(i).getName();
            }
            addToHorizontalLayout(R.string.databases, R.drawable.ic_database).setOnClickListener(v -> new MaterialAlertDialogBuilder(mActivity).setTitle(R.string.databases).setItems(databases2, (dialog, i) -> {
                // TODO: 7/7/21 VACUUM the database before opening it
                Context ctx = AppManager.getContext();
                Path dbPath = new Path(ctx, databases.get(i));
                Intent openFile = new Intent(Intent.ACTION_VIEW);
                openFile.setDataAndType(FmProvider.getContentUri(dbPath), "application/vnd.sqlite3");
                openFile.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                if (openFile.resolveActivityInfo(ctx.getPackageManager(), 0) != null) {
                    ctx.startActivity(openFile);
                }
            }).setNegativeButton(R.string.ok, null).show());
        }
    }
    // End root only features
    // Set F-Droid
    Intent fdroid_intent = new Intent(Intent.ACTION_VIEW);
    fdroid_intent.setData(Uri.parse("https://f-droid.org/packages/" + mPackageName));
    List<ResolveInfo> resolvedActivities = mPackageManager.queryIntentActivities(fdroid_intent, 0);
    if (resolvedActivities.size() > 0) {
        addToHorizontalLayout(R.string.fdroid, R.drawable.ic_frost_fdroid_black_24dp).setOnClickListener(v -> {
            try {
                startActivity(fdroid_intent);
            } catch (Exception ignored) {
            }
        });
    }
    // Set Aurora Store
    try {
        PackageInfo auroraInfo = mPackageManager.getPackageInfo(PACKAGE_NAME_AURORA_STORE, 0);
        if (PackageInfoCompat.getLongVersionCode(auroraInfo) == 36L || !auroraInfo.applicationInfo.enabled) {
            // Aurora Store is disabled or the installed version has promotional apps
            throw new PackageManager.NameNotFoundException();
        }
        addToHorizontalLayout(R.string.store, R.drawable.ic_frost_aurorastore_black_24dp).setOnClickListener(v -> {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setPackage(PACKAGE_NAME_AURORA_STORE);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setData(Uri.parse("https://play.google.com/store/apps/details?id=" + mPackageName));
            try {
                startActivity(intent);
            } catch (Exception ignored) {
            }
        });
    } catch (PackageManager.NameNotFoundException ignored) {
    }
    View v = mHorizontalLayout.getChildAt(0);
    if (v != null)
        v.requestFocus();
}
Also used : Chip(com.google.android.material.chip.Chip) Arrays(java.util.Arrays) Bundle(android.os.Bundle) NonNull(androidx.annotation.NonNull) BackupDialogFragment(io.github.muntashirakon.AppManager.backup.BackupDialogFragment) BuildConfig(io.github.muntashirakon.AppManager.BuildConfig) ComponentRule(io.github.muntashirakon.AppManager.rules.struct.ComponentRule) ProxyFile(io.github.muntashirakon.io.ProxyFile) Uri(android.net.Uri) ImageView(android.widget.ImageView) Drawable(android.graphics.drawable.Drawable) LogViewerActivity(io.github.muntashirakon.AppManager.logcat.LogViewerActivity) Manifest(android.Manifest) UIUtils.getStyledKeyValue(io.github.muntashirakon.AppManager.utils.UIUtils.getStyledKeyValue) NoRootAccessibilityService(io.github.muntashirakon.AppManager.accessibility.NoRootAccessibilityService) UIUtils.displayLongToast(io.github.muntashirakon.AppManager.utils.UIUtils.displayLongToast) UIUtils.displayShortToast(io.github.muntashirakon.AppManager.utils.UIUtils.displayShortToast) Fragment(androidx.fragment.app.Fragment) ClipboardManager(android.content.ClipboardManager) UiThread(androidx.annotation.UiThread) ContextCompat(androidx.core.content.ContextCompat) R(io.github.muntashirakon.AppManager.R) ArrayMap(androidx.collection.ArrayMap) Runner(io.github.muntashirakon.AppManager.runner.Runner) PackageManagerCompat(io.github.muntashirakon.AppManager.servermanager.PackageManagerCompat) LinearProgressIndicator(com.google.android.material.progressindicator.LinearProgressIndicator) NetworkPolicyManager(android.net.NetworkPolicyManager) KeyStoreUtils(io.github.muntashirakon.AppManager.utils.KeyStoreUtils) FileUtils(io.github.muntashirakon.AppManager.utils.FileUtils) UIUtils(io.github.muntashirakon.AppManager.utils.UIUtils) Executors(java.util.concurrent.Executors) StringRes(androidx.annotation.StringRes) Nullable(androidx.annotation.Nullable) SearchableMultiChoiceDialogBuilder(io.github.muntashirakon.AppManager.types.SearchableMultiChoiceDialogBuilder) LangUtils(io.github.muntashirakon.AppManager.utils.LangUtils) UIUtils.getColoredText(io.github.muntashirakon.AppManager.utils.UIUtils.getColoredText) ActivityResultContracts(androidx.activity.result.contract.ActivityResultContracts) MagiskHide(io.github.muntashirakon.AppManager.magisk.MagiskHide) LinearLayoutManager(androidx.recyclerview.widget.LinearLayoutManager) UiThreadHandler(io.github.muntashirakon.AppManager.utils.UiThreadHandler) PackageInstallerActivity(io.github.muntashirakon.AppManager.apk.installer.PackageInstallerActivity) RunnerUtils(io.github.muntashirakon.AppManager.runner.RunnerUtils) ServiceHelper(io.github.muntashirakon.AppManager.logcat.helper.ServiceHelper) SsaidSettings(io.github.muntashirakon.AppManager.ssaid.SsaidSettings) TextInputLayout(com.google.android.material.textfield.TextInputLayout) PackageSizeInfo(io.github.muntashirakon.AppManager.types.PackageSizeInfo) HIDDEN_API_ENFORCEMENT_DISABLED(io.github.muntashirakon.AppManager.servermanager.ApplicationInfoCompat.HIDDEN_API_ENFORCEMENT_DISABLED) WorkerThread(androidx.annotation.WorkerThread) RemoteException(android.os.RemoteException) ArrayList(java.util.ArrayList) PermissionUtils(io.github.muntashirakon.AppManager.utils.PermissionUtils) SpannableStringBuilder(android.text.SpannableStringBuilder) Path(io.github.muntashirakon.io.Path) UIUtils.getSecondaryText(io.github.muntashirakon.AppManager.utils.UIUtils.getSecondaryText) MenuInflater(android.view.MenuInflater) Menu(android.view.Menu) Settings(android.provider.Settings) SearchCriteria(io.github.muntashirakon.AppManager.logcat.struct.SearchCriteria) DateUtils(io.github.muntashirakon.AppManager.utils.DateUtils) Formatter(android.text.format.Formatter) NetworkPolicyManagerCompat(io.github.muntashirakon.AppManager.servermanager.NetworkPolicyManagerCompat) ViewModelProvider(androidx.lifecycle.ViewModelProvider) ComponentName(android.content.ComponentName) PackageInfoCompat(androidx.core.content.pm.PackageInfoCompat) IOException(java.io.IOException) AnyThread(androidx.annotation.AnyThread) WhatsNewDialogFragment(io.github.muntashirakon.AppManager.apk.whatsnew.WhatsNewDialogFragment) HIDDEN_API_ENFORCEMENT_JUST_WARN(io.github.muntashirakon.AppManager.servermanager.ApplicationInfoCompat.HIDDEN_API_ENFORCEMENT_JUST_WARN) Utils(io.github.muntashirakon.AppManager.utils.Utils) File(java.io.File) AccessibilityMultiplexer(io.github.muntashirakon.AppManager.accessibility.AccessibilityMultiplexer) FastScrollerBuilder(me.zhanghai.android.fastscroll.FastScrollerBuilder) UIUtils.getSmallerText(io.github.muntashirakon.AppManager.utils.UIUtils.getSmallerText) DigestUtils(io.github.muntashirakon.AppManager.utils.DigestUtils) AppDetailsActivity(io.github.muntashirakon.AppManager.details.AppDetailsActivity) IntentUtils(io.github.muntashirakon.AppManager.utils.IntentUtils) ComponentsBlocker(io.github.muntashirakon.AppManager.rules.compontents.ComponentsBlocker) PackageInstallerCompat(io.github.muntashirakon.AppManager.apk.installer.PackageInstallerCompat) PackageUtils(io.github.muntashirakon.AppManager.utils.PackageUtils) FeatureController(io.github.muntashirakon.AppManager.settings.FeatureController) PackageManager(android.content.pm.PackageManager) ProfileManager(io.github.muntashirakon.AppManager.profiles.ProfileManager) Spannable(android.text.Spannable) MaterialAlertDialogBuilder(com.google.android.material.dialog.MaterialAlertDialogBuilder) UIUtils.getTitleText(io.github.muntashirakon.AppManager.utils.UIUtils.getTitleText) ManifestViewerActivity(io.github.muntashirakon.AppManager.details.ManifestViewerActivity) Log(io.github.muntashirakon.AppManager.logs.Log) DrawableRes(androidx.annotation.DrawableRes) ScannerActivity(io.github.muntashirakon.AppManager.scanner.ScannerActivity) HIDDEN_API_ENFORCEMENT_DEFAULT(io.github.muntashirakon.AppManager.servermanager.ApplicationInfoCompat.HIDDEN_API_ENFORCEMENT_DEFAULT) AppManager(io.github.muntashirakon.AppManager.AppManager) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) HIDDEN_API_ENFORCEMENT_ENABLED(io.github.muntashirakon.AppManager.servermanager.ApplicationInfoCompat.HIDDEN_API_ENFORCEMENT_ENABLED) GuardedBy(androidx.annotation.GuardedBy) Locale(java.util.Locale) View(android.view.View) Button(android.widget.Button) RecyclerView(androidx.recyclerview.widget.RecyclerView) AppUsageStatsManager(io.github.muntashirakon.AppManager.usage.AppUsageStatsManager) BetterActivityResult(io.github.muntashirakon.AppManager.utils.BetterActivityResult) ApkUtils(io.github.muntashirakon.AppManager.apk.ApkUtils) PermissionUtils.hasDumpPermission(io.github.muntashirakon.AppManager.utils.PermissionUtils.hasDumpPermission) AppDetailsViewModel(io.github.muntashirakon.AppManager.details.AppDetailsViewModel) Utils.openAsFolderInFM(io.github.muntashirakon.AppManager.utils.Utils.openAsFolderInFM) ViewGroup(android.view.ViewGroup) UserPackagePair(io.github.muntashirakon.AppManager.types.UserPackagePair) TERMUX_PERM_RUN_COMMAND(io.github.muntashirakon.AppManager.utils.PermissionUtils.TERMUX_PERM_RUN_COMMAND) List(java.util.List) TextView(android.widget.TextView) TextUtils(com.android.internal.util.TextUtils) SwipeRefreshLayout(io.github.muntashirakon.widget.SwipeRefreshLayout) ProfileMetaManager(io.github.muntashirakon.AppManager.profiles.ProfileMetaManager) ApplicationInfo(android.content.pm.ApplicationInfo) Signature(android.content.pm.Signature) ColorRes(androidx.annotation.ColorRes) AppDetailsItem(io.github.muntashirakon.AppManager.details.struct.AppDetailsItem) Typeface(android.graphics.Typeface) HIDDEN_API_ENFORCEMENT_BLACK(io.github.muntashirakon.AppManager.servermanager.ApplicationInfoCompat.HIDDEN_API_ENFORCEMENT_BLACK) Context(android.content.Context) TextInputEditText(com.google.android.material.textfield.TextInputEditText) AlertDialog(androidx.appcompat.app.AlertDialog) AppDetailsFragment(io.github.muntashirakon.AppManager.details.AppDetailsFragment) Pair(android.util.Pair) Intent(android.content.Intent) MainThread(androidx.annotation.MainThread) HashMap(java.util.HashMap) Ops(io.github.muntashirakon.AppManager.settings.Ops) PackageInfo(android.content.pm.PackageInfo) AtomicReference(java.util.concurrent.atomic.AtomicReference) FmProvider(io.github.muntashirakon.AppManager.fm.FmProvider) MenuItem(android.view.MenuItem) ClipData(android.content.ClipData) ApkFile(io.github.muntashirakon.AppManager.apk.ApkFile) MaterialButton(com.google.android.material.button.MaterialButton) SharedPrefsActivity(io.github.muntashirakon.AppManager.sharedpref.SharedPrefsActivity) ArrayUtils(io.github.muntashirakon.AppManager.utils.ArrayUtils) Build(android.os.Build) ExecutorService(java.util.concurrent.ExecutorService) OutputStream(java.io.OutputStream) LayoutInflater(android.view.LayoutInflater) ActivityCompat(androidx.core.app.ActivityCompat) RulesTypeSelectionDialogFragment(io.github.muntashirakon.AppManager.rules.RulesTypeSelectionDialogFragment) MagiskDenyList(io.github.muntashirakon.AppManager.magisk.MagiskDenyList) ScrollableDialogBuilder(io.github.muntashirakon.dialog.ScrollableDialogBuilder) ResolveInfo(android.content.pm.ResolveInfo) DialogTitleBuilder(io.github.muntashirakon.dialog.DialogTitleBuilder) Bitmap(android.graphics.Bitmap) MagiskProcess(io.github.muntashirakon.AppManager.magisk.MagiskProcess) Collections(java.util.Collections) MimeTypeMap(android.webkit.MimeTypeMap) ActivityResult(androidx.activity.result.ActivityResult) ArrayList(java.util.ArrayList) BetterActivityResult(io.github.muntashirakon.AppManager.utils.BetterActivityResult) ActivityResult(androidx.activity.result.ActivityResult) ResolveInfo(android.content.pm.ResolveInfo) PackageManager(android.content.pm.PackageManager) Context(android.content.Context) Path(io.github.muntashirakon.io.Path) Bundle(android.os.Bundle) ProxyFile(io.github.muntashirakon.io.ProxyFile) PackageInfo(android.content.pm.PackageInfo) Intent(android.content.Intent) WhatsNewDialogFragment(io.github.muntashirakon.AppManager.apk.whatsnew.WhatsNewDialogFragment) SharedPrefsActivity(io.github.muntashirakon.AppManager.sharedpref.SharedPrefsActivity) MaterialAlertDialogBuilder(com.google.android.material.dialog.MaterialAlertDialogBuilder) ImageView(android.widget.ImageView) View(android.view.View) RecyclerView(androidx.recyclerview.widget.RecyclerView) TextView(android.widget.TextView) RemoteException(android.os.RemoteException) IOException(java.io.IOException) NoRootAccessibilityService(io.github.muntashirakon.AppManager.accessibility.NoRootAccessibilityService) ScrollableDialogBuilder(io.github.muntashirakon.dialog.ScrollableDialogBuilder) RemoteException(android.os.RemoteException)

Example 2 with ScrollableDialogBuilder

use of io.github.muntashirakon.dialog.ScrollableDialogBuilder in project AppManager by MuntashirAkon.

the class MainActivity method checkAppUpdate.

private void checkAppUpdate() {
    if (Utils.isAppUpdated()) {
        // Clean old am.jar
        FileUtils.deleteSilently(ServerConfig.getDestJarFile());
        mModel.executor.submit(() -> {
            final Spanned spannedChangelog = HtmlCompat.fromHtml(FileUtils.getContentFromAssets(this, "changelog.html"), HtmlCompat.FROM_HTML_MODE_COMPACT);
            runOnUiThread(() -> new ScrollableDialogBuilder(this, spannedChangelog).linkifyAll().setTitle(R.string.changelog).setNegativeButton(R.string.ok, null).setNeutralButton(R.string.instructions, (dialog, which, isChecked) -> {
                Intent helpIntent = new Intent(this, HelpActivity.class);
                startActivity(helpIntent);
            }).show());
        });
        AppPref.set(AppPref.PrefKey.PREF_LAST_VERSION_CODE_LONG, (long) BuildConfig.VERSION_CODE);
    }
}
Also used : ScrollableDialogBuilder(io.github.muntashirakon.dialog.ScrollableDialogBuilder) Intent(android.content.Intent) Spanned(android.text.Spanned)

Example 3 with ScrollableDialogBuilder

use of io.github.muntashirakon.dialog.ScrollableDialogBuilder in project AppManager by MuntashirAkon.

the class ScannerActivity method setLibraryInfo.

private void setLibraryInfo() {
    ArrayList<String> missingLibs = new ArrayList<>();
    String[] libNames = getResources().getStringArray(R.array.lib_names);
    String[] libSignatures = getResources().getStringArray(R.array.lib_signatures);
    String[] libTypes = getResources().getStringArray(R.array.lib_types);
    // The following array is directly mapped to the arrays above
    int[] signatureCount = new int[libSignatures.length];
    // Iterate over all classes
    for (String className : model.getClassListAll()) {
        if (className.length() > 8 && className.contains(".")) {
            boolean matched = false;
            // This is a greedy algorithm, only matches the first item
            for (int i = 0; i < libSignatures.length; i++) {
                if (className.contains(libSignatures[i])) {
                    matched = true;
                    // Add to found classes
                    libClassList.add(className);
                    // Increment this signature match count
                    signatureCount[i]++;
                    break;
                }
            }
            // Add the class to the missing libs list if it doesn't match the filters
            if (!matched && (mPackageName != null && !className.startsWith(mPackageName)) && !className.matches(SIG_TO_IGNORE)) {
                missingLibs.add(className);
            }
        }
    }
    Map<String, SpannableStringBuilder> foundLibInfoMap = new ArrayMap<>();
    foundLibInfoMap.putAll(getNativeLibraryInfo(false));
    // Iterate over signatures again but this time list only the found ones.
    for (int i = 0; i < libSignatures.length; i++) {
        if (signatureCount[i] == 0)
            continue;
        if (foundLibInfoMap.get(libNames[i]) == null) {
            // Add the lib info since it isn't added already
            foundLibInfoMap.put(libNames[i], new SpannableStringBuilder().append(getPrimaryText(this, libNames[i])).append(getSmallerText(" (" + libTypes[i] + ")")));
        }
        // noinspection ConstantConditions Never null here
        foundLibInfoMap.get(libNames[i]).append("\n").append(getMonospacedText(libSignatures[i])).append(getSmallerText(" (" + signatureCount[i] + ")"));
    }
    Set<String> foundLibNames = foundLibInfoMap.keySet();
    List<Spannable> foundLibInfoList = new ArrayList<>(foundLibInfoMap.values());
    int totalLibsFound = foundLibInfoList.size();
    Collections.sort(foundLibInfoList, (o1, o2) -> o1.toString().compareToIgnoreCase(o2.toString()));
    Spanned foundLibsInfo = getOrderedList(foundLibInfoList);
    String summary;
    if (totalLibsFound == 0) {
        summary = getString(R.string.no_libs);
    } else {
        summary = getResources().getQuantityString(R.plurals.libraries, totalLibsFound, totalLibsFound);
    }
    runOnUiThread(() -> {
        ((TextView) findViewById(R.id.libs_title)).setText(summary);
        ((TextView) findViewById(R.id.libs_description)).setText(TextUtils.join(", ", foundLibNames));
        if (totalLibsFound == 0)
            return;
        MaterialCardView libsView = findViewById(R.id.libs);
        libsView.setOnClickListener(v -> new ScrollableDialogBuilder(this, foundLibsInfo).setTitle(new DialogTitleBuilder(this).setTitle(R.string.lib_details).setSubtitle(summary).build()).setNegativeButton(R.string.ok, null).setNeutralButton(R.string.copy, (dialog, which, isChecked) -> {
            ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
            ClipData clip = ClipData.newPlainText(getString(R.string.signatures), foundLibsInfo);
            clipboard.setPrimaryClip(clip);
            Snackbar.make(libsView, R.string.copied_to_clipboard, Snackbar.LENGTH_SHORT).show();
        }).show());
        // Missing libs
        if (missingLibs.size() > 0) {
            ((TextView) findViewById(R.id.missing_libs_title)).setText(getResources().getQuantityString(R.plurals.missing_signatures, missingLibs.size(), missingLibs.size()));
            View view = findViewById(R.id.missing_libs);
            view.setVisibility(View.VISIBLE);
            view.setOnClickListener(v -> new SearchableMultiChoiceDialogBuilder<>(this, missingLibs, ArrayUtils.toCharSequence(missingLibs)).setTitle(R.string.signatures).showSelectAll(false).setNegativeButton(R.string.ok, null).setNeutralButton(R.string.send_selected, (dialog, which, selectedItems) -> {
                Intent i = new Intent(Intent.ACTION_SEND);
                i.setType("message/rfc822");
                i.putExtra(Intent.EXTRA_EMAIL, new String[] { "muntashirakon@riseup.net" });
                i.putExtra(Intent.EXTRA_SUBJECT, "App Manager: Missing signatures");
                i.putExtra(Intent.EXTRA_TEXT, selectedItems.toString());
                startActivity(Intent.createChooser(i, getText(R.string.signatures)));
            }).show());
        }
    });
}
Also used : ClipboardManager(android.content.ClipboardManager) ArrayList(java.util.ArrayList) ArrayMap(androidx.collection.ArrayMap) Intent(android.content.Intent) SpannableString(android.text.SpannableString) Spanned(android.text.Spanned) View(android.view.View) TextView(android.widget.TextView) MaterialCardView(com.google.android.material.card.MaterialCardView) MaterialCardView(com.google.android.material.card.MaterialCardView) SearchableMultiChoiceDialogBuilder(io.github.muntashirakon.AppManager.types.SearchableMultiChoiceDialogBuilder) TextView(android.widget.TextView) ScrollableDialogBuilder(io.github.muntashirakon.dialog.ScrollableDialogBuilder) ClipData(android.content.ClipData) SpannableStringBuilder(android.text.SpannableStringBuilder) Spannable(android.text.Spannable) DialogTitleBuilder(io.github.muntashirakon.dialog.DialogTitleBuilder)

Example 4 with ScrollableDialogBuilder

use of io.github.muntashirakon.dialog.ScrollableDialogBuilder in project AppManager by MuntashirAkon.

the class RSACryptoSelectionDialogFragment method onCreateDialog.

@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
    targetAlias = requireArguments().getString(EXTRA_ALIAS);
    allowDefault = requireArguments().getBoolean(EXTRA_ALLOW_DEFAULT, false);
    builder = new ScrollableDialogBuilder(requireActivity()).setTitle(R.string.rsa).setNegativeButton(R.string.pref_import, null).setNeutralButton(R.string.generate_key, null).setPositiveButton(allowDefault ? R.string.use_default : R.string.ok, (dialog, which, isChecked) -> {
        if (allowDefault && model != null) {
            model.addDefaultKeyPair(targetAlias);
        }
    });
    Objects.requireNonNull(model).loadSigningInfo(targetAlias);
    AlertDialog dialog = Objects.requireNonNull(builder).create();
    dialog.setOnShowListener(dialog3 -> {
        AlertDialog dialog1 = (AlertDialog) dialog3;
        Button importButton = dialog1.getButton(AlertDialog.BUTTON_NEGATIVE);
        Button generateButton = dialog1.getButton(AlertDialog.BUTTON_NEUTRAL);
        importButton.setOnClickListener(v -> {
            KeyPairImporterDialogFragment fragment = new KeyPairImporterDialogFragment();
            Bundle args = new Bundle();
            args.putString(KeyPairImporterDialogFragment.EXTRA_ALIAS, targetAlias);
            fragment.setArguments(args);
            fragment.setOnKeySelectedListener(keyPair -> model.addKeyPair(targetAlias, keyPair));
            fragment.show(getParentFragmentManager(), KeyPairImporterDialogFragment.TAG);
        });
        generateButton.setOnClickListener(v -> {
            KeyPairGeneratorDialogFragment fragment = new KeyPairGeneratorDialogFragment();
            fragment.setOnGenerateListener(keyPair -> model.addKeyPair(targetAlias, keyPair));
            fragment.show(getParentFragmentManager(), KeyPairGeneratorDialogFragment.TAG);
        });
    });
    return dialog;
}
Also used : MutableLiveData(androidx.lifecycle.MutableLiveData) X509Certificate(java.security.cert.X509Certificate) PackageUtils(io.github.muntashirakon.AppManager.utils.PackageUtils) Bundle(android.os.Bundle) AlertDialog(androidx.appcompat.app.AlertDialog) NonNull(androidx.annotation.NonNull) WorkerThread(androidx.annotation.WorkerThread) Dialog(android.app.Dialog) Log(io.github.muntashirakon.AppManager.logs.Log) KeyPair(io.github.muntashirakon.AppManager.crypto.ks.KeyPair) AndroidViewModel(androidx.lifecycle.AndroidViewModel) Button(android.widget.Button) UiThread(androidx.annotation.UiThread) ExecutorService(java.util.concurrent.ExecutorService) R(io.github.muntashirakon.AppManager.R) KeyStoreManager(io.github.muntashirakon.AppManager.crypto.ks.KeyStoreManager) LiveData(androidx.lifecycle.LiveData) ViewModelProvider(androidx.lifecycle.ViewModelProvider) ScrollableDialogBuilder(io.github.muntashirakon.dialog.ScrollableDialogBuilder) AnyThread(androidx.annotation.AnyThread) UIUtils(io.github.muntashirakon.AppManager.utils.UIUtils) Executors(java.util.concurrent.Executors) Objects(java.util.Objects) Nullable(androidx.annotation.Nullable) Application(android.app.Application) Pair(androidx.core.util.Pair) DialogFragment(androidx.fragment.app.DialogFragment) CertificateEncodingException(java.security.cert.CertificateEncodingException) AlertDialog(androidx.appcompat.app.AlertDialog) Button(android.widget.Button) Bundle(android.os.Bundle) ScrollableDialogBuilder(io.github.muntashirakon.dialog.ScrollableDialogBuilder) NonNull(androidx.annotation.NonNull)

Example 5 with ScrollableDialogBuilder

use of io.github.muntashirakon.dialog.ScrollableDialogBuilder in project AppManager by MuntashirAkon.

the class MainPreferences method onCreatePreferences.

@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
    setPreferencesFromResource(R.xml.preferences_main, rootKey);
    getPreferenceManager().setPreferenceDataStore(new SettingsDataStore());
    model = new ViewModelProvider(this).get(MainPreferencesViewModel.class);
    activity = (SettingsActivity) requireActivity();
    // Custom locale
    currentLang = AppPref.getString(AppPref.PrefKey.PREF_CUSTOM_LOCALE_STR);
    ArrayMap<String, Locale> locales = LangUtils.getAppLanguages(activity);
    final CharSequence[] languages = getLanguagesL(locales);
    Preference locale = Objects.requireNonNull(findPreference("custom_locale"));
    locale.setSummary(languages[locales.indexOfKey(currentLang)]);
    locale.setOnPreferenceClickListener(preference -> {
        new MaterialAlertDialogBuilder(activity).setTitle(R.string.choose_language).setSingleChoiceItems(languages, locales.indexOfKey(currentLang), (dialog, which) -> currentLang = locales.keyAt(which)).setPositiveButton(R.string.apply, (dialog, which) -> {
            AppPref.set(AppPref.PrefKey.PREF_CUSTOM_LOCALE_STR, currentLang);
            Lingver.getInstance().setLocale(activity, LangUtils.getLocaleByLanguage(activity));
            ActivityCompat.recreate(activity);
        }).setNegativeButton(R.string.cancel, null).show();
        return true;
    });
    // App theme
    final String[] themes = getResources().getStringArray(R.array.themes);
    currentTheme = AppPref.getInt(AppPref.PrefKey.PREF_APP_THEME_INT);
    Preference appTheme = Objects.requireNonNull(findPreference("app_theme"));
    appTheme.setSummary(themes[THEME_CONST.indexOf(currentTheme)]);
    appTheme.setOnPreferenceClickListener(preference -> {
        new MaterialAlertDialogBuilder(activity).setTitle(R.string.select_theme).setSingleChoiceItems(themes, THEME_CONST.indexOf(currentTheme), (dialog, which) -> currentTheme = THEME_CONST.get(which)).setPositiveButton(R.string.apply, (dialog, which) -> {
            AppPref.set(AppPref.PrefKey.PREF_APP_THEME_INT, currentTheme);
            AppCompatDelegate.setDefaultNightMode(currentTheme);
            appTheme.setSummary(themes[THEME_CONST.indexOf(currentTheme)]);
        }).setNegativeButton(R.string.cancel, null).show();
        return true;
    });
    // Layout orientation
    final String[] layoutOrientations = getResources().getStringArray(R.array.layout_orientations);
    currentLayoutOrientation = AppPref.getInt(AppPref.PrefKey.PREF_LAYOUT_ORIENTATION_INT);
    Preference layoutOrientation = Objects.requireNonNull(findPreference("layout_orientation"));
    layoutOrientation.setSummary(layoutOrientations[LAYOUT_ORIENTATION_CONST.indexOf(currentLayoutOrientation)]);
    layoutOrientation.setOnPreferenceClickListener(preference -> {
        new MaterialAlertDialogBuilder(activity).setTitle(R.string.pref_layout_orientation).setSingleChoiceItems(layoutOrientations, LAYOUT_ORIENTATION_CONST.indexOf(currentLayoutOrientation), (dialog, which) -> currentLayoutOrientation = LAYOUT_ORIENTATION_CONST.get(which)).setPositiveButton(R.string.apply, (dialog, which) -> {
            AppPref.set(AppPref.PrefKey.PREF_LAYOUT_ORIENTATION_INT, currentLayoutOrientation);
            ActivityCompat.recreate(activity);
        }).setNegativeButton(R.string.cancel, null).show();
        return true;
    });
    // Screen lock
    SwitchPreferenceCompat screenLock = Objects.requireNonNull(findPreference("enable_screen_lock"));
    screenLock.setChecked(AppPref.getBoolean(AppPref.PrefKey.PREF_ENABLE_SCREEN_LOCK_BOOL));
    // Mode of operation
    Preference mode = Objects.requireNonNull(findPreference("mode_of_operations"));
    final String[] modes = getResources().getStringArray(R.array.modes);
    currentMode = AppPref.getString(AppPref.PrefKey.PREF_MODE_OF_OPS_STR);
    // Backward compatibility for v2.6.0
    if (currentMode.equals("adb"))
        currentMode = Ops.MODE_ADB_OVER_TCP;
    mode.setSummary(getString(R.string.mode_of_op_with_inferred_mode_of_op, modes[MODE_NAMES.indexOf(currentMode)], getInferredMode()));
    mode.setOnPreferenceClickListener(preference -> {
        new MaterialAlertDialogBuilder(activity).setTitle(R.string.pref_mode_of_operations).setSingleChoiceItems(modes, MODE_NAMES.indexOf(currentMode), (dialog, which) -> {
            String modeName = MODE_NAMES.get(which);
            if (Ops.MODE_ADB_WIFI.equals(modeName)) {
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
                    UIUtils.displayShortToast(R.string.wireless_debugging_not_supported);
                    return;
                }
            } else {
                ServerConfig.setAdbPort(ServerConfig.DEFAULT_ADB_PORT);
            }
            currentMode = modeName;
        }).setPositiveButton(R.string.apply, (dialog, which) -> {
            AppPref.set(AppPref.PrefKey.PREF_MODE_OF_OPS_STR, currentMode);
            mode.setSummary(modes[MODE_NAMES.indexOf(currentMode)]);
            executor.submit(() -> {
                Ops.init(activity, true);
                if (isVisible()) {
                    mode.setSummary(getString(R.string.mode_of_op_with_inferred_mode_of_op, modes[MODE_NAMES.indexOf(currentMode)], getInferredMode()));
                }
            });
        }).setNegativeButton(R.string.cancel, null).show();
        return true;
    });
    Preference usersPref = Objects.requireNonNull(findPreference("selected_users"));
    usersPref.setOnPreferenceClickListener(preference -> {
        executor.submit(() -> model.loadAllUsers());
        return true;
    });
    // Enable/disable features
    FeatureController fc = FeatureController.getInstance();
    ((Preference) Objects.requireNonNull(findPreference("enabled_features"))).setOnPreferenceClickListener(preference -> {
        new MaterialAlertDialogBuilder(activity).setTitle(R.string.enable_disable_features).setMultiChoiceItems(FeatureController.getFormattedFlagNames(activity), fc.flagsToCheckedItems(), (dialog, index, isChecked) -> fc.modifyState(FeatureController.featureFlags.get(index), isChecked)).setNegativeButton(R.string.close, null).show();
        return true;
    });
    // Thread count
    Preference threadCountPref = Objects.requireNonNull(findPreference("thread_count"));
    threadCount = MultithreadedExecutor.getThreadCount();
    threadCountPref.setSummary(getResources().getQuantityString(R.plurals.pref_thread_count_msg, threadCount, threadCount));
    threadCountPref.setOnPreferenceClickListener(preference -> {
        new TextInputDialogBuilder(activity, null).setTitle(R.string.pref_thread_count).setHelperText(getString(R.string.pref_thread_count_hint, Utils.getTotalCores())).setInputText(String.valueOf(threadCount)).setNegativeButton(R.string.cancel, null).setPositiveButton(R.string.save, (dialog, which, inputText, isChecked) -> {
            if (inputText != null && TextUtils.isDigitsOnly(inputText)) {
                int c = Integer.decode(inputText.toString());
                AppPref.set(AppPref.PrefKey.PREF_CONCURRENCY_THREAD_COUNT_INT, c);
                threadCount = MultithreadedExecutor.getThreadCount();
                threadCountPref.setSummary(getResources().getQuantityString(R.plurals.pref_thread_count_msg, threadCount, threadCount));
            }
        }).show();
        return true;
    });
    // VT APK key
    ((Preference) Objects.requireNonNull(findPreference("vt_apikey"))).setOnPreferenceClickListener(preference -> {
        new TextInputDialogBuilder(activity, null).setTitle(R.string.pref_vt_apikey).setHelperText(getString(R.string.pref_vt_apikey_description) + "\n\n" + getString(R.string.vt_disclaimer)).setInputText(AppPref.getVtApiKey()).setNegativeButton(R.string.cancel, null).setPositiveButton(R.string.save, (dialog, which, inputText, isChecked) -> {
            if (inputText != null) {
                AppPref.set(AppPref.PrefKey.PREF_VIRUS_TOTAL_API_KEY_STR, inputText.toString());
            }
        }).show();
        return true;
    });
    // Import/export App Manager's KeyStore
    ((Preference) Objects.requireNonNull(findPreference("import_export_keystore"))).setOnPreferenceClickListener(preference -> {
        DialogFragment fragment = new ImportExportKeyStoreDialogFragment();
        fragment.show(getParentFragmentManager(), ImportExportKeyStoreDialogFragment.TAG);
        return true;
    });
    // About device
    ((Preference) Objects.requireNonNull(findPreference("about_device"))).setOnPreferenceClickListener(preference -> {
        executor.submit(() -> model.loadDeviceInfo(new DeviceInfo2(activity)));
        return true;
    });
    // About
    ((Preference) Objects.requireNonNull(findPreference("about"))).setOnPreferenceClickListener(preference -> {
        @SuppressLint("InflateParams") View view = getLayoutInflater().inflate(R.layout.dialog_about, null);
        ((TextView) view.findViewById(R.id.version)).setText(String.format(Locale.getDefault(), "%s (%d)", BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE));
        new AlertDialogBuilder(activity, true).setTitle(R.string.about).setView(view).show();
        return true;
    });
    // Changelog
    ((Preference) Objects.requireNonNull(findPreference("changelog"))).setOnPreferenceClickListener(preference -> {
        executor.submit(() -> model.loadChangeLog());
        return true;
    });
    // Preference loaders
    model.selectUsers().observe(this, users -> {
        if (users == null)
            return;
        int[] selectedUsers = AppPref.getSelectedUsers();
        int[] userIds = new int[users.size()];
        boolean[] choices = new boolean[users.size()];
        Arrays.fill(choices, false);
        CharSequence[] userInfo = new CharSequence[users.size()];
        for (int i = 0; i < users.size(); ++i) {
            userIds[i] = users.get(i).id;
            userInfo[i] = userIds[i] + " (" + users.get(i).name + ")";
            if (selectedUsers == null || ArrayUtils.contains(selectedUsers, userIds[i])) {
                choices[i] = true;
            }
        }
        new MaterialAlertDialogBuilder(activity).setTitle(R.string.pref_selected_users).setMultiChoiceItems(userInfo, choices, (dialog, which, isChecked) -> choices[which] = isChecked).setPositiveButton(R.string.save, (dialog, which) -> {
            List<Integer> selectedUserIds = new ArrayList<>(users.size());
            for (int i = 0; i < choices.length; ++i) {
                if (choices[i]) {
                    selectedUserIds.add(userIds[i]);
                }
            }
            if (selectedUserIds.size() > 0) {
                AppPref.setSelectedUsers(ArrayUtils.convertToIntArray(selectedUserIds));
            } else
                AppPref.setSelectedUsers(null);
            Utils.relaunchApp(activity);
        }).setNegativeButton(R.string.cancel, null).setNeutralButton(R.string.use_default, (dialog, which) -> {
            AppPref.setSelectedUsers(null);
            Utils.relaunchApp(activity);
        }).show();
    });
    // Changelog
    model.getChangeLog().observe(this, changeLog -> new ScrollableDialogBuilder(activity, changeLog, true).linkifyAll().setTitle(R.string.changelog).show());
    // Device info
    model.getDeviceInfo().observe(this, deviceInfo -> {
        @SuppressLint("InflateParams") View view = getLayoutInflater().inflate(R.layout.dialog_scrollable_text_view, null);
        ((TextView) view.findViewById(android.R.id.content)).setText(deviceInfo.toLocalizedString(activity));
        view.findViewById(android.R.id.checkbox).setVisibility(View.GONE);
        new AlertDialogBuilder(activity, true).setTitle(R.string.about_device).setView(view).show();
    });
    // Hide preferences for disabled features
    if (!FeatureController.isInstallerEnabled()) {
        ((Preference) Objects.requireNonNull(findPreference("installer"))).setVisible(false);
    }
    if (!FeatureController.isLogViewerEnabled()) {
        ((Preference) Objects.requireNonNull(findPreference("log_viewer_prefs"))).setVisible(false);
    }
}
Also used : Locale(java.util.Locale) MutableLiveData(androidx.lifecycle.MutableLiveData) MultithreadedExecutor(io.github.muntashirakon.AppManager.utils.MultithreadedExecutor) Arrays(java.util.Arrays) Bundle(android.os.Bundle) Spanned(android.text.Spanned) NonNull(androidx.annotation.NonNull) MaterialAlertDialogBuilder(com.google.android.material.dialog.MaterialAlertDialogBuilder) BuildConfig(io.github.muntashirakon.AppManager.BuildConfig) WorkerThread(androidx.annotation.WorkerThread) TextInputDialogBuilder(io.github.muntashirakon.dialog.TextInputDialogBuilder) PreferenceFragmentCompat(androidx.preference.PreferenceFragmentCompat) ArrayList(java.util.ArrayList) ImportExportKeyStoreDialogFragment(io.github.muntashirakon.AppManager.settings.crypto.ImportExportKeyStoreDialogFragment) SuppressLint(android.annotation.SuppressLint) Lingver(com.yariksoffice.lingver.Lingver) Locale(java.util.Locale) AndroidViewModel(androidx.lifecycle.AndroidViewModel) ServerConfig(io.github.muntashirakon.AppManager.servermanager.ServerConfig) ArrayUtils(io.github.muntashirakon.AppManager.utils.ArrayUtils) View(android.view.View) UserInfo(android.content.pm.UserInfo) Build(android.os.Build) ExecutorService(java.util.concurrent.ExecutorService) R(io.github.muntashirakon.AppManager.R) ArrayMap(androidx.collection.ArrayMap) LiveData(androidx.lifecycle.LiveData) ViewModelProvider(androidx.lifecycle.ViewModelProvider) ActivityCompat(androidx.core.app.ActivityCompat) SwitchPreferenceCompat(androidx.preference.SwitchPreferenceCompat) AppCompatDelegate(androidx.appcompat.app.AppCompatDelegate) AppPref(io.github.muntashirakon.AppManager.utils.AppPref) HtmlCompat(androidx.core.text.HtmlCompat) FileUtils(io.github.muntashirakon.AppManager.utils.FileUtils) ScrollableDialogBuilder(io.github.muntashirakon.dialog.ScrollableDialogBuilder) Preference(androidx.preference.Preference) UIUtils(io.github.muntashirakon.AppManager.utils.UIUtils) Utils(io.github.muntashirakon.AppManager.utils.Utils) Executors(java.util.concurrent.Executors) Objects(java.util.Objects) List(java.util.List) TextView(android.widget.TextView) LangUtils(io.github.muntashirakon.AppManager.utils.LangUtils) Application(android.app.Application) TextUtils(com.android.internal.util.TextUtils) Users(io.github.muntashirakon.AppManager.users.Users) DeviceInfo2(io.github.muntashirakon.AppManager.misc.DeviceInfo2) AlertDialogBuilder(io.github.muntashirakon.dialog.AlertDialogBuilder) DialogFragment(androidx.fragment.app.DialogFragment) ImportExportKeyStoreDialogFragment(io.github.muntashirakon.AppManager.settings.crypto.ImportExportKeyStoreDialogFragment) DialogFragment(androidx.fragment.app.DialogFragment) MaterialAlertDialogBuilder(com.google.android.material.dialog.MaterialAlertDialogBuilder) AlertDialogBuilder(io.github.muntashirakon.dialog.AlertDialogBuilder) DeviceInfo2(io.github.muntashirakon.AppManager.misc.DeviceInfo2) TextView(android.widget.TextView) ArrayList(java.util.ArrayList) List(java.util.List) ViewModelProvider(androidx.lifecycle.ViewModelProvider) SwitchPreferenceCompat(androidx.preference.SwitchPreferenceCompat) MaterialAlertDialogBuilder(com.google.android.material.dialog.MaterialAlertDialogBuilder) View(android.view.View) TextView(android.widget.TextView) SuppressLint(android.annotation.SuppressLint) Preference(androidx.preference.Preference) SuppressLint(android.annotation.SuppressLint) ScrollableDialogBuilder(io.github.muntashirakon.dialog.ScrollableDialogBuilder) ImportExportKeyStoreDialogFragment(io.github.muntashirakon.AppManager.settings.crypto.ImportExportKeyStoreDialogFragment) TextInputDialogBuilder(io.github.muntashirakon.dialog.TextInputDialogBuilder)

Aggregations

ScrollableDialogBuilder (io.github.muntashirakon.dialog.ScrollableDialogBuilder)6 Intent (android.content.Intent)4 Bundle (android.os.Bundle)4 Spanned (android.text.Spanned)4 View (android.view.View)4 TextView (android.widget.TextView)4 NonNull (androidx.annotation.NonNull)4 ArrayMap (androidx.collection.ArrayMap)4 ViewModelProvider (androidx.lifecycle.ViewModelProvider)4 R (io.github.muntashirakon.AppManager.R)4 ArrayList (java.util.ArrayList)4 ClipData (android.content.ClipData)3 ClipboardManager (android.content.ClipboardManager)3 Spannable (android.text.Spannable)3 SpannableStringBuilder (android.text.SpannableStringBuilder)3 Nullable (androidx.annotation.Nullable)3 WorkerThread (androidx.annotation.WorkerThread)3 Application (android.app.Application)2 Context (android.content.Context)2 ApplicationInfo (android.content.pm.ApplicationInfo)2