From cc1cf3b607b47eeffcef385db0fc09a80c916ded Mon Sep 17 00:00:00 2001 From: Johann Date: Thu, 11 Jul 2024 12:37:53 +0200 Subject: [PATCH 01/12] add basic config file export/import --- .../MainActivity.java | 3 + .../SharedPreferencesIOFragment.java | 126 ++++++++++++++++++ .../SharedPreferencesIO.java | 57 ++++++++ .../layout/fragment_shared_preferences_io.xml | 21 +++ app/src/main/res/navigation/nav_graph.xml | 11 ++ app/src/main/res/xml/preference.xml | 5 + 6 files changed, 223 insertions(+) create mode 100644 app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/SettingPreferences/SharedPreferencesIOFragment.java create mode 100644 app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/SharedPreferencesIO.java create mode 100644 app/src/main/res/layout/fragment_shared_preferences_io.xml diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MainActivity.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MainActivity.java index 8da549f7..a73a24a1 100644 --- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MainActivity.java +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MainActivity.java @@ -414,6 +414,9 @@ public boolean onPreferenceStartFragment(@NonNull PreferenceFragmentCompat calle case "mobile_network_settings": navController.navigate(R.id.flagSettingFragment); break; + case "shared_preferences_io": + navController.navigate(R.id.fragment_shared_preferences_io); + break; } return true; } diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/SettingPreferences/SharedPreferencesIOFragment.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/SettingPreferences/SharedPreferencesIOFragment.java new file mode 100644 index 00000000..150a5906 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/SettingPreferences/SharedPreferencesIOFragment.java @@ -0,0 +1,126 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit.SettingPreferences; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.Toast; + +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; + +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R; +import de.fraunhofer.fokus.OpenMobileNetworkToolkit.SharedPreferencesIO; + +public class SharedPreferencesIOFragment extends Fragment { + + private static final String TAG = "SharedPreferencesIOFragment"; + private Context ct; + + private final ActivityResultLauncher exportPreferences = registerForActivityResult( + new ActivityResultContracts.StartActivityForResult(), result -> { + if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { + Uri uri = result.getData().getData(); + exportPreferencesToFile(uri); + } else { + if (this.ct != null) { + Toast.makeText(this.ct, "Failed to export preferences", Toast.LENGTH_SHORT).show(); + } + } + }); + private final ActivityResultLauncher importPreferences = registerForActivityResult( + new ActivityResultContracts.StartActivityForResult(), result -> { + if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { + Uri uri = result.getData().getData(); + importPreferencesFromFile(uri); + } else { + if (this.ct != null) { + Toast.makeText(this.ct, "Failed to import preferences", Toast.LENGTH_SHORT).show(); + } + } + }); + public SharedPreferencesIOFragment() { + super(R.layout.fragment_shared_preferences_io); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_shared_preferences_io, container, false); + this.ct = requireContext(); + Button exportButton = view.findViewById(R.id.export_button); + Button importButton = view.findViewById(R.id.import_button); + + exportButton.setOnClickListener(v -> createFile()); + importButton.setOnClickListener(v -> pickFile()); + + return view; + } + + private void createFile() { + Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); + intent.setType("application/json"); + intent.putExtra(Intent.EXTRA_TITLE, "shared_preferences.json"); + intent.putExtra("CREATE_FILE", true); + exportPreferences.launch(intent); + } + + private void pickFile() { + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + intent.setType("application/json"); + intent.putExtra("CREATE_FILE", false); + importPreferences.launch(intent); + } + + private void exportPreferencesToFile(Uri uri) { + try { + if (this.ct != null) { + String jsonString = SharedPreferencesIO.exportPreferences(this.ct); + OutputStreamWriter writer = new OutputStreamWriter(this.ct.getContentResolver().openOutputStream(uri)); + writer.write(jsonString); + writer.close(); + Toast.makeText(this.ct, "Preferences exported", Toast.LENGTH_SHORT).show(); + } + } catch (Exception e) { + Log.e(TAG, "Failed to export preferences", e); + if (this.ct != null) { + Toast.makeText(this.ct, "Failed to export preferences", Toast.LENGTH_SHORT).show(); + } + } + } + + private void importPreferencesFromFile(Uri uri) { + try { + if (this.ct != null) { + BufferedReader reader = new BufferedReader(new InputStreamReader(this.ct.getContentResolver().openInputStream(uri))); + StringBuilder stringBuilder = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + stringBuilder.append(line); + } + reader.close(); + SharedPreferencesIO.importPreferences(this.ct, stringBuilder.toString()); + Toast.makeText(this.ct, "Preferences imported", Toast.LENGTH_SHORT).show(); + } + } catch (Exception e) { + Log.e(TAG, "Failed to import preferences", e); + if (this.ct != null) { + Toast.makeText(this.ct, "Failed to import preferences", Toast.LENGTH_SHORT).show(); + } + } + } + +} diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/SharedPreferencesIO.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/SharedPreferencesIO.java new file mode 100644 index 00000000..b1345504 --- /dev/null +++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/SharedPreferencesIO.java @@ -0,0 +1,57 @@ +package de.fraunhofer.fokus.OpenMobileNetworkToolkit; + +import android.content.Context; +import android.content.SharedPreferences; +import android.util.Log; +import android.widget.Toast; + +import androidx.preference.PreferenceManager; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Iterator; + +public class SharedPreferencesIO { + + private static final String TAG = "SharedPreferencesIO"; + + public static String exportPreferences(Context context) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + JSONObject preferencesJson = new JSONObject(prefs.getAll()); + try { + return preferencesJson.toString(4); + } catch (JSONException e) { + return "{}"; + } + } + + public static void importPreferences(Context context, String jsonString) { + try { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + SharedPreferences.Editor editor = prefs.edit(); + JSONObject spJSON = new JSONObject(jsonString); + for (Iterator it = spJSON.keys(); it.hasNext(); ) { + String key = it.next(); + Object value = spJSON.get(key); + if (value instanceof Boolean) { + editor.putBoolean(key, (Boolean) value); + } else if (value instanceof Float) { + editor.putFloat(key, (Float) value); + } else if (value instanceof Integer) { + editor.putInt(key, (Integer) value); + } else if (value instanceof Long) { + editor.putLong(key, (Long) value); + } else if (value instanceof String) { + editor.putString(key, (String) value); + } + } + editor.apply(); + Log.d(TAG, "Imported: " + jsonString); + Toast.makeText(context, "Preferences imported", Toast.LENGTH_SHORT).show(); + } catch (Exception e) { + Log.e(TAG, "Failed to import preferences", e); + Toast.makeText(context, "Failed to import preferences", Toast.LENGTH_SHORT).show(); + } + } +} diff --git a/app/src/main/res/layout/fragment_shared_preferences_io.xml b/app/src/main/res/layout/fragment_shared_preferences_io.xml new file mode 100644 index 00000000..58815cc3 --- /dev/null +++ b/app/src/main/res/layout/fragment_shared_preferences_io.xml @@ -0,0 +1,21 @@ + + + +