Skip to content

Commit e590579

Browse files
support url opening
1 parent 0c455fc commit e590579

2 files changed

Lines changed: 146 additions & 0 deletions

File tree

AuthFix/AndroidJavaObjectSafe.cs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
using System;
2+
using System.Linq;
3+
using System.Reflection;
4+
using Il2CppInterop.Runtime.InteropTypes.Arrays;
5+
using UnityEngine;
6+
7+
namespace AuthFix;
8+
9+
public sealed class AndroidJavaObjectSafe : IDisposable
10+
{
11+
public AndroidJavaObject Inner { get; }
12+
13+
private static readonly MethodInfo s_Call;
14+
private static readonly MethodInfo s_CallReturn;
15+
private static readonly MethodInfo s_CallStatic;
16+
private static readonly MethodInfo s_CallStaticReturn;
17+
18+
private static readonly Type[] s_paramTypes =
19+
[typeof(string), typeof(Il2CppReferenceArray<Il2CppSystem.Object>)];
20+
21+
static AndroidJavaObjectSafe()
22+
{
23+
var all = typeof(AndroidJavaObject).GetMethods(
24+
BindingFlags.Public | BindingFlags.Instance);
25+
26+
s_Call = FindVoid(all, "Call");
27+
s_CallReturn = FindNonVoid(all, "Call");
28+
s_CallStatic = FindVoid(all, "CallStatic");
29+
s_CallStaticReturn = FindNonVoid(all, "CallStatic");
30+
}
31+
32+
private static MethodInfo FindVoid(MethodInfo[] methods, string name) =>
33+
methods.FirstOrDefault(m =>
34+
m.Name == name &&
35+
!m.IsGenericMethod &&
36+
m.ReturnType == typeof(void) &&
37+
m.GetParameters().Select(p => p.ParameterType).SequenceEqual(s_paramTypes));
38+
39+
private static MethodInfo FindNonVoid(MethodInfo[] methods, string name) =>
40+
methods.FirstOrDefault(m =>
41+
m.Name == name &&
42+
!m.IsGenericMethod &&
43+
m.ReturnType != typeof(void) &&
44+
m.GetParameters().Select(p => p.ParameterType).SequenceEqual(s_paramTypes));
45+
46+
// ── Constructors ───────────────────────────────────────────────────────────
47+
48+
public AndroidJavaObjectSafe(string className,
49+
Il2CppReferenceArray<Il2CppSystem.Object> args = null)
50+
{
51+
Inner = new AndroidJavaObject(className, args ?? new Il2CppReferenceArray<Il2CppSystem.Object>(0L));
52+
}
53+
54+
public AndroidJavaObjectSafe(AndroidJavaObject existing)
55+
{
56+
Inner = existing ?? throw new ArgumentNullException(nameof(existing));
57+
}
58+
59+
public void Call(string method, Il2CppReferenceArray<Il2CppSystem.Object> args = null)
60+
{
61+
args ??= new Il2CppReferenceArray<Il2CppSystem.Object>(0L);
62+
s_Call.Invoke(Inner, [method, args]);
63+
}
64+
65+
public Il2CppSystem.Object CallReturn(string method,
66+
Il2CppReferenceArray<Il2CppSystem.Object> args = null)
67+
{
68+
args ??= new Il2CppReferenceArray<Il2CppSystem.Object>(0L);
69+
return s_CallReturn.Invoke(Inner, [method, args]) as Il2CppSystem.Object;
70+
}
71+
72+
public void CallStatic(string method,
73+
Il2CppReferenceArray<Il2CppSystem.Object> args = null)
74+
{
75+
args ??= new Il2CppReferenceArray<Il2CppSystem.Object>(0L);
76+
s_CallStatic.Invoke(Inner, [method, args]);
77+
}
78+
79+
public Il2CppSystem.Object CallStaticReturn(string method,
80+
Il2CppReferenceArray<Il2CppSystem.Object> args = null)
81+
{
82+
args ??= new Il2CppReferenceArray<Il2CppSystem.Object>(0L);
83+
return s_CallStaticReturn.Invoke(Inner, [method, args]) as Il2CppSystem.Object;
84+
}
85+
86+
// ── Pass-through
87+
88+
public IntPtr GetRawObject() => Inner.GetRawObject();
89+
public IntPtr GetRawClass() => Inner.GetRawClass();
90+
public void Dispose() => Inner.Dispose();
91+
92+
// ── Convenience
93+
94+
public static Il2CppReferenceArray<Il2CppSystem.Object> Args(
95+
params Il2CppSystem.Object[] args) => new(args);
96+
}

AuthFix/AuthPlugin.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public partial class AuthPlugin : BasePlugin
3131

3232
private static bool _ranLobbyJoin;
3333

34+
private static readonly Il2CppSystem.String ACTION_VIEW = new("android.intent.action.VIEW".ToCharArray());
35+
3436
public static string GetLobby()
3537
{
3638
return Marshal.PtrToStringUTF8(get_lobby()) ?? string.Empty;
@@ -301,6 +303,54 @@ public static bool Prefix()
301303
return false;
302304
}
303305
}
306+
307+
[HarmonyPatch(typeof(Constants), nameof(Constants.OpenURL))]
308+
public static class OpenURLPatch
309+
{
310+
public static bool Prefix([HarmonyArgument(0)] string url)
311+
{
312+
if (string.IsNullOrEmpty(url))
313+
return false;
314+
315+
if (!url.StartsWith("http"))
316+
url = "https://" + url;
317+
318+
using var unityPlayer = new AndroidJavaObjectSafe("com.unity3d.player.UnityPlayer");
319+
320+
var activityRaw = unityPlayer.CallStaticReturn("getCurrentActivity");
321+
using var currentActivity = new AndroidJavaObjectSafe((AndroidJavaObject)activityRaw);
322+
323+
using var uriClass = new AndroidJavaObjectSafe("android.net.Uri");
324+
var uri = uriClass.CallStaticReturn(
325+
"parse",
326+
AndroidJavaObjectSafe.Args((Il2CppSystem.Object)(object)url)
327+
);
328+
329+
using var intentClass = new AndroidJavaObjectSafe("android.content.Intent");
330+
331+
var intent = new AndroidJavaObjectSafe(
332+
"android.content.Intent",
333+
AndroidJavaObjectSafe.Args(
334+
ACTION_VIEW,
335+
uri
336+
)
337+
);
338+
339+
currentActivity.Call(
340+
"runOnUiThread",
341+
AndroidJavaObjectSafe.Args(
342+
(Il2CppSystem.Object)(object)(() =>
343+
{
344+
currentActivity.Call(
345+
"startActivity",
346+
AndroidJavaObjectSafe.Args(intent.Inner)
347+
);
348+
})
349+
)
350+
);
351+
return false;
352+
}
353+
}
304354
}
305355

306356
public class Coroutines : MonoBehaviour { }

0 commit comments

Comments
 (0)