Skip to content

Commit 4415c59

Browse files
committed
feat: add experimental force restore backup feature with user confirmation dialog
1 parent 3a1d758 commit 4415c59

File tree

4 files changed

+37
-85
lines changed

4 files changed

+37
-85
lines changed

app/src/main/java/com/wmods/wppenhacer/xposed/core/devkit/Unobfuscator.java

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -906,61 +906,6 @@ public synchronized static Method loadAntiRevokeMessageMethod(ClassLoader loader
906906
});
907907
}
908908

909-
public synchronized static Class<?> loadSettingsGoogleDriveActivity(ClassLoader loader) throws Exception {
910-
return UnobfuscatorCache.getInstance().getClass(loader, () -> {
911-
var classes = findAllClassUsingStrings(loader, StringMatchType.Contains, "SettingsGoogleDrive");
912-
if (classes == null)
913-
throw new Exception("SettingsGoogleDriveActivity not found (No classes with string)");
914-
915-
StringBuilder candidates = new StringBuilder();
916-
for (var cls : classes) {
917-
String name = cls.getName();
918-
if (name.contains("com.whatsapp.deeplink"))
919-
continue;
920-
921-
candidates.append(name).append(", ");
922-
923-
// Check for onCreate method (Standard for Activity/Fragment)
924-
try {
925-
// Check declared methods for "onCreate"
926-
for (Method m : cls.getDeclaredMethods()) {
927-
if (m.getName().equals("onCreate")) {
928-
return cls;
929-
}
930-
}
931-
} catch (Throwable t) {
932-
// Ignore reflection errors
933-
}
934-
}
935-
throw new Exception("SettingsGoogleDriveActivity not found. Candidates checked: " + candidates.toString());
936-
937-
});
938-
}
939-
940-
public synchronized static Class<?> loadRestoreBackupActivity(ClassLoader loader) throws Exception {
941-
return UnobfuscatorCache.getInstance().getClass(loader, () -> {
942-
var strings = new String[] { "RestoreFromBackupActivity", "gdrive/restore/activity",
943-
"gdrive_restore_title" };
944-
for (String s : strings) {
945-
var classes = findAllClassUsingStrings(loader, StringMatchType.Contains, s);
946-
if (classes != null) {
947-
for (var cls : classes) {
948-
try {
949-
for (Method m : cls.getDeclaredMethods()) {
950-
if (m.getName().equals("onCreate")) {
951-
return cls;
952-
}
953-
}
954-
} catch (Throwable t) {
955-
}
956-
}
957-
}
958-
959-
}
960-
throw new Exception("RestoreBackupActivity not found");
961-
});
962-
}
963-
964909
public synchronized static Field loadMessageKeyField(ClassLoader loader) throws Exception {
965910
return UnobfuscatorCache.getInstance().getField(loader, () -> {
966911
var classList = dexkit.findClass(new FindClass().matcher(new ClassMatcher().fieldCount(3)

app/src/main/java/com/wmods/wppenhacer/xposed/features/others/BackupRestore.java

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,19 @@
33
import android.app.Activity;
44
import android.content.Intent;
55
import android.view.Menu;
6-
import android.view.MenuItem;
76
import android.widget.Toast;
87

98
import com.wmods.wppenhacer.xposed.core.Feature;
9+
import com.wmods.wppenhacer.xposed.core.components.AlertDialogWpp;
1010
import com.wmods.wppenhacer.xposed.core.devkit.Unobfuscator;
11+
import com.wmods.wppenhacer.xposed.utils.ResId;
1112
import com.wmods.wppenhacer.xposed.utils.Utils;
1213

14+
import org.luckypray.dexkit.query.enums.StringMatchType;
15+
1316
import de.robv.android.xposed.XC_MethodHook;
1417
import de.robv.android.xposed.XSharedPreferences;
1518
import de.robv.android.xposed.XposedBridge;
16-
import de.robv.android.xposed.XposedHelpers;
1719

1820
public class BackupRestore extends Feature {
1921

@@ -30,39 +32,39 @@ public String getPluginName() {
3032
public void doHook() throws Exception {
3133
if (!prefs.getBoolean("force_restore_backup_feature", false)) return;
3234

33-
Class<?> settingsDriveClass = Unobfuscator.loadSettingsGoogleDriveActivity(classLoader);
34-
35-
XposedHelpers.findAndHookMethod(settingsDriveClass, "onPrepareOptionsMenu", Menu.class, new XC_MethodHook() {
35+
var restoreFromBackupClass = Unobfuscator.findFirstClassUsingName(classLoader, StringMatchType.EndsWith, "RestoreFromBackupActivity");
36+
37+
XposedBridge.hookAllMethods(Activity.class, "onPrepareOptionsMenu", new XC_MethodHook() {
3638
@Override
3739
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
40+
var name = param.thisObject.getClass().getSimpleName().toLowerCase();
41+
if (!(name.contains("drive") && name.contains("google"))) return;
3842
Menu menu = (Menu) param.args[0];
39-
// Hardcoding string to ensure it appears without resource injection issues
40-
String title = "Force Restore Backup (Experimental)";
41-
42-
// Use a high ID to avoid conflicts
43-
if (menu.findItem(10001) == null) {
44-
menu.add(0, 10001, 0, title);
45-
}
46-
}
47-
});
43+
if (menu.findItem(10001) != null) return;
44+
var menuItem = menu.add(0, 10001, 0, ResId.string.force_restore_backup_experimental);
45+
Activity activity = (Activity) param.thisObject;
46+
menuItem.setOnMenuItemClickListener((item) -> {
47+
new AlertDialogWpp(activity)
48+
.setTitle(ResId.string.force_restore_backup)
49+
.setMessage(activity.getString(ResId.string.warning_restore))
50+
.setPositiveButton(activity.getString(ResId.string.yes), (dialog, which) -> {
51+
try {
52+
Intent intent = new Intent(activity, restoreFromBackupClass);
53+
intent.setAction("action_show_restore_one_time_setup");
54+
activity.startActivityForResult(intent, 10001);
55+
} catch (Exception e) {
56+
XposedBridge.log(e);
57+
Utils.showToast("Error launching restore activity: " + e.getMessage(), Toast.LENGTH_LONG);
58+
}
59+
})
60+
.setNegativeButton(activity.getString(ResId.string.no), null)
61+
.show();
62+
63+
return true;
64+
});
4865

49-
XposedHelpers.findAndHookMethod(settingsDriveClass, "onOptionsItemSelected", MenuItem.class, new XC_MethodHook() {
50-
@Override
51-
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
52-
MenuItem item = (MenuItem) param.args[0];
53-
if (item.getItemId() == 10001) {
54-
Activity activity = (Activity) param.thisObject;
55-
try {
56-
Class<?> restoreClass = Unobfuscator.loadRestoreBackupActivity(classLoader);
57-
Intent intent = new Intent(activity, restoreClass);
58-
activity.startActivity(intent);
59-
param.setResult(true);
60-
} catch (Exception e) {
61-
Utils.showToast("Error launching restore activity: " + e.getMessage(), Toast.LENGTH_LONG);
62-
XposedBridge.log(e);
63-
}
64-
}
6566
}
6667
});
68+
6769
}
6870
}

app/src/main/java/com/wmods/wppenhacer/xposed/utils/ResId.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ public static class string {
109109
public static int possible_block_detected;
110110
public static int checking_if_the_contact_is_blocked;
111111
public static int block_unverified;
112+
public static int warning_restore;
113+
public static int force_restore_backup_experimental;
114+
public static int force_restore_backup;
112115
}
113116

114117
public static class array {

app/src/main/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,4 +476,6 @@
476476
<string name="action_follow_developer">Coming soon!</string>
477477
<string name="enable_spy">Enable Spy Tool</string>
478478
<string name="enable_spy_sum">Logs internal events to Xposed log for debugging.</string>
479+
<string name="warning_restore">When restoring the backup all messages after the backup will be lost, are you sure you want to continue?</string>
480+
<string name="force_restore_backup_experimental">Force Restore Backup (Experimental)</string>
479481
</resources>

0 commit comments

Comments
 (0)