Search in sources :

Example 1 with DialogTitleBuilder

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

the class PackageInstallerActivity method getInstallationFinishedDialog.

@NonNull
public AlertDialog getInstallationFinishedDialog(String packageName, CharSequence message, @Nullable String statusMessage, boolean displayOpenAndAppInfo) {
    View view = getLayoutInflater().inflate(R.layout.dialog_scrollable_text_view, null);
    view.findViewById(android.R.id.checkbox).setVisibility(View.GONE);
    TextView tv = view.findViewById(android.R.id.content);
    SpannableStringBuilder ssb = new SpannableStringBuilder(message);
    if (statusMessage != null) {
        ssb.append("\n\n").append(UIUtils.getItalicString(statusMessage));
    }
    tv.setText(ssb);
    DialogTitleBuilder title = new DialogTitleBuilder(this).setTitle(model.getAppLabel()).setSubtitle(getVersionInfoWithTrackers(model.getNewPackageInfo())).setStartIcon(model.getAppIcon());
    if (displayOpenAndAppInfo) {
        title.setEndIcon(R.drawable.ic_information_variant, v -> {
            Intent appDetailsIntent = new Intent(this, AppDetailsActivity.class);
            appDetailsIntent.putExtra(AppDetailsActivity.EXTRA_PACKAGE_NAME, packageName);
            appDetailsIntent.putExtra(AppDetailsActivity.EXTRA_USER_HANDLE, lastUserId);
            appDetailsIntent.putExtra(AppDetailsActivity.EXTRA_BACK_TO_MAIN, true);
            appDetailsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(appDetailsIntent);
        });
    }
    MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this).setCustomTitle(title.build()).setView(view).setCancelable(false).setNegativeButton(hasNext() ? R.string.next : R.string.close, (dialog, which) -> {
        dialog.dismiss();
        goToNext();
    });
    if (displayOpenAndAppInfo) {
        Intent intent = getPackageManager().getLaunchIntentForPackage(packageName);
        if (intent != null) {
            builder.setPositiveButton(R.string.open, (dialog, which) -> {
                dialog.dismiss();
                startActivity(intent);
                goToNext();
            });
        }
    }
    return builder.create();
}
Also used : TextView(android.widget.TextView) Intent(android.content.Intent) View(android.view.View) TextView(android.widget.TextView) MaterialAlertDialogBuilder(com.google.android.material.dialog.MaterialAlertDialogBuilder) SpannableStringBuilder(android.text.SpannableStringBuilder) DialogTitleBuilder(io.github.muntashirakon.dialog.DialogTitleBuilder) NonNull(androidx.annotation.NonNull)

Example 2 with DialogTitleBuilder

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

the class AppInfoFragment method setupTagCloud.

@UiThread
private void setupTagCloud(AppInfoViewModel.TagCloud tagCloud) {
    mTagCloud.removeAllViews();
    if (mainModel == null)
        return;
    // Add tracker chip
    if (!tagCloud.trackerComponents.isEmpty()) {
        CharSequence[] trackerComponentNames = new CharSequence[tagCloud.trackerComponents.size()];
        for (int i = 0; i < trackerComponentNames.length; ++i) {
            ComponentRule rule = tagCloud.trackerComponents.get(i);
            trackerComponentNames[i] = rule.isBlocked() ? getColoredText(rule.name, ContextCompat.getColor(mActivity, R.color.stopped)) : rule.name;
        }
        addChip(getResources().getQuantityString(R.plurals.no_of_trackers, tagCloud.trackerComponents.size(), tagCloud.trackerComponents.size()), tagCloud.areAllTrackersBlocked ? R.color.stopped : R.color.tracker).setOnClickListener(v -> {
            if (!isExternalApk && isRootEnabled) {
                new SearchableMultiChoiceDialogBuilder<>(mActivity, tagCloud.trackerComponents, trackerComponentNames).setTitle(R.string.trackers).setSelections(tagCloud.trackerComponents).setNegativeButton(R.string.cancel, null).setPositiveButton(R.string.block, (dialog, which, selectedItems) -> {
                    showProgressIndicator(true);
                    executor.submit(() -> {
                        mainModel.addRules(selectedItems, true);
                        runOnUiThread(() -> {
                            if (isDetached())
                                return;
                            showProgressIndicator(false);
                            displayShortToast(R.string.done);
                        });
                    });
                }).setNeutralButton(R.string.unblock, (dialog, which, selectedItems) -> {
                    showProgressIndicator(true);
                    executor.submit(() -> {
                        mainModel.removeRules(selectedItems, true);
                        runOnUiThread(() -> {
                            if (isDetached())
                                return;
                            showProgressIndicator(false);
                            displayShortToast(R.string.done);
                        });
                    });
                }).show();
            } else {
                new MaterialAlertDialogBuilder(mActivity).setTitle(R.string.trackers).setItems(trackerComponentNames, null).setNegativeButton(R.string.close, null).show();
            }
        });
    }
    if (tagCloud.isSystemApp) {
        if (tagCloud.isSystemlessPath) {
            addChip(R.string.systemless_app);
        } else
            addChip(R.string.system_app);
        if (tagCloud.isUpdatedSystemApp) {
            addChip(R.string.updated_app);
        }
    } else if (!mainModel.getIsExternalApk())
        addChip(R.string.user_app);
    if (tagCloud.splitCount > 0) {
        addChip(getResources().getQuantityString(R.plurals.no_of_splits, tagCloud.splitCount, tagCloud.splitCount)).setOnClickListener(v -> {
            try (ApkFile apkFile = ApkFile.getInstance(mainModel.getApkFileKey())) {
                // Display a list of apks
                List<ApkFile.Entry> apkEntries = apkFile.getEntries();
                CharSequence[] entryNames = new CharSequence[tagCloud.splitCount];
                for (int i = 0; i < tagCloud.splitCount; ++i) {
                    entryNames[i] = apkEntries.get(i + 1).toLocalizedString(mActivity);
                }
                new MaterialAlertDialogBuilder(mActivity).setTitle(R.string.splits).setItems(entryNames, null).setNegativeButton(R.string.close, null).show();
            }
        });
    }
    if (tagCloud.isDebuggable) {
        addChip(R.string.debuggable);
    }
    if (tagCloud.isTestOnly) {
        addChip(R.string.test_only);
    }
    if (!tagCloud.hasCode) {
        addChip(R.string.no_code);
    }
    if (tagCloud.hasRequestedLargeHeap) {
        addChip(R.string.requested_large_heap, R.color.tracker);
    }
    if (tagCloud.runningServices.size() > 0) {
        addChip(R.string.running, R.color.running).setOnClickListener(v -> {
            mProgressIndicator.show();
            executor.submit(() -> {
                CharSequence[] runningServices = new CharSequence[tagCloud.runningServices.size()];
                for (int i = 0; i < runningServices.length; ++i) {
                    runningServices[i] = new SpannableStringBuilder().append(getTitleText(mActivity, tagCloud.runningServices.get(i).service.getShortClassName())).append("\n").append(getSmallerText(new SpannableStringBuilder().append(getStyledKeyValue(mActivity, R.string.process_name, tagCloud.runningServices.get(i).process)).append("\n").append(getStyledKeyValue(mActivity, R.string.pid, String.valueOf(tagCloud.runningServices.get(i).pid)))));
                }
                DialogTitleBuilder titleBuilder = new DialogTitleBuilder(mActivity).setTitle(R.string.running_services);
                if (PermissionUtils.hasDumpPermission() && FeatureController.isLogViewerEnabled()) {
                    titleBuilder.setSubtitle(R.string.running_services_logcat_hint);
                }
                runOnUiThread(() -> {
                    mProgressIndicator.hide();
                    MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(mActivity).setCustomTitle(titleBuilder.build()).setItems(runningServices, (dialog, which) -> {
                        if (!FeatureController.isLogViewerEnabled())
                            return;
                        Intent logViewerIntent = new Intent(mActivity.getApplicationContext(), LogViewerActivity.class).setAction(LogViewerActivity.ACTION_LAUNCH).putExtra(LogViewerActivity.EXTRA_FILTER, SearchCriteria.PID_KEYWORD + tagCloud.runningServices.get(which).pid).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        mActivity.startActivity(logViewerIntent);
                    }).setNeutralButton(R.string.force_stop, (dialog, which) -> 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);
                        }
                    })).setNegativeButton(R.string.close, null);
                    builder.show();
                });
            });
        });
    }
    if (tagCloud.isForceStopped) {
        addChip(R.string.stopped, R.color.stopped);
    }
    if (!tagCloud.isAppEnabled) {
        addChip(R.string.disabled_app, R.color.disabled_user);
    }
    if (tagCloud.isAppSuspended) {
        addChip(R.string.suspended, R.color.stopped);
    }
    if (tagCloud.isAppHidden) {
        addChip(R.string.hidden, R.color.disabled_user);
    }
    magiskHiddenProcesses = tagCloud.magiskHiddenProcesses;
    if (tagCloud.isMagiskHideEnabled) {
        addChip(R.string.magisk_hide_enabled).setOnClickListener(v -> displayMagiskHideDialog());
    }
    magiskDeniedProcesses = tagCloud.magiskDeniedProcesses;
    if (tagCloud.isMagiskDenyListEnabled) {
        addChip(R.string.magisk_denylist).setOnClickListener(v -> displayMagiskDenyListDialog());
    }
    if (tagCloud.hasKeyStoreItems) {
        Chip chip;
        if (tagCloud.hasMasterKeyInKeyStore) {
            chip = addChip(R.string.keystore, R.color.tracker);
        } else
            chip = addChip(R.string.keystore);
        chip.setOnClickListener(view -> new MaterialAlertDialogBuilder(mActivity).setTitle(R.string.keystore).setItems(KeyStoreUtils.getKeyStoreFiles(mApplicationInfo.uid, mainModel.getUserHandle()).toArray(new String[0]), null).setNegativeButton(R.string.close, null).show());
    }
    if (tagCloud.backups.length > 0) {
        CharSequence[] backupNames = new CharSequence[tagCloud.backups.length];
        for (int i = 0; i < tagCloud.backups.length; ++i) {
            backupNames[i] = tagCloud.backups[i].toLocalizedString(mActivity);
        }
        addChip(R.string.backup).setOnClickListener(v -> new MaterialAlertDialogBuilder(mActivity).setTitle(R.string.backup).setItems(backupNames, null).setNegativeButton(R.string.close, null).show());
    }
    if (!tagCloud.isBatteryOptimized) {
        addChip(R.string.no_battery_optimization, R.color.red_orange).setOnClickListener(v -> new MaterialAlertDialogBuilder(mActivity).setTitle(R.string.battery_optimization).setMessage(R.string.enable_battery_optimization).setNegativeButton(R.string.no, null).setPositiveButton(R.string.yes, (dialog, which) -> {
            Runner.runCommand(new String[] { "dumpsys", "deviceidle", "whitelist", "-" + mPackageName });
            refreshDetails();
        }).show());
    }
    if (tagCloud.netPolicies > 0) {
        String[] readablePolicies = NetworkPolicyManagerCompat.getReadablePolicies(mActivity, tagCloud.netPolicies).values().toArray(new String[0]);
        addChip(R.string.has_net_policy).setOnClickListener(v -> new MaterialAlertDialogBuilder(mActivity).setTitle(R.string.net_policy).setItems(readablePolicies, null).setNegativeButton(R.string.ok, null).show());
    }
    if (tagCloud.ssaid != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        addChip(R.string.ssaid, R.color.red_orange).setOnClickListener(v -> {
            View view = getLayoutInflater().inflate(R.layout.dialog_ssaid_info, null);
            AlertDialog alertDialog = new MaterialAlertDialogBuilder(mActivity).setTitle(R.string.ssaid).setView(view).setPositiveButton(R.string.apply, null).setNegativeButton(R.string.close, null).setNeutralButton(R.string.reset_to_default, null).create();
            TextInputEditText ssaidHolder = view.findViewById(R.id.ssaid);
            TextInputLayout ssaidInputLayout = view.findViewById(android.R.id.text1);
            AtomicReference<Button> applyButton = new AtomicReference<>();
            AtomicReference<Button> resetButton = new AtomicReference<>();
            AtomicReference<String> ssaid = new AtomicReference<>(tagCloud.ssaid);
            alertDialog.setOnShowListener(dialog -> {
                applyButton.set(alertDialog.getButton(AlertDialog.BUTTON_POSITIVE));
                resetButton.set(alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL));
                applyButton.get().setVisibility(View.GONE);
                applyButton.get().setOnClickListener(v2 -> executor.submit(() -> {
                    try {
                        SsaidSettings ssaidSettings = new SsaidSettings(mPackageName, mApplicationInfo.uid);
                        if (ssaidSettings.setSsaid(ssaid.get())) {
                            model.loadTagCloud();
                            runOnUiThread(() -> displayLongToast(R.string.restart_to_reflect_changes));
                        } else {
                            runOnUiThread(() -> displayLongToast(R.string.failed_to_change_ssaid));
                        }
                        alertDialog.dismiss();
                    } catch (IOException ignore) {
                    }
                }));
                resetButton.get().setVisibility(View.GONE);
                resetButton.get().setOnClickListener(v2 -> {
                    ssaid.set(tagCloud.ssaid);
                    ssaidHolder.setText(ssaid.get());
                    resetButton.get().setVisibility(View.GONE);
                    applyButton.get().setVisibility(View.GONE);
                });
            });
            ssaidHolder.setText(tagCloud.ssaid);
            ssaidHolder.setTypeface(Typeface.MONOSPACE);
            ssaidHolder.setOnClickListener(v2 -> {
                ClipboardManager clipboard = (ClipboardManager) mActivity.getSystemService(Context.CLIPBOARD_SERVICE);
                ClipData clip = ClipData.newPlainText("SSAID", ssaid.get());
                clipboard.setPrimaryClip(clip);
                displayShortToast(R.string.copied_to_clipboard);
            });
            ssaidInputLayout.setEndIconOnClickListener(v2 -> {
                ssaid.set(SsaidSettings.generateSsaid(mPackageName));
                ssaidHolder.setText(ssaid.get());
                if (!tagCloud.ssaid.equals(ssaid.get())) {
                    if (resetButton.get() != null) {
                        resetButton.get().setVisibility(View.VISIBLE);
                    }
                    if (applyButton.get() != null) {
                        applyButton.get().setVisibility(View.VISIBLE);
                    }
                }
            });
            alertDialog.show();
        });
    }
    if (tagCloud.uriGrants != null) {
        addChip(R.string.saf).setOnClickListener(v -> {
            CharSequence[] uriGrants = new CharSequence[tagCloud.uriGrants.size()];
            for (int i = 0; i < tagCloud.uriGrants.size(); ++i) {
                uriGrants[i] = tagCloud.uriGrants.get(i).uri.toString();
            }
            new MaterialAlertDialogBuilder(mActivity).setTitle(R.string.saf).setItems(uriGrants, null).setNegativeButton(R.string.close, null).show();
        });
    }
    if (tagCloud.usesPlayAppSigning) {
        addChip(R.string.uses_play_app_signing, R.color.disabled_user).setOnClickListener(v -> new MaterialAlertDialogBuilder(mActivity).setTitle(R.string.uses_play_app_signing).setMessage(R.string.uses_play_app_signing_description).setNegativeButton(R.string.close, null).show());
    }
}
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) AlertDialog(androidx.appcompat.app.AlertDialog) ApkFile(io.github.muntashirakon.AppManager.apk.ApkFile) Chip(com.google.android.material.chip.Chip) SearchableMultiChoiceDialogBuilder(io.github.muntashirakon.AppManager.types.SearchableMultiChoiceDialogBuilder) Button(android.widget.Button) MaterialButton(com.google.android.material.button.MaterialButton) SsaidSettings(io.github.muntashirakon.AppManager.ssaid.SsaidSettings) TextInputLayout(com.google.android.material.textfield.TextInputLayout) DialogTitleBuilder(io.github.muntashirakon.dialog.DialogTitleBuilder) ClipboardManager(android.content.ClipboardManager) Intent(android.content.Intent) AtomicReference(java.util.concurrent.atomic.AtomicReference) IOException(java.io.IOException) ComponentRule(io.github.muntashirakon.AppManager.rules.struct.ComponentRule) MaterialAlertDialogBuilder(com.google.android.material.dialog.MaterialAlertDialogBuilder) ImageView(android.widget.ImageView) View(android.view.View) RecyclerView(androidx.recyclerview.widget.RecyclerView) TextView(android.widget.TextView) LogViewerActivity(io.github.muntashirakon.AppManager.logcat.LogViewerActivity) TextInputEditText(com.google.android.material.textfield.TextInputEditText) RemoteException(android.os.RemoteException) ClipData(android.content.ClipData) SpannableStringBuilder(android.text.SpannableStringBuilder) UiThread(androidx.annotation.UiThread)

Example 3 with DialogTitleBuilder

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

the class BackupRestorePreferences method onCreatePreferences.

@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
    setPreferencesFromResource(R.xml.preferences_backup_restore, rootKey);
    getPreferenceManager().setPreferenceDataStore(new SettingsDataStore());
    activity = (SettingsActivity) requireActivity();
    // Backup compression method
    String[] tarTypes = MetadataManager.TAR_TYPES;
    String[] readableTarTypes = new String[] { "GZip", "BZip2" };
    currentCompression = ArrayUtils.indexOf(tarTypes, AppPref.get(AppPref.PrefKey.PREF_BACKUP_COMPRESSION_METHOD_STR));
    Preference compressionMethod = Objects.requireNonNull(findPreference("backup_compression_method"));
    compressionMethod.setSummary(readableTarTypes[currentCompression == -1 ? 0 : currentCompression]);
    compressionMethod.setOnPreferenceClickListener(preference -> {
        new MaterialAlertDialogBuilder(activity).setTitle(R.string.pref_compression_method).setSingleChoiceItems(readableTarTypes, currentCompression, (dialog, which) -> currentCompression = which).setPositiveButton(R.string.save, (dialog, which) -> {
            AppPref.set(AppPref.PrefKey.PREF_BACKUP_COMPRESSION_METHOD_STR, tarTypes[currentCompression]);
            compressionMethod.setSummary(readableTarTypes[currentCompression == -1 ? 0 : currentCompression]);
        }).setNegativeButton(R.string.cancel, null).show();
        return true;
    });
    // Backup flags
    BackupFlags flags = BackupFlags.fromPref();
    ((Preference) Objects.requireNonNull(findPreference("backup_flags"))).setOnPreferenceClickListener(preference -> {
        new MaterialAlertDialogBuilder(activity).setTitle(R.string.backup_options).setMultiChoiceItems(BackupFlags.getFormattedFlagNames(activity), flags.flagsToCheckedItems(), (dialog, index, isChecked) -> {
            if (isChecked) {
                flags.addFlag(BackupFlags.backupFlags.get(index));
            } else
                flags.removeFlag(BackupFlags.backupFlags.get(index));
        }).setPositiveButton(R.string.save, (dialog, which) -> AppPref.set(AppPref.PrefKey.PREF_BACKUP_FLAGS_INT, flags.getFlags())).setNegativeButton(R.string.cancel, null).show();
        return true;
    });
    // Keystore toggle
    SwitchPreferenceCompat backupKeyStore = Objects.requireNonNull(findPreference("backup_android_keystore"));
    backupKeyStore.setChecked((boolean) AppPref.get(AppPref.PrefKey.PREF_BACKUP_ANDROID_KEYSTORE_BOOL));
    // Encryption
    ((Preference) Objects.requireNonNull(findPreference("encryption"))).setOnPreferenceClickListener(preference -> {
        CharSequence[] encryptionNamesText = new CharSequence[encryptionNames.length];
        for (int i = 0; i < encryptionNames.length; ++i) {
            encryptionNamesText[i] = getString(encryptionNames[i]);
        }
        int choice = encModeToIndex((String) AppPref.get(AppPref.PrefKey.PREF_ENCRYPTION_STR));
        new MaterialAlertDialogBuilder(activity).setTitle(R.string.encryption).setSingleChoiceItems(encryptionNamesText, choice, (dialog, which) -> {
            String encryptionMode = indexToEncMode(which);
            switch(encryptionMode) {
                case CryptoUtils.MODE_NO_ENCRYPTION:
                    AppPref.set(AppPref.PrefKey.PREF_ENCRYPTION_STR, encryptionMode);
                    break;
                case CryptoUtils.MODE_AES:
                    {
                        DialogFragment fragment = new AESCryptoSelectionDialogFragment();
                        fragment.show(getParentFragmentManager(), AESCryptoSelectionDialogFragment.TAG);
                        break;
                    }
                case CryptoUtils.MODE_RSA:
                    {
                        RSACryptoSelectionDialogFragment fragment = new RSACryptoSelectionDialogFragment();
                        Bundle args = new Bundle();
                        args.putString(RSACryptoSelectionDialogFragment.EXTRA_ALIAS, RSACrypto.RSA_KEY_ALIAS);
                        args.putBoolean(RSACryptoSelectionDialogFragment.EXTRA_ALLOW_DEFAULT, false);
                        fragment.setArguments(args);
                        fragment.setOnKeyPairUpdatedListener((keyPair, certificateBytes) -> {
                            if (keyPair != null) {
                                AppPref.set(AppPref.PrefKey.PREF_ENCRYPTION_STR, CryptoUtils.MODE_RSA);
                            }
                        });
                        fragment.show(getParentFragmentManager(), RSACryptoSelectionDialogFragment.TAG);
                        break;
                    }
                case CryptoUtils.MODE_ECC:
                    {
                        // TODO(01/04/21): Implement ECC
                        Toast.makeText(activity, "Not implemented yet.", Toast.LENGTH_SHORT).show();
                        break;
                    }
                case CryptoUtils.MODE_OPEN_PGP:
                    {
                        AppPref.set(AppPref.PrefKey.PREF_ENCRYPTION_STR, encryptionMode);
                        DialogFragment fragment = new OpenPgpKeySelectionDialogFragment();
                        fragment.show(getParentFragmentManager(), OpenPgpKeySelectionDialogFragment.TAG);
                    }
            }
        }).setPositiveButton(R.string.ok, null).show();
        return true;
    });
    // Backup volume
    this.backupVolume = AppPref.getSelectedDirectory();
    ((Preference) Objects.requireNonNull(findPreference("backup_volume"))).setOnPreferenceClickListener(preference -> {
        displayVolumeSelectionDialog();
        return true;
    });
    // Import backups
    ((Preference) Objects.requireNonNull(findPreference("import_backups"))).setOnPreferenceClickListener(preference -> {
        new MaterialAlertDialogBuilder(activity).setCustomTitle(new DialogTitleBuilder(activity).setTitle(R.string.pref_import_backups).setSubtitle(R.string.pref_import_backups_hint).build()).setItems(R.array.import_backup_options, (dialog, which) -> {
            importType = which;
            safSelectImportDirectory.launch(safIntent);
        }).setNegativeButton(R.string.close, null).show();
        return true;
    });
}
Also used : Bundle(android.os.Bundle) AlertDialog(androidx.appcompat.app.AlertDialog) AppDb(io.github.muntashirakon.AppManager.db.utils.AppDb) NonNull(androidx.annotation.NonNull) MaterialAlertDialogBuilder(com.google.android.material.dialog.MaterialAlertDialogBuilder) Uri(android.net.Uri) Intent(android.content.Intent) ImportType(io.github.muntashirakon.AppManager.backup.convert.ImportType) OpenPgpKeySelectionDialogFragment(io.github.muntashirakon.AppManager.settings.crypto.OpenPgpKeySelectionDialogFragment) PreferenceFragmentCompat(androidx.preference.PreferenceFragmentCompat) AtomicReference(java.util.concurrent.atomic.AtomicReference) RSACrypto(io.github.muntashirakon.AppManager.crypto.RSACrypto) StorageUtils(io.github.muntashirakon.AppManager.utils.StorageUtils) SpannableStringBuilder(android.text.SpannableStringBuilder) AppManager(io.github.muntashirakon.AppManager.AppManager) UIUtils.getSecondaryText(io.github.muntashirakon.AppManager.utils.UIUtils.getSecondaryText) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) BackupFlags(io.github.muntashirakon.AppManager.backup.BackupFlags) CryptoUtils(io.github.muntashirakon.AppManager.backup.CryptoUtils) Toast(android.widget.Toast) ArrayUtils(io.github.muntashirakon.AppManager.utils.ArrayUtils) UiThread(androidx.annotation.UiThread) RSACryptoSelectionDialogFragment(io.github.muntashirakon.AppManager.settings.crypto.RSACryptoSelectionDialogFragment) ContextCompat(androidx.core.content.ContextCompat) R(io.github.muntashirakon.AppManager.R) AESCryptoSelectionDialogFragment(io.github.muntashirakon.AppManager.settings.crypto.AESCryptoSelectionDialogFragment) ArrayMap(androidx.collection.ArrayMap) ActivityResultLauncher(androidx.activity.result.ActivityResultLauncher) SwitchPreferenceCompat(androidx.preference.SwitchPreferenceCompat) MetadataManager(io.github.muntashirakon.AppManager.backup.MetadataManager) AppPref(io.github.muntashirakon.AppManager.utils.AppPref) BatchOpsService(io.github.muntashirakon.AppManager.batchops.BatchOpsService) Preference(androidx.preference.Preference) UIUtils.getSmallerText(io.github.muntashirakon.AppManager.utils.UIUtils.getSmallerText) Objects(java.util.Objects) DialogTitleBuilder(io.github.muntashirakon.dialog.DialogTitleBuilder) StringRes(androidx.annotation.StringRes) ActivityResultContracts(androidx.activity.result.contract.ActivityResultContracts) BatchOpsManager(io.github.muntashirakon.AppManager.batchops.BatchOpsManager) Activity(android.app.Activity) Collections(java.util.Collections) DialogFragment(androidx.fragment.app.DialogFragment) OpenPgpKeySelectionDialogFragment(io.github.muntashirakon.AppManager.settings.crypto.OpenPgpKeySelectionDialogFragment) SwitchPreferenceCompat(androidx.preference.SwitchPreferenceCompat) BackupFlags(io.github.muntashirakon.AppManager.backup.BackupFlags) Bundle(android.os.Bundle) OpenPgpKeySelectionDialogFragment(io.github.muntashirakon.AppManager.settings.crypto.OpenPgpKeySelectionDialogFragment) RSACryptoSelectionDialogFragment(io.github.muntashirakon.AppManager.settings.crypto.RSACryptoSelectionDialogFragment) AESCryptoSelectionDialogFragment(io.github.muntashirakon.AppManager.settings.crypto.AESCryptoSelectionDialogFragment) DialogFragment(androidx.fragment.app.DialogFragment) MaterialAlertDialogBuilder(com.google.android.material.dialog.MaterialAlertDialogBuilder) RSACryptoSelectionDialogFragment(io.github.muntashirakon.AppManager.settings.crypto.RSACryptoSelectionDialogFragment) AESCryptoSelectionDialogFragment(io.github.muntashirakon.AppManager.settings.crypto.AESCryptoSelectionDialogFragment) Preference(androidx.preference.Preference) DialogTitleBuilder(io.github.muntashirakon.dialog.DialogTitleBuilder)

Example 4 with DialogTitleBuilder

use of io.github.muntashirakon.dialog.DialogTitleBuilder 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 5 with DialogTitleBuilder

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

the class BackupDialogFragment method onCreateDialog.

@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
    activity = requireActivity();
    Bundle args = requireArguments();
    targetPackages = args.getParcelableArrayList(ARG_PACKAGE_PAIRS);
    int customModes = args.getInt(ARG_CUSTOM_MODE, MODE_BACKUP | MODE_RESTORE | MODE_DELETE);
    if (targetPackages == null)
        return super.onCreateDialog(savedInstanceState);
    if (targetPackages.size() == 1) {
        // Check for all meta, not just the base since we are going to display every backups
        if (MetadataManager.hasAnyMetadata(targetPackages.get(0).getPackageName())) {
            ++baseBackupCount;
        }
    } else {
        // Check if only for base meta
        for (UserPackagePair userPackagePair : targetPackages) {
            if (MetadataManager.hasBaseMetadata(userPackagePair.getPackageName())) {
                ++baseBackupCount;
            }
        }
    }
    CharSequence title = targetPackages.size() == 1 ? PackageUtils.getPackageLabel(activity.getPackageManager(), targetPackages.get(0).getPackageName()) : getString(R.string.backup_options);
    DialogTitleBuilder titleBuilder = new DialogTitleBuilder(activity).setTitle(title);
    if ((customModes & MODE_DELETE) != 0 && baseBackupCount == targetPackages.size()) {
        titleBuilder.setEndIcon(R.drawable.ic_trash_can_outline, v -> {
            mode = MODE_DELETE;
            new Thread(this::handleCustomUsers).start();
        });
        titleBuilder.setEndIconContentDescription(R.string.delete_backup);
    }
    MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(activity).setCustomTitle(titleBuilder.build()).setMultiChoiceItems(BackupFlags.getFormattedFlagNames(activity), flags.flagsToCheckedItems(), (dialog, index, isChecked) -> {
        if (isChecked)
            flags.addFlag(BackupFlags.backupFlags.get(index));
        else
            flags.removeFlag(BackupFlags.backupFlags.get(index));
    }).setPositiveButton(R.string.backup, null).setNegativeButton(R.string.restore, null);
    AlertDialog alertDialog = builder.create();
    alertDialog.setOnShowListener(dialog -> {
        AlertDialog dialog1 = (AlertDialog) dialog;
        Button positiveButton = dialog1.getButton(AlertDialog.BUTTON_POSITIVE);
        Button negativeButton = dialog1.getButton(AlertDialog.BUTTON_NEGATIVE);
        if ((customModes & MODE_BACKUP) != 0) {
            positiveButton.setOnClickListener(v -> {
                mode = MODE_BACKUP;
                new Thread(this::handleCustomUsers).start();
            });
            new Thread(() -> {
                for (UserPackagePair pair : targetPackages) {
                    List<App> apps = AppManager.getDb().appDao().getAll(pair.getPackageName(), pair.getUserHandle());
                    if (apps == null || apps.size() <= 0 || !apps.get(0).isInstalled) {
                        activity.runOnUiThread(() -> {
                            if (isDetached())
                                return;
                            positiveButton.setVisibility(View.GONE);
                        });
                    }
                }
            }).start();
        } else {
            positiveButton.setVisibility(View.GONE);
        }
        // Display restore and delete only if backups of all the selected package exist
        if ((customModes & MODE_RESTORE) != 0 && baseBackupCount == targetPackages.size()) {
            negativeButton.setOnClickListener(v -> {
                mode = MODE_RESTORE;
                new Thread(this::handleCustomUsers).start();
            });
        } else {
            negativeButton.setVisibility(View.GONE);
        }
    });
    return alertDialog;
}
Also used : AlertDialog(androidx.appcompat.app.AlertDialog) Button(android.widget.Button) Bundle(android.os.Bundle) ArrayList(java.util.ArrayList) List(java.util.List) UserPackagePair(io.github.muntashirakon.AppManager.types.UserPackagePair) MaterialAlertDialogBuilder(com.google.android.material.dialog.MaterialAlertDialogBuilder) DialogTitleBuilder(io.github.muntashirakon.dialog.DialogTitleBuilder) WorkerThread(androidx.annotation.WorkerThread) UiThread(androidx.annotation.UiThread) NonNull(androidx.annotation.NonNull)

Aggregations

DialogTitleBuilder (io.github.muntashirakon.dialog.DialogTitleBuilder)10 MaterialAlertDialogBuilder (com.google.android.material.dialog.MaterialAlertDialogBuilder)9 NonNull (androidx.annotation.NonNull)8 Intent (android.content.Intent)7 SpannableStringBuilder (android.text.SpannableStringBuilder)7 Bundle (android.os.Bundle)6 View (android.view.View)6 TextView (android.widget.TextView)6 ArrayMap (androidx.collection.ArrayMap)6 Uri (android.net.Uri)5 ContextCompat (androidx.core.content.ContextCompat)5 R (io.github.muntashirakon.AppManager.R)5 ArrayUtils (io.github.muntashirakon.AppManager.utils.ArrayUtils)5 UIUtils.getSmallerText (io.github.muntashirakon.AppManager.utils.UIUtils.getSmallerText)5 ArrayList (java.util.ArrayList)5 Collections (java.util.Collections)5 ClipData (android.content.ClipData)4 ClipboardManager (android.content.ClipboardManager)4 ApplicationInfo (android.content.pm.ApplicationInfo)4 Spannable (android.text.Spannable)4