Use native XML parser for settings migration

This commit is contained in:
topjohnwu 2018-02-20 20:16:14 +08:00
parent 821dcaa7c7
commit 41f47acd76
2 changed files with 63 additions and 25 deletions

View File

@ -54,6 +54,5 @@ dependencies {
implementation 'com.jakewharton:butterknife:8.8.1' implementation 'com.jakewharton:butterknife:8.8.1'
implementation 'com.atlassian.commonmark:commonmark:0.10.0' implementation 'com.atlassian.commonmark:commonmark:0.10.0'
implementation 'org.kamranzafar:jtar:2.3' implementation 'org.kamranzafar:jtar:2.3'
implementation 'com.google.code.gson:gson:2.8.2'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
} }

View File

@ -19,10 +19,9 @@ import android.support.annotation.StringRes;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.util.Xml;
import android.widget.Toast; import android.widget.Toast;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.SplashActivity; import com.topjohnwu.magisk.SplashActivity;
@ -31,14 +30,18 @@ import com.topjohnwu.magisk.receivers.DownloadReceiver;
import com.topjohnwu.superuser.Shell; import com.topjohnwu.superuser.Shell;
import com.topjohnwu.superuser.ShellUtils; import com.topjohnwu.superuser.ShellUtils;
import com.topjohnwu.superuser.io.SuFile; import com.topjohnwu.superuser.io.SuFile;
import com.topjohnwu.superuser.io.SuFileInputStream;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
public class Utils { public class Utils {
@ -213,35 +216,71 @@ public class Utils {
} }
public static void dumpPrefs() { public static void dumpPrefs() {
Gson gson = new Gson(); MagiskManager mm = MagiskManager.get();
Map<String, ?> prefs = MagiskManager.get().prefs.getAll(); // Flush prefs to disk
prefs.remove("App Restrictions"); mm.prefs.edit().commit();
String json = gson.toJson(prefs, new TypeToken<Map<String, ?>>(){}.getType()); File xml = new File(mm.getFilesDir().getParent() + "/shared_prefs",
Shell.Sync.su(fmt("for usr in /data/user/*; do echo '%s' > ${usr}/%s; done", json, Const.MANAGER_CONFIGS)); mm.getPackageName() + "_preferences.xml");
Shell.Sync.su(fmt("for usr in /data/user/*; do cat %s > ${usr}/%s; done", xml, Const.MANAGER_CONFIGS));
} }
public static void loadPrefs() { public static void loadPrefs() {
SuFile config = new SuFile(fmt("/data/user/%d/%s", Const.USER_ID, Const.MANAGER_CONFIGS), true); SuFile config = new SuFile(fmt("/data/user/%d/%s", Const.USER_ID, Const.MANAGER_CONFIGS), true);
List<String> ret = Shell.Sync.su("cat " + config); if (config.exists()) {
if (ShellUtils.isValidOutput(ret)) { MagiskManager mm = MagiskManager.get();
SharedPreferences.Editor editor = MagiskManager.get().prefs.edit(); SharedPreferences.Editor editor = mm.prefs.edit();
String json = ret.get(0); try {
Gson gson = new Gson(); SuFileInputStream is = new SuFileInputStream(config);
Map<String, ?> prefMap = gson.fromJson(json, new TypeToken<Map<String, ?>>(){}.getType()); XmlPullParser parser = Xml.newPullParser();
editor.clear(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
for (Map.Entry<String, ?> entry : prefMap.entrySet()) { parser.setInput(is, "UTF-8");
Object value = entry.getValue(); parser.nextTag();
if (value instanceof String) { parser.require(XmlPullParser.START_TAG, null, "map");
editor.putString(entry.getKey(), (String) value); while (parser.next() != XmlPullParser.END_TAG) {
} else if (value instanceof Boolean) { if (parser.getEventType() != XmlPullParser.START_TAG)
editor.putBoolean(entry.getKey(), (boolean) value); continue;
} else if (value instanceof Number) { String key = parser.getAttributeValue(null, "name");
editor.putInt(entry.getKey(), ((Number) value).intValue()); String value = parser.getAttributeValue(null, "value");
switch (parser.getName()) {
case "string":
parser.require(XmlPullParser.START_TAG, null, "string");
editor.putString(key, parser.nextText());
parser.require(XmlPullParser.END_TAG, null, "string");
break;
case "boolean":
parser.require(XmlPullParser.START_TAG, null, "boolean");
editor.putBoolean(key, Boolean.parseBoolean(value));
parser.nextTag();
parser.require(XmlPullParser.END_TAG, null, "boolean");
break;
case "int":
parser.require(XmlPullParser.START_TAG, null, "int");
editor.putInt(key, Integer.parseInt(value));
parser.nextTag();
parser.require(XmlPullParser.END_TAG, null, "int");
break;
case "long":
parser.require(XmlPullParser.START_TAG, null, "long");
editor.putLong(key, Long.parseLong(value));
parser.nextTag();
parser.require(XmlPullParser.END_TAG, null, "long");
break;
case "float":
parser.require(XmlPullParser.START_TAG, null, "int");
editor.putFloat(key, Float.parseFloat(value));
parser.nextTag();
parser.require(XmlPullParser.END_TAG, null, "int");
break;
default:
parser.next();
} }
} }
} catch (IOException | XmlPullParserException e) {
e.printStackTrace();
}
editor.remove(Const.Key.ETAG_KEY); editor.remove(Const.Key.ETAG_KEY);
editor.apply(); editor.apply();
MagiskManager.get().loadConfig(); mm.loadConfig();
config.delete(); config.delete();
} }
} }