diff --git a/app/build.gradle b/app/build.gradle index fb389eb..ead050f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "xyz.rodit.snapmod" minSdk 24 targetSdk 32 - versionCode 1 - versionName "1.0" + versionCode 2 + versionName "1.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -34,7 +34,7 @@ dependencies { implementation files('libs/snapmod.jar') implementation 'androidx.preference:preference:1.2.0' - implementation 'xyz.rodit:xposed:1.2.1' + implementation 'xyz.rodit:xposed:1.3.0' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.3' diff --git a/app/src/main/java/xyz/rodit/snapmod/Shared.java b/app/src/main/java/xyz/rodit/snapmod/Shared.java index 8c95bb4..2506a91 100644 --- a/app/src/main/java/xyz/rodit/snapmod/Shared.java +++ b/app/src/main/java/xyz/rodit/snapmod/Shared.java @@ -11,8 +11,8 @@ public class Shared { public static final String SNAPMOD_FORCE_RESUME_ACTIVITY = SNAPMOD_PACKAGE_NAME + ".ForceResumeActivity"; - public static final String CONTEXT_HOOK_CLASS = "com.snap.mushroom.MainActivity"; - public static final String CONTEXT_HOOK_METHOD = "onCreate"; + public static final String CONTEXT_HOOK_CLASS = "android.app.Application"; + public static final String CONTEXT_HOOK_METHOD = "attach"; public static final String SNAPMOD_MEDIA_PREFIX = "SnapMod_"; diff --git a/app/src/main/java/xyz/rodit/snapmod/SnapHooks.java b/app/src/main/java/xyz/rodit/snapmod/SnapHooks.java index c26062c..a794d27 100644 --- a/app/src/main/java/xyz/rodit/snapmod/SnapHooks.java +++ b/app/src/main/java/xyz/rodit/snapmod/SnapHooks.java @@ -14,6 +14,7 @@ import java.text.SimpleDateFormat; import java.util.Collections; import java.util.Date; +import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -50,6 +51,7 @@ import xyz.rodit.snapmod.mappings.LocalMessageContent; import xyz.rodit.snapmod.mappings.LocationMessage; import xyz.rodit.snapmod.mappings.LocationMessageBuilder; +import xyz.rodit.snapmod.mappings.MainActivity; import xyz.rodit.snapmod.mappings.MediaBaseBase; import xyz.rodit.snapmod.mappings.MediaContainer; import xyz.rodit.snapmod.mappings.MediaType; @@ -75,6 +77,7 @@ import xyz.rodit.xposed.HooksBase; import xyz.rodit.xposed.client.http.StreamProvider; import xyz.rodit.xposed.client.http.streams.FileProxyStreamProvider; +import xyz.rodit.xposed.mappings.LoadScheme; public class SnapHooks extends HooksBase { @@ -88,6 +91,7 @@ public class SnapHooks extends HooksBase { public SnapHooks() { super(Collections.singletonList(Shared.SNAPCHAT_PACKAGE), + EnumSet.of(LoadScheme.CACHED_ON_CONTEXT, LoadScheme.SERVICE), Shared.SNAPMOD_PACKAGE_NAME, Shared.SNAPMOD_CONFIG_ACTION, Shared.CONTEXT_HOOK_CLASS, @@ -108,8 +112,6 @@ protected void beforeHookedMethod(MethodHookParam param) { @Override protected void onContextHook(Context context) { - mainActivity = context; - Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> { XposedBridge.log("Uncaught exception on thread " + thread + "."); XposedBridge.log(throwable); @@ -118,9 +120,20 @@ protected void onContextHook(Context context) { @Override protected void onConfigLoaded(boolean first) { - Intent intent = new Intent(); - intent.setClassName(Shared.SNAPMOD_PACKAGE_NAME, Shared.SNAPMOD_FORCE_RESUME_ACTIVITY); - mainActivity.startActivity(intent); + try { + if (mappingsLoaded) { + performStoryHooks(); + } + } catch (Throwable t) { + XposedBridge.log("Error performing story (un)hooks."); + XposedBridge.log(t); + } + + if (mainActivity != null) { + Intent intent = new Intent(); + intent.setClassName(Shared.SNAPMOD_PACKAGE_NAME, Shared.SNAPMOD_FORCE_RESUME_ACTIVITY); + mainActivity.startActivity(intent); + } } @Override @@ -128,6 +141,13 @@ protected void performHooks() throws Throwable { requireFileService(Shared.SNAPMOD_FILES_ACTION); requireStreamServer(0); + MainActivity.attachBaseContext.hook(new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) { + mainActivity = (Context) param.thisObject; + } + }); + // Prevent screenshot/save to gallery notifications ConversationManager.sendMessageWithContent.hook(new XC_MethodHook() { @Override @@ -423,6 +443,7 @@ protected void beforeHookedMethod(MethodHookParam param) { } }); + // Allow public story downloads InAppReportManagerImpl.handle.hook(new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) { @@ -442,6 +463,10 @@ protected void beforeHookedMethod(MethodHookParam param) { } }); + performStoryHooks(); + } + + private void performStoryHooks() throws Throwable { if (config.getBoolean("allow_download_stories")) { Class clsOperaContextActions = OperaContextActions.getMappedClass(); Field reportAction = null; @@ -521,6 +546,14 @@ protected void beforeHookedMethod(MethodHookParam param) { ChatMediaInAppReportClient.report.hook(downloadHook); TopicSnapInAppReportClient.report.hook(downloadHook); DirectSnapInAppReportClient.report.hook(downloadHook); + } else { + PublicUserStoryInAppReportClient.report.unhook(); + FriendStoryInAppReportClient.report.unhook(); + PublisherStoryInAppReportClient.report.unhook(); + AdInAppReportClient.report.unhook(); + ChatMediaInAppReportClient.report.unhook(); + TopicSnapInAppReportClient.report.unhook(); + DirectSnapInAppReportClient.report.unhook(); } }