[Android] Add the user changed settings to the logs

Nicolas Pomepuy git at videolan.org
Wed Sep 8 06:52:31 UTC 2021


vlc-android | branch: master | Nicolas Pomepuy <nicolas at videolabs.io> | Tue Sep  7 09:15:04 2021 +0200| [ce93b882c6a186e95e754b4b9d0d63eb9a2efdb0] | committer: Nicolas Pomepuy

Add the user changed settings to the logs

> https://code.videolan.org/videolan/vlc-android/commit/ce93b882c6a186e95e754b4b9d0d63eb9a2efdb0
---

 .../src/org/videolan/vlc/DebugLogService.kt        | 12 +++
 .../vlc/gui/preferences/search/PreferenceParser.kt | 92 ++++++++++++++++++----
 2 files changed, 88 insertions(+), 16 deletions(-)

diff --git a/application/vlc-android/src/org/videolan/vlc/DebugLogService.kt b/application/vlc-android/src/org/videolan/vlc/DebugLogService.kt
index dd6bfc651..681a268a7 100644
--- a/application/vlc-android/src/org/videolan/vlc/DebugLogService.kt
+++ b/application/vlc-android/src/org/videolan/vlc/DebugLogService.kt
@@ -29,6 +29,7 @@ import android.content.Intent
 import android.content.ServiceConnection
 import android.os.*
 import android.text.format.DateFormat
+import android.util.Log
 import androidx.core.app.NotificationCompat
 import org.videolan.libvlc.util.AndroidUtil
 import org.videolan.resources.AndroidDevices
@@ -39,6 +40,7 @@ import org.videolan.tools.Logcat
 import org.videolan.tools.getContextWithLocale
 import org.videolan.vlc.gui.DebugLogActivity
 import org.videolan.vlc.gui.helpers.NotificationHelper
+import org.videolan.vlc.gui.preferences.search.PreferenceParser
 import java.io.*
 import java.util.*
 
@@ -176,7 +178,17 @@ class DebugLogService : Service(), Logcat.Callback, Runnable {
             output = OutputStreamWriter(fos)
             bw = BufferedWriter(output)
             synchronized(this) {
+                bw.write("____________________________\r\n")
+                bw.write("Useful info\r\n")
+                bw.write("____________________________\r\n")
                 bw.write("App version: ${BuildConfig.VLC_VERSION_CODE} / ${BuildConfig.VLC_VERSION_NAME}\r\n")
+                try {
+                    bw.write("Changed settings:\r\n${PreferenceParser.getChangedPrefsString(this)}\r\n")
+                } catch (e: Exception) {
+                    bw.write("Cannot retrieve changed settings\r\n")
+                    bw.write(Log.getStackTraceString(e))
+                }
+                bw.write("____________________________\r\n")
                 for (line in logList) {
                     bw.write(line)
                     bw.newLine()
diff --git a/application/vlc-android/src/org/videolan/vlc/gui/preferences/search/PreferenceParser.kt b/application/vlc-android/src/org/videolan/vlc/gui/preferences/search/PreferenceParser.kt
index 3bc575c3b..58c95ccfd 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/preferences/search/PreferenceParser.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/preferences/search/PreferenceParser.kt
@@ -26,17 +26,23 @@ package org.videolan.vlc.gui.preferences.search
 
 import android.content.Context
 import android.content.ContextWrapper
+import android.content.SharedPreferences
 import android.content.res.XmlResourceParser
 import android.os.Parcelable
-import android.util.Log
+import androidx.annotation.XmlRes
 import kotlinx.android.parcel.Parcelize
 import org.videolan.tools.Settings
 import org.videolan.tools.wrap
-import org.videolan.vlc.BuildConfig
 import org.videolan.vlc.R
 
 object PreferenceParser {
 
+    /**
+     * Parses all the preferences available in the app.
+     * @param context the context to be used to retrieve the preferences
+     *
+     * @return a list of [PreferenceItem]
+     */
     fun parsePreferences(context: Context): ArrayList<PreferenceItem> {
         val result = ArrayList<PreferenceItem>()
         arrayOf(R.xml.preferences, R.xml.preferences_adv, R.xml.preferences_audio, R.xml.preferences_casting, R.xml.preferences_perf, R.xml.preferences_subtitles, R.xml.preferences_ui, R.xml.preferences_video).forEach {
@@ -45,7 +51,59 @@ object PreferenceParser {
         return result
     }
 
-    private fun parsePreferences(context: Context, id: Int): ArrayList<PreferenceItem> {
+    /**
+     * Compares the preference list with the set settings to get the list of the changed settings by the user
+     * @param context the context to be used to retrieve the preferences
+     *
+     * @return a list of changed settings in the form a of pair of the key and the value
+     */
+    private fun getAllChangedPrefs(context: Context): ArrayList<Pair<String, Any>> {
+        val allPrefs = parsePreferences(context)
+        val allSettings = Settings.getInstance(context).all
+        val changedSettings = ArrayList<Pair<String, Any>>()
+        allPrefs.forEach { pref ->
+            allSettings.forEach { setting ->
+                if (pref.key == setting.key) {
+                    setting.value?.let {
+                        if (!isSame(it, pref.defaultValue)) changedSettings.add(Pair(pref.key, it))
+                    }
+                }
+            }
+        }
+        return changedSettings
+    }
+
+    /**
+     * Compares a [SharedPreferences] item value to a retrieved String from the preference parsing
+     * @param settingValue the found preference value
+     * @param defaultValue the defaultValue [String] found by parsing the pref xml
+     *
+     * @return true if values are considered to be the same
+     */
+    private fun isSame(settingValue: Any, defaultValue: String?) = when {
+        defaultValue == null -> false
+        settingValue is Boolean -> settingValue.toString() == defaultValue
+        else -> settingValue == defaultValue
+    }
+
+    /**
+     * Get a string describing the preferences changed by the user
+     * @param context the context to be used to retrieve the preferences
+     *
+     * @return a string of all the changed preferences
+     */
+    fun getChangedPrefsString(context: Context) = buildString {
+        getAllChangedPrefs(context).forEach { append("\t* ${it.first} -> ${it.second}\r\n") }
+    }
+
+    /**
+     * Parse a preference xml resource to get a list of [PreferenceItem]
+     * @param context the context to be used to retrieve the preferences
+     * @param id the xml resource id to parse
+     *
+     * @return all the parsed items in the form of a [PreferenceItem] list
+     */
+    private fun parsePreferences(context: Context, @XmlRes id: Int): ArrayList<PreferenceItem> {
         var category = ""
         var categoryEng = ""
         val result = ArrayList<PreferenceItem>()
@@ -69,10 +127,10 @@ object PreferenceParser {
                     val titleEng = getValue(englishContext, parser, namespace, "title")
                     var summary = getValue(context, parser, namespace, "summary")
                     var summaryEng = getValue(englishContext, parser, namespace, "summary")
+                    val defaultValue = getValue(context, parser, namespace, "defaultValue")
                     if (summary.contains("%s") && element == "ListPreference") {
                         //get the current value for the string substitution
                         try {
-                            val defaultValue = getValue(context, parser, namespace, "defaultValue")
                             val rawValue = Settings.getInstance(context).getString(key, defaultValue) ?: ""
                             val entriesId = parser.getAttributeResourceValue(namespace, "entries", -1)
                             val entryValuesId = parser.getAttributeResourceValue(namespace, "entryValues", -1)
@@ -82,7 +140,7 @@ object PreferenceParser {
                         } catch (e: Exception) {
                         }
                     }
-                    if (key.isNotBlank()) result.add(PreferenceItem(key, id, title, summary, titleEng, summaryEng, category, categoryEng))
+                    if (key.isNotBlank()) result.add(PreferenceItem(key, id, title, summary, titleEng, summaryEng, category, categoryEng, defaultValue))
                 }
             }
             eventType = parser.next()
@@ -90,6 +148,15 @@ object PreferenceParser {
         return result
     }
 
+    /**
+     * Get the value of an xml node
+     * @param context the context to be used to retrieve the value. This context can be localized in English to retrieve the strings
+     * @param parser the [XmlResourceParser] to use to parse the attributes
+     * @param namespace the namespace to use to parse the attributes
+     * @param node the node to be parsed
+     *
+     * @return the parsed value
+     */
     private fun getValue(context: Context, parser: XmlResourceParser, namespace: String, node: String): String {
         try {
             val titleResId = parser.getAttributeResourceValue(namespace, node, -1)
@@ -102,17 +169,10 @@ object PreferenceParser {
         }
         return ""
     }
-
-    private fun getSummary (context: Context, parser: XmlResourceParser, namespace: String, node: String, defaultValue:String, key:String):String {
-
-        val value = getValue(context, parser, namespace, node)
-        if (value.contains("%s")) if (BuildConfig.DEBUG) Log.d(this::class.java.simpleName, "Found string replacement for $key")
-        return if (value.contains("%s"))
-            value.replace("%s", Settings.getInstance(context).getString(key, defaultValue) ?: "")
-        else value
-
-    }
 }
 
+/**
+ * Object describing a [androidx.preference.Preference] with useful values to search / display them
+ */
 @Parcelize
-data class PreferenceItem(val key: String, val parentScreen: Int, val title: String, val summary: String, val titleEng:String, val summaryEng: String, val category: String, val categoryEng: String) : Parcelable
\ No newline at end of file
+data class PreferenceItem(val key: String, val parentScreen: Int, val title: String, val summary: String, val titleEng:String, val summaryEng: String, val category: String, val categoryEng: String, val defaultValue:String?) : Parcelable
\ No newline at end of file



More information about the Android mailing list