[app] Async improvements

This commit is contained in:
tehcneko 2021-08-25 14:37:24 +08:00 committed by vvb2060
parent eb61f84c67
commit 8d3e8e8ed2
10 changed files with 192 additions and 166 deletions

View File

@ -20,7 +20,6 @@
package org.lsposed.manager; package org.lsposed.manager;
import android.annotation.SuppressLint;
import android.app.Application; import android.app.Application;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@ -30,6 +29,7 @@ import android.system.Os;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
@ -47,6 +47,8 @@ import java.io.StringWriter;
import java.time.Instant; import java.time.Instant;
import java.time.ZoneOffset; import java.time.ZoneOffset;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import okhttp3.Cache; import okhttp3.Cache;
import okhttp3.Call; import okhttp3.Call;
@ -67,12 +69,11 @@ public class App extends Application {
} }
public static final String TAG = "LSPosedManager"; public static final String TAG = "LSPosedManager";
@SuppressLint("StaticFieldLeak")
private static App instance = null; private static App instance = null;
private static OkHttpClient okHttpClient; private static OkHttpClient okHttpClient;
private static Cache okHttpCache; private static Cache okHttpCache;
private SharedPreferences pref; private SharedPreferences pref;
private ExecutorService executorService;
public static App getInstance() { public static App getInstance() {
return instance; return instance;
@ -82,6 +83,10 @@ public class App extends Application {
return instance.pref; return instance.pref;
} }
public static ExecutorService getExecutorService() {
return instance.executorService;
}
private void setCrashReport() { private void setCrashReport() {
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> { Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
@ -116,6 +121,8 @@ public class App extends Application {
instance = this; instance = this;
executorService = Executors.newCachedThreadPool();
pref = PreferenceManager.getDefaultSharedPreferences(this); pref = PreferenceManager.getDefaultSharedPreferences(this);
if ("CN".equals(Locale.getDefault().getCountry())) { if ("CN".equals(Locale.getDefault().getCountry())) {
if (!pref.contains("doh")) { if (!pref.contains("doh")) {

View File

@ -255,7 +255,7 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
if (launchIntent != null) { if (launchIntent != null) {
ConfigManager.startActivityAsUserWithFeature(launchIntent, module.userId); ConfigManager.startActivityAsUserWithFeature(launchIntent, module.userId);
} else { } else {
fragment.makeSnackBar(R.string.module_no_ui, Snackbar.LENGTH_LONG); Snackbar.make(fragment.binding.snackbar, R.string.module_no_ui, Snackbar.LENGTH_LONG).show();
} }
return true; return true;
} else if (itemId == R.id.backup) { } else if (itemId == R.id.backup) {
@ -469,7 +469,7 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
checkedList.remove(appInfo.application); checkedList.remove(appInfo.application);
} }
if (!ConfigManager.setModuleScope(module.packageName, checkedList)) { if (!ConfigManager.setModuleScope(module.packageName, checkedList)) {
fragment.makeSnackBar(R.string.failed_to_save_scope_list, Snackbar.LENGTH_SHORT); Snackbar.make(fragment.binding.snackbar, R.string.failed_to_save_scope_list, Snackbar.LENGTH_SHORT).show();
if (!isChecked) { if (!isChecked) {
checkedList.add(appInfo.application); checkedList.add(appInfo.application);
} else { } else {

View File

@ -19,28 +19,25 @@
package org.lsposed.manager.ui.fragment; package org.lsposed.manager.ui.fragment;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Toast;
import androidx.activity.OnBackPressedCallback; import androidx.activity.OnBackPressedCallback;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.SearchView; import androidx.appcompat.widget.SearchView;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import org.lsposed.manager.BuildConfig; import org.lsposed.manager.App;
import org.lsposed.manager.R; import org.lsposed.manager.R;
import org.lsposed.manager.adapters.ScopeAdapter; import org.lsposed.manager.adapters.ScopeAdapter;
import org.lsposed.manager.databinding.FragmentAppListBinding; import org.lsposed.manager.databinding.FragmentAppListBinding;
@ -111,56 +108,35 @@ public class AppListFragment extends BaseFragment {
backupLauncher = registerForActivityResult(new ActivityResultContracts.CreateDocument(), backupLauncher = registerForActivityResult(new ActivityResultContracts.CreateDocument(),
uri -> { uri -> {
if (uri != null) { if (uri == null) return;
runAsync(() -> {
try { try {
// grantUriPermission might throw RemoteException on MIUI BackupUtils.backup(uri, modulePackageName);
requireActivity().grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); var text = App.getInstance().getString(R.string.settings_backup_failed2, e.getMessage());
} if (binding != null && isResumed()) {
AlertDialog alertDialog = new AlertDialog.Builder(requireActivity()) Snackbar.make(binding.snackbar, text, Snackbar.LENGTH_LONG).show();
.setCancelable(false) } else {
.setMessage(R.string.settings_backuping) Toast.makeText(App.getInstance(), text, Toast.LENGTH_LONG).show();
.show();
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
boolean success = BackupUtils.backup(requireActivity(), uri, modulePackageName);
try {
requireActivity().runOnUiThread(() -> {
alertDialog.dismiss();
makeSnackBar(success ? R.string.settings_backup_success : R.string.settings_backup_failed, Snackbar.LENGTH_SHORT);
});
} catch (Exception e) {
e.printStackTrace();
} }
}); }
} });
}); });
restoreLauncher = registerForActivityResult(new ActivityResultContracts.OpenDocument(), restoreLauncher = registerForActivityResult(new ActivityResultContracts.OpenDocument(),
uri -> { uri -> {
if (uri != null) { if (uri == null) return;
runAsync(() -> {
try { try {
// grantUriPermission might throw RemoteException on MIUI BackupUtils.restore(uri, modulePackageName);
requireActivity().grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); var text = App.getInstance().getString(R.string.settings_restore_failed2, e.getMessage());
} if (binding != null && isResumed()) {
AlertDialog alertDialog = new AlertDialog.Builder(requireActivity()) Snackbar.make(binding.snackbar, text, Snackbar.LENGTH_LONG).show();
.setCancelable(false) } else {
.setMessage(R.string.settings_restoring) Toast.makeText(App.getInstance(), text, Toast.LENGTH_LONG).show();
.show();
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
boolean success = BackupUtils.restore(requireActivity(), uri, modulePackageName);
try {
requireActivity().runOnUiThread(() -> {
alertDialog.dismiss();
makeSnackBar(success ? R.string.settings_restore_success : R.string.settings_restore_failed, Snackbar.LENGTH_SHORT);
scopeAdapter.refresh(false);
});
} catch (Exception e) {
e.printStackTrace();
} }
}); }
} });
}); });
requireActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) { requireActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@ -207,12 +183,4 @@ public class AppListFragment extends BaseFragment {
} }
return super.onContextItemSelected(item); return super.onContextItemSelected(item);
} }
public void makeSnackBar(String text, @Snackbar.Duration int duration) {
Snackbar.make(binding.snackbar, text, duration).show();
}
public void makeSnackBar(@StringRes int text, @Snackbar.Duration int duration) {
Snackbar.make(binding.snackbar, text, duration).show();
}
} }

View File

@ -26,8 +26,11 @@ import androidx.fragment.app.Fragment;
import androidx.navigation.NavController; import androidx.navigation.NavController;
import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.fragment.NavHostFragment;
import org.lsposed.manager.App;
import org.lsposed.manager.R; import org.lsposed.manager.R;
import java.util.concurrent.Future;
public class BaseFragment extends Fragment { public class BaseFragment extends Fragment {
public void navigateUp() { public void navigateUp() {
getNavController().navigateUp(); getNavController().navigateUp();
@ -59,4 +62,8 @@ public class BaseFragment extends Fragment {
onPrepareOptionsMenu(toolbar.getMenu()); onPrepareOptionsMenu(toolbar.getMenu());
} }
} }
public Future<?> runAsync(Runnable runnable) {
return App.getExecutorService().submit(runnable);
}
} }

View File

@ -34,7 +34,6 @@ import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatDialogFragment; import androidx.appcompat.app.AppCompatDialogFragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Lifecycle;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
@ -93,7 +92,7 @@ public class CompileDialogFragment extends AppCompatDialogFragment {
appInfo = arguments.getParcelable(KEY_APP_INFO); appInfo = arguments.getParcelable(KEY_APP_INFO);
String[] command = COMPILE_RESET_COMMAND; String[] command = COMPILE_RESET_COMMAND;
command[6] = appInfo.packageName; command[6] = appInfo.packageName;
new CompileTask(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, command); new CompileTask(this).executeOnExecutor(App.getExecutorService(), command);
} else { } else {
dismissAllowingStateLoss(); dismissAllowingStateLoss();
} }
@ -156,8 +155,8 @@ public class CompileDialogFragment extends AppCompatDialogFragment {
if (fragment != null) { if (fragment != null) {
fragment.dismissAllowingStateLoss(); fragment.dismissAllowingStateLoss();
AppListFragment appListFragment = (AppListFragment) fragment.getParentFragment(); AppListFragment appListFragment = (AppListFragment) fragment.getParentFragment();
if (appListFragment != null && appListFragment.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)) { if (appListFragment != null && appListFragment.binding != null && appListFragment.isResumed()) {
appListFragment.makeSnackBar(text, Snackbar.LENGTH_LONG); Snackbar.make(appListFragment.binding.snackbar, text, Snackbar.LENGTH_LONG).show();
return; return;
} }
} }

View File

@ -34,6 +34,7 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
@ -46,6 +47,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayout;
import org.lsposed.manager.App;
import org.lsposed.manager.ConfigManager; import org.lsposed.manager.ConfigManager;
import org.lsposed.manager.R; import org.lsposed.manager.R;
import org.lsposed.manager.databinding.FragmentLogsBinding; import org.lsposed.manager.databinding.FragmentLogsBinding;
@ -80,15 +82,18 @@ public class LogsFragment extends BaseFragment {
new ActivityResultContracts.CreateDocument(), new ActivityResultContracts.CreateDocument(),
uri -> { uri -> {
if (uri == null) return; if (uri == null) return;
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { runAsync(() -> {
try (var os = new ZipOutputStream(requireContext().getContentResolver().openOutputStream(uri))) { try (var os = new ZipOutputStream(requireContext().getContentResolver().openOutputStream(uri))) {
os.setLevel(Deflater.BEST_COMPRESSION); os.setLevel(Deflater.BEST_COMPRESSION);
zipLogs(os); zipLogs(os);
os.finish(); os.finish();
} catch (IOException e) { } catch (IOException e) {
var str = getResources().getString(R.string.logs_save_failed); var text = App.getInstance().getString(R.string.logs_save_failed2, e.getMessage());
Snackbar.make(binding.snackbar, str + "\n" + e.getMessage(), if (binding != null && isResumed()) {
Snackbar.LENGTH_LONG).show(); Snackbar.make(binding.snackbar, text, Snackbar.LENGTH_LONG).show();
} else {
Toast.makeText(App.getInstance(), text, Toast.LENGTH_LONG).show();
}
} }
}); });
}); });

View File

@ -19,21 +19,20 @@
package org.lsposed.manager.ui.fragment; package org.lsposed.manager.ui.fragment;
import android.content.Intent; import android.content.Context;
import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.SwitchPreference; import androidx.preference.SwitchPreference;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@ -42,7 +41,6 @@ import com.google.android.material.snackbar.Snackbar;
import com.takisoft.preferencex.PreferenceFragmentCompat; import com.takisoft.preferencex.PreferenceFragmentCompat;
import org.lsposed.manager.App; import org.lsposed.manager.App;
import org.lsposed.manager.BuildConfig;
import org.lsposed.manager.ConfigManager; import org.lsposed.manager.ConfigManager;
import org.lsposed.manager.R; import org.lsposed.manager.R;
import org.lsposed.manager.databinding.FragmentSettingsBinding; import org.lsposed.manager.databinding.FragmentSettingsBinding;
@ -82,61 +80,55 @@ public class SettingsFragment extends BaseFragment {
} }
public static class PreferenceFragment extends PreferenceFragmentCompat { public static class PreferenceFragment extends PreferenceFragmentCompat {
private SettingsFragment parentFragment;
ActivityResultLauncher<String> backupLauncher = registerForActivityResult(new ActivityResultContracts.CreateDocument(), ActivityResultLauncher<String> backupLauncher = registerForActivityResult(new ActivityResultContracts.CreateDocument(),
uri -> { uri -> {
if (uri != null) { if (uri == null || parentFragment == null) return;
parentFragment.runAsync(() -> {
try { try {
// grantUriPermission might throw RemoteException on MIUI BackupUtils.backup(uri);
requireActivity().grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); var text = App.getInstance().getString(R.string.settings_backup_failed2, e.getMessage());
} if (parentFragment != null && parentFragment.binding != null && isResumed()) {
AlertDialog alertDialog = new AlertDialog.Builder(requireActivity()) Snackbar.make(parentFragment.binding.snackbar, text, Snackbar.LENGTH_LONG).show();
.setCancelable(false) } else {
.setMessage(R.string.settings_backuping) Toast.makeText(App.getInstance(), text, Toast.LENGTH_LONG).show();
.show();
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
boolean success = BackupUtils.backup(requireContext(), uri);
try {
SettingsFragment fragment = (SettingsFragment) getParentFragment();
requireActivity().runOnUiThread(() -> {
alertDialog.dismiss();
fragment.makeSnackBar(success ? R.string.settings_backup_success : R.string.settings_backup_failed, Snackbar.LENGTH_SHORT);
});
} catch (Exception e) {
e.printStackTrace();
} }
}); }
} });
}); });
ActivityResultLauncher<String[]> restoreLauncher = registerForActivityResult(new ActivityResultContracts.OpenDocument(), ActivityResultLauncher<String[]> restoreLauncher = registerForActivityResult(new ActivityResultContracts.OpenDocument(),
uri -> { uri -> {
if (uri != null) { if (uri == null || parentFragment == null) return;
parentFragment.runAsync(() -> {
try { try {
// grantUriPermission might throw RemoteException on MIUI BackupUtils.restore(uri);
requireActivity().grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); var text = App.getInstance().getString(R.string.settings_restore_failed2, e.getMessage());
} if (parentFragment != null && parentFragment.binding != null && isResumed()) {
AlertDialog alertDialog = new AlertDialog.Builder(requireActivity()) Snackbar.make(parentFragment.binding.snackbar, text, Snackbar.LENGTH_LONG).show();
.setCancelable(false) } else {
.setMessage(R.string.settings_restoring) Toast.makeText(App.getInstance(), text, Toast.LENGTH_LONG).show();
.show();
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
boolean success = BackupUtils.restore(requireContext(), uri);
try {
SettingsFragment fragment = (SettingsFragment) getParentFragment();
requireActivity().runOnUiThread(() -> {
alertDialog.dismiss();
fragment.makeSnackBar(success ? R.string.settings_restore_success : R.string.settings_restore_failed, Snackbar.LENGTH_SHORT);
});
} catch (Exception e) {
e.printStackTrace();
} }
}); }
} });
}); });
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
parentFragment = (SettingsFragment) requireParentFragment();
}
@Override
public void onDetach() {
super.onDetach();
parentFragment = null;
}
@Override @Override
public void onCreatePreferencesFix(Bundle savedInstanceState, String rootKey) { public void onCreatePreferencesFix(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.prefs); addPreferencesFromResource(R.xml.prefs);

View File

@ -20,16 +20,16 @@
package org.lsposed.manager.util; package org.lsposed.manager.util;
import android.content.Context;
import android.net.Uri; import android.net.Uri;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.lsposed.manager.App;
import org.lsposed.manager.ConfigManager; import org.lsposed.manager.ConfigManager;
import org.lsposed.manager.adapters.ScopeAdapter; import org.lsposed.manager.adapters.ScopeAdapter;
import java.io.InputStream; import java.io.IOException;
import java.io.OutputStream;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
@ -38,55 +38,45 @@ import java.util.zip.GZIPOutputStream;
public class BackupUtils { public class BackupUtils {
private static final int VERSION = 2; private static final int VERSION = 2;
public static boolean backup(Context context, Uri uri) { public static void backup(Uri uri) throws JSONException, IOException {
return backup(context, uri, null); backup(uri, null);
} }
public static boolean backup(Context context, Uri uri, String packageName) { public static void backup(Uri uri, String packageName) throws IOException, JSONException {
try { JSONObject rootObject = new JSONObject();
JSONObject rootObject = new JSONObject(); rootObject.put("version", VERSION);
rootObject.put("version", VERSION); JSONArray modulesArray = new JSONArray();
JSONArray modulesArray = new JSONArray(); var modules = ModuleUtil.getInstance().getModules();
var modules = ModuleUtil.getInstance().getModules(); for (ModuleUtil.InstalledModule module : modules.values()) {
for (ModuleUtil.InstalledModule module : modules.values()) { if (packageName != null && !module.packageName.equals(packageName)) {
if (packageName != null && !module.packageName.equals(packageName)) { continue;
continue;
}
JSONObject moduleObject = new JSONObject();
moduleObject.put("enable", ModuleUtil.getInstance().isModuleEnabled(module.packageName));
moduleObject.put("package", module.packageName);
List<ScopeAdapter.ApplicationWithEquals> scope = ConfigManager.getModuleScope(module.packageName);
JSONArray scopeArray = new JSONArray();
for (ScopeAdapter.ApplicationWithEquals s : scope) {
JSONObject app = new JSONObject();
app.put("package", s.packageName);
app.put("userId", s.userId);
scopeArray.put(app);
}
moduleObject.put("scope", scopeArray);
modulesArray.put(moduleObject);
} }
rootObject.put("modules", modulesArray); JSONObject moduleObject = new JSONObject();
OutputStream outputStream = context.getContentResolver().openOutputStream(uri); moduleObject.put("enable", ModuleUtil.getInstance().isModuleEnabled(module.packageName));
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream); moduleObject.put("package", module.packageName);
gzipOutputStream.write(rootObject.toString().getBytes()); List<ScopeAdapter.ApplicationWithEquals> scope = ConfigManager.getModuleScope(module.packageName);
gzipOutputStream.close(); JSONArray scopeArray = new JSONArray();
outputStream.close(); for (ScopeAdapter.ApplicationWithEquals s : scope) {
return true; JSONObject app = new JSONObject();
} catch (Exception e) { app.put("package", s.packageName);
e.printStackTrace(); app.put("userId", s.userId);
scopeArray.put(app);
}
moduleObject.put("scope", scopeArray);
modulesArray.put(moduleObject);
}
rootObject.put("modules", modulesArray);
try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(App.getInstance().getContentResolver().openOutputStream(uri))) {
gzipOutputStream.write(rootObject.toString().getBytes());
} }
return false;
} }
public static boolean restore(Context context, Uri uri) { public static void restore(Uri uri) throws JSONException, IOException {
return restore(context, uri, null); restore(uri, null);
} }
public static boolean restore(Context context, Uri uri, String packageName) { public static void restore(Uri uri, String packageName) throws IOException, JSONException {
try { try (GZIPInputStream gzipInputStream = new GZIPInputStream(App.getInstance().getContentResolver().openInputStream(uri), 32)) {
InputStream inputStream = context.getContentResolver().openInputStream(uri);
GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream, 32);
StringBuilder string = new StringBuilder(); StringBuilder string = new StringBuilder();
byte[] data = new byte[32]; byte[] data = new byte[32];
int bytesRead; int bytesRead;
@ -94,7 +84,6 @@ public class BackupUtils {
string.append(new String(data, 0, bytesRead)); string.append(new String(data, 0, bytesRead));
} }
gzipInputStream.close(); gzipInputStream.close();
inputStream.close();
JSONObject rootObject = new JSONObject(string.toString()); JSONObject rootObject = new JSONObject(string.toString());
int version = rootObject.getInt("version"); int version = rootObject.getInt("version");
if (version == VERSION || version == 1) { if (version == VERSION || version == 1) {
@ -122,12 +111,8 @@ public class BackupUtils {
} }
} }
} else { } else {
return false; throw new IllegalArgumentException("Unknown backup file version");
} }
return true;
} catch (Exception e) {
e.printStackTrace();
} }
return false;
} }
} }

View File

@ -0,0 +1,61 @@
package org.lsposed.manager.util;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeProvider;
public class EmptyAccessibilityDelegate extends View.AccessibilityDelegate {
@Override
public void sendAccessibilityEvent(View host, int eventType) {
}
@Override
public boolean performAccessibilityAction(View host, int action, Bundle args) {
return true;
}
@Override
public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
}
@Override
public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
return true;
}
@Override
public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
}
@Override
public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
}
@Override
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
}
@Override
public void addExtraDataToAccessibilityNodeInfo(View host, AccessibilityNodeInfo info, String extraDataKey, Bundle arguments) {
}
@Override
public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event) {
return true;
}
@Override
public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
return null;
}
}

View File

@ -62,7 +62,7 @@
<string name="menuSaveToSd">Save</string> <string name="menuSaveToSd">Save</string>
<string name="nav_item_logs_lsp">LSPosed Logs</string> <string name="nav_item_logs_lsp">LSPosed Logs</string>
<string name="nav_item_logs_module">Modules Logs</string> <string name="nav_item_logs_module">Modules Logs</string>
<string name="logs_save_failed">Failed to save:</string> <string name="logs_save_failed2">Failed to save:\n%s</string>
<string name="menuClearLog">Clear log now</string> <string name="menuClearLog">Clear log now</string>
<string name="logs_cleared">Log successfully cleared.</string> <string name="logs_cleared">Log successfully cleared.</string>
<string name="scroll_top">Scroll to top</string> <string name="scroll_top">Scroll to top</string>
@ -72,6 +72,8 @@
<string name="menuReload">Reload</string> <string name="menuReload">Reload</string>
<string name="logs_clear_failed_2">Failed to clear the log</string> <string name="logs_clear_failed_2">Failed to clear the log</string>
<string name="verbose_log_not_avaliable">Verbose log is not available, if you just enabled it without reboot, try again after reboot.</string> <string name="verbose_log_not_avaliable">Verbose log is not available, if you just enabled it without reboot, try again after reboot.</string>
<string name="logs_saving">Saving logs…</string>
<string name="logs_saved">Logs saved!</string>
<!-- Notification --> <!-- Notification -->
<string name="module_is_not_activated_yet">Xposed module is not activated yet</string> <string name="module_is_not_activated_yet">Xposed module is not activated yet</string>
@ -155,11 +157,11 @@
<string name="settings_backup">Backup</string> <string name="settings_backup">Backup</string>
<string name="settings_backuping">Backing up…</string> <string name="settings_backuping">Backing up…</string>
<string name="settings_backup_success">Backup finished!</string> <string name="settings_backup_success">Backup finished!</string>
<string name="settings_backup_failed">Failed to backup</string> <string name="settings_backup_failed2">Failed to backup:\n%s</string>
<string name="settings_restore">Restore</string> <string name="settings_restore">Restore</string>
<string name="settings_restoring">Restoring…</string> <string name="settings_restoring">Restoring…</string>
<string name="settings_restore_success">Restore finished!</string> <string name="settings_restore_success">Restore finished!</string>
<string name="settings_restore_failed">Failed to restore</string> <string name="settings_restore_failed2">Failed to restore:\n%s</string>
<string name="group_network">Network</string> <string name="group_network">Network</string>
<string name="dns_over_http">DNS over HTTPS</string> <string name="dns_over_http">DNS over HTTPS</string>
<string name="dns_over_http_summary">Workaround DNS poisoning in some nations</string> <string name="dns_over_http_summary">Workaround DNS poisoning in some nations</string>