diff --git a/app/src/main/java/cu/axel/smartdock/fragments/AdvancedPreferences.java b/app/src/main/java/cu/axel/smartdock/fragments/AdvancedPreferences.java index a180c7c3..e016d850 100644 --- a/app/src/main/java/cu/axel/smartdock/fragments/AdvancedPreferences.java +++ b/app/src/main/java/cu/axel/smartdock/fragments/AdvancedPreferences.java @@ -1,6 +1,7 @@ package cu.axel.smartdock.fragments; import android.Manifest; +import android.app.Activity; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -22,178 +23,213 @@ import cu.axel.smartdock.R; import cu.axel.smartdock.utils.AppUtils; import cu.axel.smartdock.utils.DeviceUtils; +import cu.axel.smartdock.utils.Utils; public class AdvancedPreferences extends PreferenceFragmentCompat { - private boolean rootAvailable; - - @Override - public void onCreatePreferences(Bundle arg0, String arg1) { - setPreferencesFromResource(R.xml.preferences_advanced, arg1); - - Preference preferLastDisplay = findPreference("prefer_last_display"); - preferLastDisplay.setVisible(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q); - - boolean hasWriteSettingsPermission = DeviceUtils.hasWriteSettingsPermission(getActivity()); - - preferLastDisplay.setOnPreferenceClickListener((Preference p1) -> { - showAccessibilityDialog(getActivity()); - return true; - }); - - findPreference("soft_reboot").setOnPreferenceClickListener((Preference p1) -> { - DeviceUtils.sotfReboot(); - return false; - }); - - Preference moveToSystem = findPreference("move_to_system"); - moveToSystem.setVisible(!AppUtils.isSystemApp(getActivity(), getActivity().getPackageName())); - moveToSystem.setOnPreferenceClickListener((Preference p1) -> { - try { - ApplicationInfo appInfo = getActivity().getPackageManager() - .getApplicationInfo(getActivity().getPackageName(), 0); - String appDir = appInfo.sourceDir.substring(0, appInfo.sourceDir.lastIndexOf("/")); - DeviceUtils.runAsRoot("mv " + appDir + " /system/priv-app/"); - DeviceUtils.reboot(); - } catch (PackageManager.NameNotFoundException e) { - } - return false; - }); - - CheckBoxPreference hideNav = findPreference("hide_nav_buttons"); - - String result = DeviceUtils.runAsRoot("cat /system/build.prop"); - - hideNav.setChecked(result.contains("qemu.hw.mainkeys=1")); - - rootAvailable = !result.equals("error"); - findPreference("root_category").setEnabled(rootAvailable); - - if (rootAvailable && !hasWriteSettingsPermission) { - DeviceUtils.grantPermission(Manifest.permission.WRITE_SECURE_SETTINGS); - hasWriteSettingsPermission = DeviceUtils.hasWriteSettingsPermission(getActivity()); - } - - CheckBoxPreference hideStatus = findPreference("hide_status_bar"); - hideStatus.setVisible(Build.VERSION.SDK_INT < 31); - - if (hasWriteSettingsPermission) { - findPreference("secure_category").setEnabled(true); - - findPreference("custom_display_size").setOnPreferenceClickListener(p -> { - showDisplaySizeDialog(getActivity()); - return true; - }); - - hideStatus.setChecked(DeviceUtils.getGlobalSetting(getActivity(), DeviceUtils.POLICY_CONTROL, "") - .equals(DeviceUtils.IMMERSIVE_APPS)); - - hideStatus.setOnPreferenceChangeListener((Preference p1, Object p2) -> { - if ((boolean) p2) { - if (DeviceUtils.putGlobalSetting(getActivity(), DeviceUtils.POLICY_CONTROL, - DeviceUtils.IMMERSIVE_APPS)) { - if (rootAvailable) - showRebootDialog(getActivity(), true); - return true; - } - } else { - if (DeviceUtils.putGlobalSetting(getActivity(), DeviceUtils.POLICY_CONTROL, null)) { - if (rootAvailable) - showRebootDialog(getActivity(), true); - return true; - } - } - return false; - }); - - findPreference("status_icon_blacklist").setOnPreferenceClickListener((Preference p1) -> { - showIBDialog(getActivity()); - return false; - }); - - CheckBoxPreference disableHeadsUp = findPreference("disable_heads_up"); - disableHeadsUp - .setChecked(DeviceUtils.getGlobalSetting(getActivity(), DeviceUtils.HEADS_UP_ENABLED, 1) == 0); - disableHeadsUp.setOnPreferenceChangeListener((Preference p1, Object p2) -> { - if ((boolean) p2) { - return DeviceUtils.putGlobalSetting(getActivity(), DeviceUtils.HEADS_UP_ENABLED, 0); - } else { - return DeviceUtils.putGlobalSetting(getActivity(), DeviceUtils.HEADS_UP_ENABLED, 1); - } - }); - } - - hideNav.setOnPreferenceChangeListener((Preference p1, Object p2) -> { - if ((boolean) p2) { - String status = DeviceUtils.runAsRoot("echo qemu.hw.mainkeys=1 >> /system/build.prop"); - if (!status.equals("error")) { - hideNav.getSharedPreferences().edit().putBoolean("navbar_fix", false).apply(); - showRebootDialog(getActivity(), false); - return true; - } - } else { - String status = DeviceUtils.runAsRoot("sed -i /qemu.hw.mainkeys=1/d /system/build.prop"); - if (!status.equals("error")) { - hideNav.getSharedPreferences().edit().putBoolean("navbar_fix", true).apply(); - showRebootDialog(getActivity(), false); - return true; - } - } - return false; - }); - - findPreference("navbar_fix").setVisible(Build.VERSION.SDK_INT > 31); - } - - public void showDisplaySizeDialog(final Context context) { - MaterialAlertDialogBuilder dialog = new MaterialAlertDialogBuilder(context); - dialog.setTitle(R.string.custom_display_size_title); - View view = LayoutInflater.from(context).inflate(R.layout.dialog_display_size, null); - final EditText contentEt = view.findViewById(R.id.display_size_et); - contentEt.setText(DeviceUtils.getSecureSetting(context, DeviceUtils.DISPLAY_SIZE, "") + ""); - dialog.setPositiveButton(R.string.ok, (DialogInterface p1, int p2) -> { - String value = contentEt.getText().toString(); - String size = value.equals("0") ? "" : value; - - if (DeviceUtils.putSecureSetting(getActivity(), DeviceUtils.DISPLAY_SIZE, size) && rootAvailable) - showRebootDialog(getActivity(), true); - }); - dialog.setNegativeButton(getString(R.string.cancel), null); - dialog.setView(view); - dialog.show(); - } - - public void showIBDialog(final Context context) { - MaterialAlertDialogBuilder dialog = new MaterialAlertDialogBuilder(context); - dialog.setTitle(R.string.icon_blacklist); - View view = LayoutInflater.from(context).inflate(R.layout.dialog_icon_blacklist, null); - final EditText contentEt = view.findViewById(R.id.icon_blacklist_et); - contentEt.setText(DeviceUtils.getSecureSetting(context, DeviceUtils.ICON_BLACKLIST, "")); - dialog.setPositiveButton(R.string.ok, (DialogInterface p1, int p2) -> DeviceUtils.putSecureSetting(context, DeviceUtils.ICON_BLACKLIST, contentEt.getText().toString())); - dialog.setNegativeButton(getString(R.string.cancel), null); - dialog.setView(view); - dialog.show(); - } - - public void showRebootDialog(Context context, final boolean softReboot) { - MaterialAlertDialogBuilder dialog = new MaterialAlertDialogBuilder(context); - dialog.setTitle(getString(R.string.reboot_required_title)); - dialog.setMessage(getString(R.string.reboot_required_text)); - dialog.setPositiveButton(getString(R.string.ok), (DialogInterface p1, int p2) -> { - if (softReboot) - DeviceUtils.sotfReboot(); - else - DeviceUtils.reboot(); - }); - dialog.setNegativeButton(getString(R.string.cancel), null); - dialog.show(); - } - - public void showAccessibilityDialog(final Context context) { - MaterialAlertDialogBuilder dialog = new MaterialAlertDialogBuilder(context); - dialog.setTitle(R.string.restart); - dialog.setMessage(R.string.restart_accessibility); - dialog.setNegativeButton(getString(R.string.cancel), null); - dialog.setPositiveButton(getString(R.string.open_accessibility), (DialogInterface p1, int p2) -> startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS))); - dialog.show(); - } + private boolean rootAvailable; + private final int SAVE_REQUEST_CODE = 236; + private final int OPEN_REQUEST_CODE = 632; + + @Override + public void onCreatePreferences(Bundle arg0, String arg1) { + setPreferencesFromResource(R.xml.preferences_advanced, arg1); + + Preference preferLastDisplay = findPreference("prefer_last_display"); + preferLastDisplay.setVisible(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q); + + boolean hasWriteSettingsPermission = DeviceUtils.hasWriteSettingsPermission(getActivity()); + + preferLastDisplay.setOnPreferenceClickListener((Preference p1) -> { + showAccessibilityDialog(getActivity()); + return true; + }); + + findPreference("soft_reboot").setOnPreferenceClickListener((Preference p1) -> { + DeviceUtils.sotfReboot(); + return false; + }); + + Preference moveToSystem = findPreference("move_to_system"); + moveToSystem.setVisible(!AppUtils.isSystemApp(getActivity(), getActivity().getPackageName())); + moveToSystem.setOnPreferenceClickListener((Preference p1) -> { + try { + ApplicationInfo appInfo = getActivity().getPackageManager() + .getApplicationInfo(getActivity().getPackageName(), 0); + String appDir = appInfo.sourceDir.substring(0, appInfo.sourceDir.lastIndexOf("/")); + DeviceUtils.runAsRoot("mv " + appDir + " /system/priv-app/"); + DeviceUtils.reboot(); + } catch (PackageManager.NameNotFoundException e) { + } + return false; + }); + + CheckBoxPreference hideNav = findPreference("hide_nav_buttons"); + + String result = DeviceUtils.runAsRoot("cat /system/build.prop"); + + hideNav.setChecked(result.contains("qemu.hw.mainkeys=1")); + + rootAvailable = !result.equals("error"); + findPreference("root_category").setEnabled(rootAvailable); + + if (rootAvailable && !hasWriteSettingsPermission) { + DeviceUtils.grantPermission(Manifest.permission.WRITE_SECURE_SETTINGS); + hasWriteSettingsPermission = DeviceUtils.hasWriteSettingsPermission(getActivity()); + } + + CheckBoxPreference hideStatus = findPreference("hide_status_bar"); + hideStatus.setVisible(Build.VERSION.SDK_INT < 31); + + if (hasWriteSettingsPermission) { + findPreference("secure_category").setEnabled(true); + + findPreference("custom_display_size").setOnPreferenceClickListener(p -> { + showDisplaySizeDialog(getActivity()); + return true; + }); + + hideStatus.setChecked(DeviceUtils.getGlobalSetting(getActivity(), DeviceUtils.POLICY_CONTROL, "") + .equals(DeviceUtils.IMMERSIVE_APPS)); + + hideStatus.setOnPreferenceChangeListener((Preference p1, Object p2) -> { + if ((boolean) p2) { + if (DeviceUtils.putGlobalSetting(getActivity(), DeviceUtils.POLICY_CONTROL, + DeviceUtils.IMMERSIVE_APPS)) { + if (rootAvailable) + showRebootDialog(getActivity(), true); + return true; + } + } else { + if (DeviceUtils.putGlobalSetting(getActivity(), DeviceUtils.POLICY_CONTROL, null)) { + if (rootAvailable) + showRebootDialog(getActivity(), true); + return true; + } + } + return false; + }); + + findPreference("status_icon_blacklist").setOnPreferenceClickListener((Preference p1) -> { + showIBDialog(getActivity()); + return false; + }); + + CheckBoxPreference disableHeadsUp = findPreference("disable_heads_up"); + disableHeadsUp + .setChecked(DeviceUtils.getGlobalSetting(getActivity(), DeviceUtils.HEADS_UP_ENABLED, 1) == 0); + disableHeadsUp.setOnPreferenceChangeListener((Preference p1, Object p2) -> { + if ((boolean) p2) { + return DeviceUtils.putGlobalSetting(getActivity(), DeviceUtils.HEADS_UP_ENABLED, 0); + } else { + return DeviceUtils.putGlobalSetting(getActivity(), DeviceUtils.HEADS_UP_ENABLED, 1); + } + }); + } + + hideNav.setOnPreferenceChangeListener((Preference p1, Object p2) -> { + if ((boolean) p2) { + String status = DeviceUtils.runAsRoot("echo qemu.hw.mainkeys=1 >> /system/build.prop"); + if (!status.equals("error")) { + hideNav.getSharedPreferences().edit().putBoolean("navbar_fix", false).apply(); + showRebootDialog(getActivity(), false); + return true; + } + } else { + String status = DeviceUtils.runAsRoot("sed -i /qemu.hw.mainkeys=1/d /system/build.prop"); + if (!status.equals("error")) { + hideNav.getSharedPreferences().edit().putBoolean("navbar_fix", true).apply(); + showRebootDialog(getActivity(), false); + return true; + } + } + return false; + }); + + findPreference("navbar_fix").setVisible(Build.VERSION.SDK_INT > 31); + + findPreference("backup_preferences").setOnPreferenceClickListener((Preference p1) -> { + + startActivityForResult(new Intent(Intent.ACTION_CREATE_DOCUMENT).addCategory(Intent.CATEGORY_OPENABLE) + .setType("*/*").putExtra(Intent.EXTRA_TITLE, + getActivity().getPackageName() + "_backup_" + Utils.getCurrentDateString() + ".sdp"), + SAVE_REQUEST_CODE); + + return false; + }); + + findPreference("restore_preferences").setOnPreferenceClickListener((Preference p1) -> { + + startActivityForResult( + new Intent(Intent.ACTION_OPEN_DOCUMENT).addCategory(Intent.CATEGORY_OPENABLE).setType("*/*"), + OPEN_REQUEST_CODE); + + return false; + }); + } + + public void showDisplaySizeDialog(final Context context) { + MaterialAlertDialogBuilder dialog = new MaterialAlertDialogBuilder(context); + dialog.setTitle(R.string.custom_display_size_title); + View view = LayoutInflater.from(context).inflate(R.layout.dialog_display_size, null); + final EditText contentEt = view.findViewById(R.id.display_size_et); + contentEt.setText(DeviceUtils.getSecureSetting(context, DeviceUtils.DISPLAY_SIZE, "") + ""); + dialog.setPositiveButton(R.string.ok, (DialogInterface p1, int p2) -> { + String value = contentEt.getText().toString(); + String size = value.equals("0") ? "" : value; + + if (DeviceUtils.putSecureSetting(getActivity(), DeviceUtils.DISPLAY_SIZE, size) && rootAvailable) + showRebootDialog(getActivity(), true); + }); + dialog.setNegativeButton(getString(R.string.cancel), null); + dialog.setView(view); + dialog.show(); + } + + public void showIBDialog(final Context context) { + MaterialAlertDialogBuilder dialog = new MaterialAlertDialogBuilder(context); + dialog.setTitle(R.string.icon_blacklist); + View view = LayoutInflater.from(context).inflate(R.layout.dialog_icon_blacklist, null); + final EditText contentEt = view.findViewById(R.id.icon_blacklist_et); + contentEt.setText(DeviceUtils.getSecureSetting(context, DeviceUtils.ICON_BLACKLIST, "")); + dialog.setPositiveButton(R.string.ok, (DialogInterface p1, int p2) -> DeviceUtils.putSecureSetting(context, + DeviceUtils.ICON_BLACKLIST, contentEt.getText().toString())); + dialog.setNegativeButton(getString(R.string.cancel), null); + dialog.setView(view); + dialog.show(); + } + + public void showRebootDialog(Context context, final boolean softReboot) { + MaterialAlertDialogBuilder dialog = new MaterialAlertDialogBuilder(context); + dialog.setTitle(getString(R.string.reboot_required_title)); + dialog.setMessage(getString(R.string.reboot_required_text)); + dialog.setPositiveButton(getString(R.string.ok), (DialogInterface p1, int p2) -> { + if (softReboot) + DeviceUtils.sotfReboot(); + else + DeviceUtils.reboot(); + }); + dialog.setNegativeButton(getString(R.string.cancel), null); + dialog.show(); + } + + public void showAccessibilityDialog(final Context context) { + MaterialAlertDialogBuilder dialog = new MaterialAlertDialogBuilder(context); + dialog.setTitle(R.string.restart); + dialog.setMessage(R.string.restart_accessibility); + dialog.setNegativeButton(getString(R.string.cancel), null); + dialog.setPositiveButton(getString(R.string.open_accessibility), + (DialogInterface p1, int p2) -> startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS))); + dialog.show(); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent intent) { + if (resultCode == Activity.RESULT_OK) { + if (requestCode == SAVE_REQUEST_CODE) { + Utils.backupPreferences(getActivity(), intent.getData()); + } else if (requestCode == OPEN_REQUEST_CODE) { + Utils.restorePreferences(getActivity(), intent.getData()); + } + } + } } diff --git a/app/src/main/java/cu/axel/smartdock/utils/Utils.java b/app/src/main/java/cu/axel/smartdock/utils/Utils.java index 67b351bf..3b579120 100644 --- a/app/src/main/java/cu/axel/smartdock/utils/Utils.java +++ b/app/src/main/java/cu/axel/smartdock/utils/Utils.java @@ -16,16 +16,25 @@ import android.provider.MediaStore; import android.view.WindowManager; +import android.widget.Toast; +import androidx.preference.PreferenceManager; +import java.io.BufferedReader; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.io.InputStreamReader; import cu.axel.smartdock.R; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Map; public class Utils { public static boolean notificationPanelVisible, shouldPlayChargeComplete; public static long startupTime; - //public static int dockHeight; + //public static int dockHeight; public static void toggleBuiltinNavigation(SharedPreferences.Editor editor, boolean value) { editor.putBoolean("enable_nav_back", value); @@ -122,7 +131,7 @@ else if (level == 100) public static void saveLog(Context context, String name, String log) { try { FileWriter fw = new FileWriter( - new File(context.getExternalFilesDir(null), name + "_" + System.currentTimeMillis() + ".log")); + new File(context.getExternalFilesDir(null), name + "_" + getCurrentDateString() + ".log")); fw.write(log); fw.close(); } catch (IOException e) { @@ -155,5 +164,88 @@ else if (expression.contains("-")) return Double.parseDouble(expression.split("\\*")[0]) * Double.parseDouble(expression.split("\\*")[1]); return 0; } + + public static void backupPreferences(Context context, Uri backupUri) { + Map allPrefs = PreferenceManager.getDefaultSharedPreferences(context).getAll(); + StringBuilder stringBuilder = new StringBuilder(); + + for (Map.Entry entry : allPrefs.entrySet()) { + String type = "string"; + if (entry.getValue() instanceof Boolean) { + type = "boolean"; + } else if (entry.getValue() instanceof Integer) { + type = "integer"; + } + + stringBuilder.append(type).append(" ").append(entry.getKey()).append(" ") + .append(entry.getValue().toString()).append("\n"); + } + String content = stringBuilder.toString().trim(); + + OutputStream os = null; + try { + os = context.getContentResolver().openOutputStream(backupUri); + os.write(content.getBytes()); + os.flush(); + Toast.makeText(context, R.string.preferences_saved, Toast.LENGTH_SHORT).show(); + + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (os != null) { + try { + os.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + public static void restorePreferences(Context context, Uri restoreUri) { + InputStream is = null; + + try { + is = context.getContentResolver().openInputStream(restoreUri); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String line; + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); + + SharedPreferences.Editor editor = sharedPreferences.edit(); + while ((line = br.readLine()) != null) { + String[] contents = line.split(" "); + if (contents.length > 2) { + String type = contents[0]; + String key = contents[1]; + String value = contents[2]; + + if (type.equals("boolean")) + editor.putBoolean(key, Boolean.parseBoolean(value)); + else if (type.equals("integer")) + editor.putInt(key, Integer.parseInt(value)); + else + editor.putString(key, value); + } + } + br.close(); + editor.commit(); + Toast.makeText(context, R.string.preferences_restored, Toast.LENGTH_SHORT).show(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + } + + public static String getCurrentDateString(){ + return new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(new Date()); + } } diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 2d88ce81..7f0bc55f 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -241,6 +241,11 @@ Reinicio requerido Es necesario reiniciar para que los cambios surtan efecto. ¿Quieres reiniciar ahora? Herramientas de desarrollo + Guardar y restaurar + Guardar preferencias + Restaurar preferencias + Preferencias guardadas + Preferencias restauradas Ayuda y acerca de diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index c05af229..9df91ea3 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -241,6 +241,11 @@ ਰੀਬੂਟ ਦੀ ਲੋੜ ਹੈ ਤਬਦੀਲੀਆਂ ਨੂੰ ਲਾਗੂ ਕਰਨ ਲਈ ਇੱਕ ਰੀਬੂਟ ਦੀ ਲੋੜ ਹੈ। ਕੀ ਤੁਸੀਂ ਹੁਣੇ ਰੀਬੂਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? ਡਿਵੈਲਪਮੈਂਟ ਟੂਲਸ + Backup and restore + Backup preferences + Restore preferences + Preferences saved + Preferences restored ਮਦਦ ਅਤੇ ਇਸ ਬਾਰੇ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d7fe0931..876b889f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -240,6 +240,11 @@ Reboot required A reboot is required for changes to take effect. Do you want to reboot now? Development tools + Backup and restore + Backup preferences + Restore preferences + Preferences saved + Preferences restored Help and about diff --git a/app/src/main/res/xml/preferences_advanced.xml b/app/src/main/res/xml/preferences_advanced.xml index ce6e0999..32bc5d4b 100644 --- a/app/src/main/res/xml/preferences_advanced.xml +++ b/app/src/main/res/xml/preferences_advanced.xml @@ -81,6 +81,17 @@ android:summary="@string/soft_reboot_summary" android:title="@string/soft_reboot_title"/> + + + + +