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();
}
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);
}
}
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());
}
});
}
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;
}
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);
}
}
Aggregations