diff --git a/app/src/main/java/ru/vtosters/lite/deviceinfo/OEMDetector.java b/app/src/main/java/ru/vtosters/lite/deviceinfo/OEMDetector.java index 667474e4b..8290fa664 100644 --- a/app/src/main/java/ru/vtosters/lite/deviceinfo/OEMDetector.java +++ b/app/src/main/java/ru/vtosters/lite/deviceinfo/OEMDetector.java @@ -25,8 +25,7 @@ public class OEMDetector { try { getPropMtd = ReflectionUtils.findMethod(Class.forName("android.os.SystemProperties"), "get", String.class); semPlatformIntField = ReflectionUtils.findField(Build.VERSION.class, "SEM_PLATFORM_INT"); - } catch (NoSuchFieldException | ClassNotFoundException | NoSuchMethodException e) { - e.printStackTrace(); + } catch (NoSuchFieldException | ClassNotFoundException | NoSuchMethodException ignored) { } } diff --git a/app/src/main/java/ru/vtosters/lite/hooks/DeviceInfoHook.java b/app/src/main/java/ru/vtosters/lite/hooks/DeviceInfoHook.java index 7667b6661..1aee0f646 100644 --- a/app/src/main/java/ru/vtosters/lite/hooks/DeviceInfoHook.java +++ b/app/src/main/java/ru/vtosters/lite/hooks/DeviceInfoHook.java @@ -40,7 +40,7 @@ public class DeviceInfoHook { } @SuppressLint("HardwareIds") - private static String findDeviceId() { - return Settings.Secure.getString(getGlobalContext().getContentResolver(), "android_id"); + public static String findDeviceId() { + return Settings.Secure.getString(getGlobalContext().getContentResolver(), Settings.Secure.ANDROID_ID); } } diff --git a/app/src/main/java/ru/vtosters/lite/hooks/ProxyHook.java b/app/src/main/java/ru/vtosters/lite/hooks/ProxyHook.java index c79cf94a0..1c33bfb4b 100644 --- a/app/src/main/java/ru/vtosters/lite/hooks/ProxyHook.java +++ b/app/src/main/java/ru/vtosters/lite/hooks/ProxyHook.java @@ -10,7 +10,9 @@ import androidx.appcompat.view.ContextThemeWrapper; import com.vk.auth.ui.VkAuthTextView; import com.vk.core.dialogs.alert.VkAlertDialog; import com.vtosters.lite.R; +import ru.vtosters.lite.ui.fragments.DataSettingsFragment; import ru.vtosters.lite.ui.fragments.ProxySettingsFragment; +import ru.vtosters.lite.utils.AndroidUtils; import ru.vtosters.lite.utils.NavigatorUtils; import ru.vtosters.lite.utils.Preferences; @@ -21,9 +23,13 @@ import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr; public class ProxyHook { public static void hookAuth(View v) { - VkAuthTextView button = (VkAuthTextView) v; + VkAuthTextView button = v.findViewById(AndroidUtils.getIdentifier("already_have_account", "id")); button.setText(R.string.proxy_setup); button.setOnClickListener(v1 -> callProxyDialog(v1.getContext())); + + VkAuthTextView recoverAccounts = v.findViewById(AndroidUtils.getIdentifier("account_backup_view", "id")); + recoverAccounts.setText("Восстановить аккаунты"); + recoverAccounts.setOnClickListener(v1 -> NavigatorUtils.switchFragment(v.getContext(), DataSettingsFragment.class)); } @SuppressLint("SetTextI18n") diff --git a/app/src/main/java/ru/vtosters/lite/ui/components/BackupManager.java b/app/src/main/java/ru/vtosters/lite/ui/components/BackupManager.java index aa61d75f1..61385b34e 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/components/BackupManager.java +++ b/app/src/main/java/ru/vtosters/lite/ui/components/BackupManager.java @@ -80,17 +80,6 @@ public class BackupManager { } } - public static String[] getBackupsNames() { - var arr = sBackupDir.list((dir, name) -> { - return name.endsWith(".xml"); - }); - if (arr == null) return new String[0]; - for (int i = 0; i < arr.length; i++) { - arr[i] = arr[i].replace(".xml", ""); - } - return arr; - } - public static String getPrefContent(String filename) throws IOException { File prefsDir = new File(getGlobalContext().getFilesDir().getParentFile(), "shared_prefs"); if (!prefsDir.exists()) @@ -99,9 +88,9 @@ public class BackupManager { return IOUtils.readAllLines(pref); } - public static void restoreBackup(String backupName) throws IOException { + public static void restoreBackup(String path) throws IOException { SharedPreferences.Editor editor = getPrefs().edit(); - File pref = new File(sBackupDir, backupName + ".xml"); + File pref = new File(path); Scanner scanner = new Scanner(IOUtils.readAllLines(pref)); while (scanner.hasNextLine()) { String line = scanner.nextLine().trim(); diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/DataSettingsFragment.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/DataSettingsFragment.java new file mode 100644 index 000000000..4cb0e3380 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/DataSettingsFragment.java @@ -0,0 +1,175 @@ +package ru.vtosters.lite.ui.fragments; + +import android.app.Activity; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.view.View; +import android.view.WindowInsetsController; +import android.widget.Toast; +import com.vk.core.dialogs.alert.VkAlertDialog; +import ru.vtosters.lite.ui.PreferenceFragmentUtils; +import ru.vtosters.lite.ui.components.BackupManager; +import ru.vtosters.lite.utils.*; + +import java.io.IOException; + +public class DataSettingsFragment extends TrackedMaterialPreferenceToolbarFragment { + private static final int RECOVER_ACCOUNTS = 2; + private static final int RECOVER_SETTINGS = 1; + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (resultCode != Activity.RESULT_OK) return; + + switch (requestCode) { + case RECOVER_ACCOUNTS -> VKAccountDB.saveDatabase(data.getData()); + case RECOVER_SETTINGS -> { + try { + BackupManager.restoreBackup(AndroidUtils.getRealPathFromURI(data.getData())); + LifecycleUtils.restartApplicationWithTimer(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + @Override + public void onCreate(Bundle bundle) { + super.onCreate(bundle); + addPreferencesFromResource(com.vtosters.lite.R.xml.empty); + + requireActivity().getWindow().setStatusBarColor(ThemesUtils.getBackgroundContent()); + requireActivity().getWindow().setNavigationBarColor(ThemesUtils.getBackgroundContent()); + + if (!ThemesUtils.isDarkTheme()) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + requireActivity().getWindow().getInsetsController().setSystemBarsAppearance(WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS, WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS); + } else { + requireActivity().getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } + + PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), "Аккаунты"); + + PreferenceFragmentUtils.addPreference( + getPreferenceScreen(), + "", + "Сохранить аккаунты", + "", + null, + preference -> { + VKAccountDB.saveData(); + return false; + } + ).setVisible(AccountManagerUtils.isLogin()); + + PreferenceFragmentUtils.addPreference( + getPreferenceScreen(), + "", + "Восстановить аккаунты", + "", + null, + preference -> { + startActivityForResult(new Intent(Intent.ACTION_OPEN_DOCUMENT).addCategory(Intent.CATEGORY_OPENABLE).setType("application/*"), RECOVER_ACCOUNTS); + return false; + } + ); + + PreferenceFragmentUtils.addPreference( + getPreferenceScreen(), + "", + "Сбросить все аккаунты", + "", + null, + preference -> { + VKAccountDB.resetData(); + return false; + } + ).setVisible(AccountManagerUtils.isLogin()); + + PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), "Настройки"); + + PreferenceFragmentUtils.addPreference( + getPreferenceScreen(), + "", + "Сохранить настройки", + "", + null, + preference -> { + BackupManager.backupSettings(); + return false; + } + ); + + PreferenceFragmentUtils.addPreference( + getPreferenceScreen(), + "", + "Сохранить данные об онлайне", + "", + null, + preference -> { + try { + BackupManager.backupOnlines(); + } catch (IOException e) { + Toast.makeText(getContext(), requireContext().getString(com.vtosters.lite.R.string.no_data_to_backup), Toast.LENGTH_SHORT).show(); + } + return false; + } + ); + + PreferenceFragmentUtils.addPreference( + getPreferenceScreen(), + "", + "Восстановить настройки", + "", + null, + preference -> { + startActivityForResult(new Intent(Intent.ACTION_OPEN_DOCUMENT).setType("text/xml"), RECOVER_SETTINGS); + return false; + } + ); + + PreferenceFragmentUtils.addPreference( + getPreferenceScreen(), + "", + "Сбросить все настройки", + "", + null, + preference -> { + new VkAlertDialog.Builder(requireContext()) + .setTitle(requireContext().getString(com.vtosters.lite.R.string.warning)) + .setMessage(requireContext().getString(com.vtosters.lite.R.string.settings_reset_confirm)) + .setCancelable(false) + .setPositiveButton(requireContext().getString(com.vtosters.lite.R.string.yes), (dialogInterface, i) -> { + BackupManager.deletePrefs(); + LifecycleUtils.restartApplication(); + }) + .setNegativeButton(requireContext().getString(com.vtosters.lite.R.string.cancel), (dialogInterface, i) -> dialogInterface.dismiss()) + .show(); + return false; + } + ); + + PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), "Прочее"); + + PreferenceFragmentUtils.addMaterialSwitchPreference( + getPreferenceScreen(), + "analyticsDisabled", + "Отключить сбор данных", + "Сбор данных о падениях приложения помогает нам улучшать приложение\n\nОтключение сбора логов падений заставит грустить бедных разработчиков", + null, + false, + (preference, o) -> { + Preferences.getPreferences().edit().putBoolean("analyticsDisabled", (boolean) o).apply(); + LifecycleUtils.restartApplicationWithTimer(); + return true; + } + ); + + findPreference("analyticsDisabled").setVisible(Preferences.isValidSignature()); + } +} diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/OtherFragment.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/OtherFragment.java index 99721ae5c..9fc343e9e 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/fragments/OtherFragment.java +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/OtherFragment.java @@ -1,38 +1,16 @@ package ru.vtosters.lite.ui.fragments; -import static android.widget.Toast.LENGTH_LONG; -import static android.widget.Toast.LENGTH_SHORT; -import static ru.vtosters.lite.ui.components.BackupManager.backupOnlines; -import static ru.vtosters.lite.ui.components.BackupManager.backupSettings; -import static ru.vtosters.lite.ui.components.BackupManager.deletePrefs; -import static ru.vtosters.lite.ui.components.BackupManager.restoreBackup; -import static ru.vtosters.lite.utils.AccountManagerUtils.getUserToken; -import static ru.vtosters.lite.utils.AndroidUtils.dp2px; -import static ru.vtosters.lite.utils.AndroidUtils.sendToast; -import static ru.vtosters.lite.utils.LifecycleUtils.restartApplication; -import static ru.vtosters.lite.utils.LifecycleUtils.restartApplicationWithTimer; -import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr; - import android.annotation.SuppressLint; import android.app.Activity; -import android.content.ClipData; -import android.content.ClipboardManager; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; +import android.content.*; import android.os.Bundle; import android.util.TypedValue; -import android.view.View; -import android.view.ViewGroup; import android.webkit.WebView; -import android.widget.ArrayAdapter; import android.widget.RadioButton; import android.widget.RadioGroup; -import android.widget.TextView; import android.widget.Toast; - import androidx.appcompat.view.ContextThemeWrapper; - +import b.h.g.m.FileUtils; import com.vk.auth.api.VKAccount; import com.vk.core.dialogs.alert.VkAlertDialog; import com.vk.core.util.ToastUtils; @@ -48,24 +26,14 @@ import com.vk.stickers.Stickers; import com.vtosters.lite.R; import com.vtosters.lite.auth.VKAccountManager; import com.vtosters.lite.im.ImEngineProvider; - -import java.io.IOException; - -import b.h.g.m.FileUtils; import ru.vtosters.lite.deviceinfo.DeviceInfoCollector; import ru.vtosters.lite.hooks.SwitchHook; import ru.vtosters.lite.ssfs.UsersList; import ru.vtosters.lite.ui.activities.VKAdminTokenActivity; -import ru.vtosters.lite.ui.components.BackupManager; -import ru.vtosters.lite.utils.AccountManagerUtils; -import ru.vtosters.lite.utils.AndroidUtils; -import ru.vtosters.lite.utils.NavigatorUtils; -import ru.vtosters.lite.utils.Preferences; -import ru.vtosters.lite.utils.VTVerifications; +import ru.vtosters.lite.utils.*; public class OtherFragment extends TrackedMaterialPreferenceToolbarFragment { private static final int VK_ADMIN_TOKEN_REQUEST_CODE = 1; - @Override public void onCreate(Bundle bundle) { super.onCreate(bundle); @@ -77,12 +45,12 @@ public class OtherFragment extends TrackedMaterialPreferenceToolbarFragment { public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); + if (resultCode != Activity.RESULT_OK) return; + if (requestCode == VK_ADMIN_TOKEN_REQUEST_CODE) { - if (resultCode == Activity.RESULT_OK) { - String token = data.getStringExtra("token"); - Preferences.getPreferences().edit().putString("vk_admin_token", token).apply(); - Toast.makeText(getContext(), requireContext().getString(R.string.token_saved), LENGTH_SHORT).show(); - } + String token = data.getStringExtra("token"); + Preferences.getPreferences().edit().putString("vk_admin_token", token).apply(); + Toast.makeText(getContext(), requireContext().getString(R.string.token_saved), Toast.LENGTH_SHORT).show(); } } @@ -107,21 +75,21 @@ public class OtherFragment extends TrackedMaterialPreferenceToolbarFragment { }); findPreference("tokencopy").setOnPreferenceClickListener(preference -> { - copyText(getUserToken()); + copyText(AccountManagerUtils.getUserToken()); - Toast.makeText(requireContext(), requireContext().getString(R.string.copybtn), LENGTH_SHORT).show(); + Toast.makeText(requireContext(), requireContext().getString(R.string.copybtn), Toast.LENGTH_SHORT).show(); ToastUtils.a(requireContext().getString(R.string.tokenwarning)); return true; }); findPreference("copydebuginfo").setOnPreferenceClickListener(preference -> { copyText(new DeviceInfoCollector().collect().forLogging()); - Toast.makeText(requireContext(), AndroidUtils.getString("device_info_copied"), LENGTH_SHORT).show(); + Toast.makeText(requireContext(), AndroidUtils.getString("device_info_copied"), Toast.LENGTH_SHORT).show(); return true; }); findPreference("applicationrestart").setOnPreferenceClickListener(preference -> { - restartApplication(); + LifecycleUtils.restartApplication(); return true; }); @@ -146,12 +114,17 @@ public class OtherFragment extends TrackedMaterialPreferenceToolbarFragment { return true; }); + findPreference("datasettings").setOnPreferenceClickListener(preference -> { + NavigatorUtils.switchFragment(requireContext(), DataSettingsFragment.class); + return true; + }); + findPreference("dialogrecomm").setVisible(!Preferences.hasVerification()); findPreference("updateverifdata").setOnPreferenceClickListener(preference -> { UsersList.getUsersList(); VTVerifications.load(requireContext()); - sendToast(AndroidUtils.getString("data_updated")); + AndroidUtils.sendToast(AndroidUtils.getString("data_updated")); return true; }); @@ -168,53 +141,6 @@ public class OtherFragment extends TrackedMaterialPreferenceToolbarFragment { case "5gb" -> findPreference("autoclearcache").setSummary(requireContext().getString(R.string.cache_5gb)); } - findPreference("deleteprefs").setOnPreferenceClickListener(preference -> { - delprefs(getContext()); - return true; - }); - - findPreference("saveonlines").setOnPreferenceClickListener(preference -> { - try { - backupOnlines(); - } catch (IOException e) { - Toast.makeText(getContext(), requireContext().getString(R.string.no_data_to_backup), LENGTH_SHORT).show(); - } - - return true; - }); - - findPreference("saveprefs").setOnPreferenceClickListener(preference -> { - backupSettings(); - - return false; - }); - findPreference("restoreprefs").setOnPreferenceClickListener(preference -> { - var arr = BackupManager.getBackupsNames(); - var adapter = new ArrayAdapter(getContext(), android.R.layout.simple_list_item_1, arr) { - @Override - public View getView(int position, View convertView, ViewGroup parent) { - TextView textView = (TextView) super.getView(position, convertView, parent); - textView.setTextColor(getTextAttr()); - return textView; - } - }; - new VkAlertDialog.Builder(getContext()) - .setTitle(requireContext().getString(R.string.select_backup)) - .setAdapter(adapter, (dialog, which) -> { - try { - restoreBackup(arr[which]); - restartApplicationWithTimer(); - Toast.makeText(getContext(), requireContext().getString(R.string.backup_success), LENGTH_LONG).show(); - } catch (IOException e) { - e.printStackTrace(); - Toast.makeText(getContext(), requireContext().getString(R.string.backup_error), LENGTH_LONG).show(); - } - }) - .show(); - - return true; - }); - var vkAdminTokenPref = findPreference("vk_admin_token"); vkAdminTokenPref.setVisible(Preferences.getPreferences().getBoolean("new_music_downloading_way", false)); if (vkAdminTokenPref.isVisible()) { @@ -224,12 +150,6 @@ public class OtherFragment extends TrackedMaterialPreferenceToolbarFragment { return true; }); } - - findPreference("analyticsDisabled").setVisible(Preferences.isValidSignature()); - findPreference("analyticsDisabled").setOnPreferenceClickListener(preference -> { - restartApplicationWithTimer(); - return true; - }); } @SuppressLint({"CommitPrefEdits", "SetTextI18n"}) @@ -239,19 +159,19 @@ public class OtherFragment extends TrackedMaterialPreferenceToolbarFragment { var val = Preferences.getPreferences().getInt("autoclearcache_size", 0); RadioGroup rg = new RadioGroup(getContext()); - rg.setPadding(dp2px(18f), dp2px(12f), dp2px(18f), 0); + rg.setPadding(AndroidUtils.dp2px(18f), AndroidUtils.dp2px(12f), AndroidUtils.dp2px(18f), 0); for (int item = 0; item <= 5; item++) { RadioButton rb = new RadioButton(new ContextThemeWrapper(getContext(), com.vtosters.lite.R.style.Widget_AppCompat_CompoundButton_RadioButton)); SwitchHook.setCompoundButton(rb); rg.addView(rb); rb.setId(item); - rb.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp2px(14f)); + rb.setTextSize(TypedValue.COMPLEX_UNIT_PX, AndroidUtils.dp2px(14f)); var text = cacheText[item]; rb.setText(text != null ? text : AndroidUtils.getString("autoclearcachedisabled")); - rb.setTextColor(getTextAttr()); + rb.setTextColor(ThemesUtils.getTextAttr()); rb.setChecked(val == item); } @@ -311,7 +231,7 @@ public class OtherFragment extends TrackedMaterialPreferenceToolbarFragment { } case 5 -> clearWebViewCache(); } - Toast.makeText(getContext(), requireContext().getString(R.string.cache_cleaned), LENGTH_SHORT).show(); + Toast.makeText(getContext(), requireContext().getString(R.string.cache_cleaned), Toast.LENGTH_SHORT).show(); }) .show(); } @@ -320,19 +240,6 @@ public class OtherFragment extends TrackedMaterialPreferenceToolbarFragment { new WebView(requireContext()).clearCache(true); } - private void delprefs(Context context) { - new VkAlertDialog.Builder(context) - .setTitle(requireContext().getString(R.string.warning)) - .setMessage(requireContext().getString(R.string.settings_reset_confirm)) - .setCancelable(false) - .setPositiveButton(requireContext().getString(R.string.yes), (dialogInterface, i) -> { - deletePrefs(); - restartApplication(); - }) - .setNegativeButton(requireContext().getString(R.string.cancel), (dialogInterface, i) -> dialogInterface.dismiss()) - .show(); - } - private void copyText(String src) { var manager = (ClipboardManager) requireContext().getSystemService(Context.CLIPBOARD_SERVICE); manager.setPrimaryClip(ClipData.newPlainText("MBH-ST", src)); diff --git a/app/src/main/java/ru/vtosters/lite/utils/AndroidUtils.java b/app/src/main/java/ru/vtosters/lite/utils/AndroidUtils.java index c0cbb70b6..0fe8b9aa8 100644 --- a/app/src/main/java/ru/vtosters/lite/utils/AndroidUtils.java +++ b/app/src/main/java/ru/vtosters/lite/utils/AndroidUtils.java @@ -3,7 +3,6 @@ package ru.vtosters.lite.utils; import android.app.Activity; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.verify.domain.DomainVerificationManager; @@ -11,7 +10,6 @@ import android.content.pm.verify.domain.DomainVerificationUserState; import android.content.res.Resources; import android.net.Uri; import android.os.Build; -import android.preference.PreferenceManager; import android.provider.Settings; import android.util.Log; import androidx.annotation.NonNull; @@ -22,16 +20,22 @@ import com.vk.core.util.ToastUtils; import com.vtosters.lite.general.fragments.WebViewFragment; import ru.vtosters.lite.hooks.DateHook; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.lang.reflect.Method; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Locale; import java.util.Map; -import java.util.Objects; +import java.util.Random; import static ru.vtosters.lite.utils.Preferences.getBoolValue; public class AndroidUtils { + private static final String ALLOWED_CHARACTERS = "0123456789qwertyuiopasdfghjklzxcvbnm"; + public static boolean isDebuggable() { return 0 != (AndroidUtils.getGlobalContext().getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE); } @@ -173,9 +177,10 @@ public class AndroidUtils { try { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + getPackageName())); activity.startActivity(intent); - } catch (Throwable ignored) {} + } catch (Throwable ignored) { + } } - } + } ) .show(); } @@ -201,6 +206,36 @@ public class AndroidUtils { return null; } + private static String getRandomString(int sizeOfRandomString) { + final Random random = new Random(); + final StringBuilder sb = new StringBuilder(sizeOfRandomString); + for (int i = 0; i < sizeOfRandomString; ++i) + sb.append(ALLOWED_CHARACTERS.charAt(random.nextInt(ALLOWED_CHARACTERS.length()))); + return sb.toString(); + } + + public static String getRealPathFromURI(Uri uri) { + try { + InputStream inputStream = AndroidUtils.getGlobalContext().getContentResolver().openInputStream(uri); + + File file = File.createTempFile(getRandomString(10), ""); + + FileOutputStream outputStream = new FileOutputStream(file); + byte[] buff = new byte[1024]; + int read; + while ((read = inputStream.read(buff, 0, buff.length)) > 0) + outputStream.write(buff, 0, read); + inputStream.close(); + outputStream.close(); + + return file.getPath(); + } catch (IOException e) { + Log.d("AndroidUtils", e.getMessage()); + } + + return null; + } + public static boolean isFirstInstall(Context context) { try { long firstInstallTime = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).firstInstallTime; diff --git a/app/src/main/java/ru/vtosters/lite/utils/VKAccountDB.java b/app/src/main/java/ru/vtosters/lite/utils/VKAccountDB.java new file mode 100644 index 000000000..8ca4c6742 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/utils/VKAccountDB.java @@ -0,0 +1,98 @@ +package ru.vtosters.lite.utils; + +import android.annotation.SuppressLint; +import android.content.ContentValues; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.net.Uri; +import android.os.Environment; +import android.util.Log; +import com.vk.usersstore.contentprovider.a.UsersDbHelper; +import com.vtosters.lite.auth.VKAuth; + +import java.io.*; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class VKAccountDB { + private static SQLiteOpenHelper getDatabase() { + return new UsersDbHelper(AndroidUtils.getGlobalContext()); + } + + @SuppressLint("Range") + public static void copyDatabase(SQLiteDatabase db1, SQLiteDatabase db2) { + try { + Cursor cursor = db1.query("users", null, null, null, null, null, null); + + while (cursor.moveToNext()) { + int user_id = cursor.getInt(cursor.getColumnIndex("user_id")); + String name = cursor.getString(cursor.getColumnIndex("name")); + String avatar = cursor.getString(cursor.getColumnIndex("avatar")); + String exchange_token = cursor.getString(cursor.getColumnIndex("exchange_token")); + long timestamp = cursor.getLong(cursor.getColumnIndex("timestamp")); + + ContentValues values = new ContentValues(); + values.put("user_id", user_id); + values.put("name", name); + values.put("avatar", avatar); + values.put("exchange_token", exchange_token); + values.put("timestamp", timestamp); + values.put("logged_in", false); + + db2.insert("users", null, values); + } + + cursor.close(); + } catch (Exception e) { + Log.d("VKAccountDB", e.getMessage()); + } + } + + public static void saveDatabase(Uri uri) { + var path = AndroidUtils.getRealPathFromURI(uri); + + if (path == null) AndroidUtils.sendToast("No path"); + + SQLiteDatabase db = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY); + copyDatabase(db, getDatabase().getWritableDatabase()); + db.close(); + + LifecycleUtils.restartApplicationWithTimer(); + } + + public static void saveData() { + var db = getDatabase().getReadableDatabase(); + var dateFormat = new SimpleDateFormat("yyyy-MM-dd.HH-mm-ss", Locale.getDefault()); + var file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/VTLBackups/saved_accounts_" + dateFormat.format(new Date()) + ".vtl"); + + InputStream inputStream; + try { + inputStream = new FileInputStream(db.getPath()); + + FileOutputStream outputStream = new FileOutputStream(file); + byte[] buff = new byte[1024]; + int read; + while ((read = inputStream.read(buff, 0, buff.length)) > 0) + outputStream.write(buff, 0, read); + inputStream.close(); + outputStream.close(); + + AndroidUtils.sendToast("Аккаунты сохранены по пути " + file.getPath()); + } catch (IOException e) { + e.printStackTrace(); + AndroidUtils.sendToast("Ошибка при сохранении файла"); + } + } + + public static void resetData() { + SQLiteDatabase db = getDatabase().getWritableDatabase(); + db.execSQL("DELETE FROM users"); + db.close(); + + VKAuth.a("logout", false); + + LifecycleUtils.restartApplicationWithTimer(); + } +} diff --git a/smali/res/layout/vk_auth_choose_auth_method_fragment.xml b/smali/res/layout/vk_auth_choose_auth_method_fragment.xml index 25ad52f73..01f66fbe6 100644 --- a/smali/res/layout/vk_auth_choose_auth_method_fragment.xml +++ b/smali/res/layout/vk_auth_choose_auth_method_fragment.xml @@ -47,6 +47,18 @@ android:layout_marginEnd="16.0dip" android:layout_marginBottom="8.0dip" android:text="@string/vk_auth_already_have_account" + app:layout_constraintBottom_toTopOf="@id/account_backup_view" + app:layout_constraintVertical_bias="1.0" /> + + diff --git a/smali/res/values/ids.xml b/smali/res/values/ids.xml index 276bf1ab1..5157840f5 100644 --- a/smali/res/values/ids.xml +++ b/smali/res/values/ids.xml @@ -3919,4 +3919,5 @@ + diff --git a/smali/res/xml/preferences_other.xml b/smali/res/xml/preferences_other.xml index 91c43bd4d..0e3ec8e0c 100644 --- a/smali/res/xml/preferences_other.xml +++ b/smali/res/xml/preferences_other.xml @@ -1,10 +1,9 @@ - + + android:key="datasettings" + android:title="Настройки данных приложения"/> @@ -12,21 +11,11 @@ android:key="autoclearcache" android:title="@string/autoclearcache"/> - + - - - + android:key="firebasefix" + android:summary="@string/firebasefixsum" + android:title="@string/firebasefix"/> - \ No newline at end of file diff --git a/smali/smali_classes2/com/vk/auth/w/a/ChooseAuthMethodFragment.smali b/smali/smali_classes2/com/vk/auth/w/a/ChooseAuthMethodFragment.smali index 42139135b..78ef16688 100644 --- a/smali/smali_classes2/com/vk/auth/w/a/ChooseAuthMethodFragment.smali +++ b/smali/smali_classes2/com/vk/auth/w/a/ChooseAuthMethodFragment.smali @@ -210,7 +210,7 @@ invoke-virtual {p2, v0}, Landroid/view/View;->setOnClickListener(Landroid/view/View$OnClickListener;)V - invoke-static {p2}, Lru/vtosters/lite/hooks/ProxyHook;->hookAuth(Landroid/view/View;)V + invoke-static {p1}, Lru/vtosters/lite/hooks/ProxyHook;->hookAuth(Landroid/view/View;)V .line 7 invoke-direct {p0}, Lcom/vk/auth/w/a/ChooseAuthMethodFragment;->K4()V