diff --git a/Assets/Plugins/Android/WebViewPlugin-development.aar.tmpl b/Assets/Plugins/Android/WebViewPlugin-development.aar.tmpl index ff041ec6..d338e7c2 100644 Binary files a/Assets/Plugins/Android/WebViewPlugin-development.aar.tmpl and b/Assets/Plugins/Android/WebViewPlugin-development.aar.tmpl differ diff --git a/Assets/Plugins/Android/WebViewPlugin-release.aar.tmpl b/Assets/Plugins/Android/WebViewPlugin-release.aar.tmpl index 58859069..6788d893 100644 Binary files a/Assets/Plugins/Android/WebViewPlugin-release.aar.tmpl and b/Assets/Plugins/Android/WebViewPlugin-release.aar.tmpl differ diff --git a/Assets/Plugins/Editor/UnityWebViewPostprocessBuild.cs b/Assets/Plugins/Editor/UnityWebViewPostprocessBuild.cs index 19d9a961..bae62938 100644 --- a/Assets/Plugins/Editor/UnityWebViewPostprocessBuild.cs +++ b/Assets/Plugins/Editor/UnityWebViewPostprocessBuild.cs @@ -8,6 +8,9 @@ using System.Text; using System.Xml; using System; using UnityEditor.Android; +#if UNITY_2020_1_OR_NEWER +using UnityEditor.Build.Reporting; +#endif #if UNITY_2018_1_OR_NEWER using UnityEditor.Build; #endif @@ -15,525 +18,551 @@ using UnityEditor.Callbacks; using UnityEditor; using UnityEngine; -#if UNITY_2018_1_OR_NEWER -public class UnityWebViewPostprocessBuild : IPreprocessBuild, IPostGenerateGradleAndroidProject -#else -public class UnityWebViewPostprocessBuild -#endif +namespace Gree.UnityWebView { - private static bool nofragment = false; - - //// for android/unity 2018.1 or newer - //// cf. https://forum.unity.com/threads/android-hardwareaccelerated-is-forced-false-in-all-activities.532786/ - //// cf. https://github.com/Over17/UnityAndroidManifestCallback - -#if UNITY_2018_1_OR_NEWER - public void OnPreprocessBuild(BuildTarget buildTarget, string path) { - if (buildTarget == BuildTarget.Android) { - var dev = "Packages/net.gree.unity-webview/Assets/Plugins/Android/WebViewPlugin-development.aar.tmpl"; - var rel = "Packages/net.gree.unity-webview/Assets/Plugins/Android/WebViewPlugin-release.aar.tmpl"; - if (!File.Exists(dev) || !File.Exists(rel)) { - dev = "Assets/Plugins/Android/WebViewPlugin-development.aar.tmpl"; - rel = "Assets/Plugins/Android/WebViewPlugin-release.aar.tmpl"; - } - var src = (EditorUserBuildSettings.development) ? dev : rel; - //Directory.CreateDirectory("Temp/StagingArea/aar"); - //File.Copy(src, "Temp/StagingArea/aar/WebViewPlugin.aar", true); - Directory.CreateDirectory("Assets/Plugins/Android"); - File.Copy(src, "Assets/Plugins/Android/WebViewPlugin.aar", true); - } - } - - public void OnPostGenerateGradleAndroidProject(string basePath) { - var changed = false; - var androidManifest = new AndroidManifest(GetManifestPath(basePath)); - if (!nofragment) { - changed = (androidManifest.AddFileProvider(basePath) || changed); - { - var path = GetBuildGradlePath(basePath); - var lines0 = File.ReadAllText(path).Replace("\r\n", "\n").Replace("\r", "\n").Split(new[]{'\n'}); - { - var lines = new List(); - var independencies = false; - foreach (var line in lines0) { - if (line == "dependencies {") { - independencies = true; - } else if (independencies && line == "}") { - independencies = false; - lines.Add(" implementation 'androidx.core:core:1.6.0'"); - } else if (independencies) { - if (line.Contains("implementation(name: 'core") - || line.Contains("implementation(name: 'androidx.core.core") - || line.Contains("implementation 'androidx.core:core")) { - break; - } - } - lines.Add(line); - } - if (lines.Count > lines0.Length) { - File.WriteAllText(path, string.Join("\n", lines) + "\n"); - } - } - } - { - var path = GetGradlePropertiesPath(basePath); - var lines0 = ""; - var lines = ""; - if (File.Exists(path)) { - lines0 = File.ReadAllText(path).Replace("\r\n", "\n").Replace("\r", "\n") + "\n"; - lines = lines0; - } - if (!lines.Contains("android.useAndroidX=true")) { - lines += "android.useAndroidX=true\n"; - } - if (!lines.Contains("android.enableJetifier=true")) { - lines += "android.enableJetifier=true\n"; - } - if (lines != lines0) { - File.WriteAllText(path, lines); - } - } - } - changed = (androidManifest.SetExported(true) || changed); - changed = (androidManifest.SetWindowSoftInputMode("adjustPan") || changed); - changed = (androidManifest.SetHardwareAccelerated(true) || changed); -#if UNITYWEBVIEW_ANDROID_USES_CLEARTEXT_TRAFFIC - changed = (androidManifest.SetUsesCleartextTraffic(true) || changed); -#endif -#if UNITYWEBVIEW_ANDROID_ENABLE_CAMERA - changed = (androidManifest.AddCamera() || changed); - changed = (androidManifest.AddGallery() || changed); -#endif -#if UNITYWEBVIEW_ANDROID_ENABLE_MICROPHONE - changed = (androidManifest.AddMicrophone() || changed); -#endif - if (changed) { - androidManifest.Save(); - Debug.Log("unitywebview: adjusted AndroidManifest.xml."); - } - } -#endif - - public int callbackOrder { - get { - return 1; - } - } - - private string GetManifestPath(string basePath) { - var pathBuilder = new StringBuilder(basePath); - pathBuilder.Append(Path.DirectorySeparatorChar).Append("src"); - pathBuilder.Append(Path.DirectorySeparatorChar).Append("main"); - pathBuilder.Append(Path.DirectorySeparatorChar).Append("AndroidManifest.xml"); - return pathBuilder.ToString(); - } - - private string GetBuildGradlePath(string basePath) { - var pathBuilder = new StringBuilder(basePath); - pathBuilder.Append(Path.DirectorySeparatorChar).Append("build.gradle"); - return pathBuilder.ToString(); - } - - private string GetGradlePropertiesPath(string basePath) { - var pathBuilder = new StringBuilder(basePath); - if (basePath.EndsWith("unityLibrary")) { - pathBuilder.Append(Path.DirectorySeparatorChar).Append(".."); - } - pathBuilder.Append(Path.DirectorySeparatorChar).Append("gradle.properties"); - return pathBuilder.ToString(); - } - - //// for others - - [PostProcessBuild(100)] - public static void OnPostprocessBuild(BuildTarget buildTarget, string path) { -#if UNITY_2018_1_OR_NEWER - try { - File.Delete("Assets/Plugins/Android/WebViewPlugin.aar"); - File.Delete("Assets/Plugins/Android/WebViewPlugin.aar.meta"); - Directory.Delete("Assets/Plugins/Android"); - File.Delete("Assets/Plugins/Android.meta"); - Directory.Delete("Assets/Plugins"); - File.Delete("Assets/Plugins.meta"); - } catch (Exception) { - } +#if UNITY_2020_1_OR_NEWER + public class UnityWebViewPostprocessBuild : IPreprocessBuildWithReport, IPostGenerateGradleAndroidProject +#elif UNITY_2018_1_OR_NEWER + public class UnityWebViewPostprocessBuild : IPreprocessBuild, IPostGenerateGradleAndroidProject #else - if (buildTarget == BuildTarget.Android) { - string manifest = Path.Combine(Application.dataPath, "Plugins/Android/AndroidManifest.xml"); - if (!File.Exists(manifest)) { - string manifest0 = Path.Combine(Application.dataPath, "../Temp/StagingArea/AndroidManifest-main.xml"); - if (!File.Exists(manifest0)) { - Debug.LogError("unitywebview: cannot find both Assets/Plugins/Android/AndroidManifest.xml and Temp/StagingArea/AndroidManifest-main.xml. please build the app to generate Assets/Plugins/Android/AndroidManifest.xml and then rebuild it again."); - return; - } else { - File.Copy(manifest0, manifest, true); + public class UnityWebViewPostprocessBuild +#endif + { + private static bool nofragment = false; + + //// for android/unity 2018.1 or newer + //// cf. https://forum.unity.com/threads/android-hardwareaccelerated-is-forced-false-in-all-activities.532786/ + //// cf. https://github.com/Over17/UnityAndroidManifestCallback + +#if UNITY_2018_1_OR_NEWER +#if UNITY_2020_1_OR_NEWER + public void OnPreprocessBuild(BuildReport buildReport) { + var buildTarget = buildReport.summary.platform; +#else + public void OnPreprocessBuild(BuildTarget buildTarget, string path) { +#endif + if (buildTarget == BuildTarget.Android) { + var dev = "Packages/net.gree.unity-webview/Assets/Plugins/Android/WebViewPlugin-development.aar.tmpl"; + var rel = "Packages/net.gree.unity-webview/Assets/Plugins/Android/WebViewPlugin-release.aar.tmpl"; + if (!File.Exists(dev) || !File.Exists(rel)) { + dev = "Assets/Plugins/Android/WebViewPlugin-development.aar.tmpl"; + rel = "Assets/Plugins/Android/WebViewPlugin-release.aar.tmpl"; } + var src = (EditorUserBuildSettings.development) ? dev : rel; + //Directory.CreateDirectory("Temp/StagingArea/aar"); + //File.Copy(src, "Temp/StagingArea/aar/WebViewPlugin.aar", true); + Directory.CreateDirectory("Assets/Plugins/Android"); + File.Copy(src, "Assets/Plugins/Android/WebViewPlugin.aar", true); } + } + + public void OnPostGenerateGradleAndroidProject(string basePath) { var changed = false; - if (EditorUserBuildSettings.development) { - if (!File.Exists("Assets/Plugins/Android/WebView.aar") - || !File.ReadAllBytes("Assets/Plugins/Android/WebView.aar").SequenceEqual(File.ReadAllBytes("Assets/Plugins/Android/WebViewPlugin-development.aar.tmpl"))) { - File.Copy("Assets/Plugins/Android/WebViewPlugin-development.aar.tmpl", "Assets/Plugins/Android/WebView.aar", true); - changed = true; - } - } else { - if (!File.Exists("Assets/Plugins/Android/WebView.aar") - || !File.ReadAllBytes("Assets/Plugins/Android/WebView.aar").SequenceEqual(File.ReadAllBytes("Assets/Plugins/Android/WebViewPlugin-release.aar.tmpl"))) { - File.Copy("Assets/Plugins/Android/WebViewPlugin-release.aar.tmpl", "Assets/Plugins/Android/WebView.aar", true); - changed = true; - } - } - var androidManifest = new AndroidManifest(manifest); + var androidManifest = new AndroidManifest(GetManifestPath(basePath)); if (!nofragment) { - changed = (androidManifest.AddFileProvider("Assets/Plugins/Android") || changed); - var files = Directory.GetFiles("Assets/Plugins/Android/"); - var found = false; - foreach (var file in files) { - if (Regex.IsMatch(file, @"^Assets/Plugins/Android/(androidx\.core\.)?core-.*.aar$")) { - found = true; - break; - } - } - if (!found) { - foreach (var file in files) { - var match = Regex.Match(file, @"^Assets/Plugins/Android/(core.*.aar).tmpl$"); - if (match.Success) { - var name = match.Groups[1].Value; - File.Copy(file, "Assets/Plugins/Android/" + name, true); - break; + changed = (androidManifest.AddFileProvider(basePath) || changed); + { + var path = GetBuildGradlePath(basePath); + var lines0 = File.ReadAllText(path).Replace("\r\n", "\n").Replace("\r", "\n").Split(new[]{'\n'}); + { + var lines = new List(); + var independencies = false; + foreach (var line in lines0) { + if (line == "dependencies {") { + independencies = true; + } else if (independencies && line == "}") { + independencies = false; + lines.Add(" implementation 'androidx.core:core:1.6.0'"); + } else if (independencies) { + if (line.Contains("implementation(name: 'core") + || line.Contains("implementation(name: 'androidx.core.core") + || line.Contains("implementation 'androidx.core:core")) { + break; + } + } + lines.Add(line); + } + if (lines.Count > lines0.Length) { + File.WriteAllText(path, string.Join("\n", lines) + "\n"); } } } + { + var path = GetGradlePropertiesPath(basePath); + var lines0 = ""; + var lines = ""; + if (File.Exists(path)) { + lines0 = File.ReadAllText(path).Replace("\r\n", "\n").Replace("\r", "\n") + "\n"; + lines = lines0; + } + if (!lines.Contains("android.useAndroidX=true")) { + lines += "android.useAndroidX=true\n"; + } + if (!lines.Contains("android.enableJetifier=true")) { + lines += "android.enableJetifier=true\n"; + } + if (lines != lines0) { + File.WriteAllText(path, lines); + } + } } + changed = (androidManifest.SetExported(true) || changed); changed = (androidManifest.SetWindowSoftInputMode("adjustPan") || changed); changed = (androidManifest.SetHardwareAccelerated(true) || changed); #if UNITYWEBVIEW_ANDROID_USES_CLEARTEXT_TRAFFIC changed = (androidManifest.SetUsesCleartextTraffic(true) || changed); #endif + if (!nofragment) { + changed = (androidManifest.AddGallery() || changed); #if UNITYWEBVIEW_ANDROID_ENABLE_CAMERA - changed = (androidManifest.AddCamera() || changed); - changed = (androidManifest.AddGallery() || changed); + changed = (androidManifest.AddCamera() || changed); #endif #if UNITYWEBVIEW_ANDROID_ENABLE_MICROPHONE - changed = (androidManifest.AddMicrophone() || changed); -#endif -#if UNITY_5_6_0 || UNITY_5_6_1 - changed = (androidManifest.SetActivityName("net.gree.unitywebview.CUnityPlayerActivity") || changed); + changed = (androidManifest.AddMicrophone() || changed); #endif + } if (changed) { androidManifest.Save(); - Debug.LogError("unitywebview: adjusted AndroidManifest.xml and/or WebView.aar. Please rebuild the app."); + Debug.Log("unitywebview: adjusted AndroidManifest.xml."); } } #endif - if (buildTarget == BuildTarget.iOS) { - string projPath = path + "/Unity-iPhone.xcodeproj/project.pbxproj"; - var type = Type.GetType("UnityEditor.iOS.Xcode.PBXProject, UnityEditor.iOS.Extensions.Xcode"); - if (type == null) - { - Debug.LogError("unitywebview: failed to get PBXProject. please install iOS build support."); - return; + + public int callbackOrder { + get { + return 1; } - var src = File.ReadAllText(projPath); - //dynamic proj = type.GetConstructor(Type.EmptyTypes).Invoke(null); - var proj = type.GetConstructor(Type.EmptyTypes).Invoke(null); - //proj.ReadFromString(src); - { - var method = type.GetMethod("ReadFromString"); - method.Invoke(proj, new object[]{src}); + } + + private string GetManifestPath(string basePath) { + var pathBuilder = new StringBuilder(basePath); + pathBuilder.Append(Path.DirectorySeparatorChar).Append("src"); + pathBuilder.Append(Path.DirectorySeparatorChar).Append("main"); + pathBuilder.Append(Path.DirectorySeparatorChar).Append("AndroidManifest.xml"); + return pathBuilder.ToString(); + } + + private string GetBuildGradlePath(string basePath) { + var pathBuilder = new StringBuilder(basePath); + pathBuilder.Append(Path.DirectorySeparatorChar).Append("build.gradle"); + return pathBuilder.ToString(); + } + + private string GetGradlePropertiesPath(string basePath) { + var pathBuilder = new StringBuilder(basePath); + if (basePath.EndsWith("unityLibrary")) { + pathBuilder.Append(Path.DirectorySeparatorChar).Append(".."); } - var target = ""; -#if UNITY_2019_3_OR_NEWER - //target = proj.GetUnityFrameworkTargetGuid(); - { - var method = type.GetMethod("GetUnityFrameworkTargetGuid"); - target = (string)method.Invoke(proj, null); + pathBuilder.Append(Path.DirectorySeparatorChar).Append("gradle.properties"); + return pathBuilder.ToString(); + } + + //// for others + + [PostProcessBuild(100)] + public static void OnPostprocessBuild(BuildTarget buildTarget, string path) { +#if UNITY_2018_1_OR_NEWER + try { + File.Delete("Assets/Plugins/Android/WebViewPlugin.aar"); + File.Delete("Assets/Plugins/Android/WebViewPlugin.aar.meta"); + Directory.Delete("Assets/Plugins/Android"); + File.Delete("Assets/Plugins/Android.meta"); + Directory.Delete("Assets/Plugins"); + File.Delete("Assets/Plugins.meta"); + } catch (Exception) { } #else - //target = proj.TargetGuidByName("Unity-iPhone"); - { - var method = type.GetMethod("TargetGuidByName"); - target = (string)method.Invoke(proj, new object[]{"Unity-iPhone"}); + if (buildTarget == BuildTarget.Android) { + string manifest = Path.Combine(Application.dataPath, "Plugins/Android/AndroidManifest.xml"); + if (!File.Exists(manifest)) { + string manifest0 = Path.Combine(Application.dataPath, "../Temp/StagingArea/AndroidManifest-main.xml"); + if (!File.Exists(manifest0)) { + Debug.LogError("unitywebview: cannot find both Assets/Plugins/Android/AndroidManifest.xml and Temp/StagingArea/AndroidManifest-main.xml. please build the app to generate Assets/Plugins/Android/AndroidManifest.xml and then rebuild it again."); + return; + } else { + File.Copy(manifest0, manifest, true); + } + } + var changed = false; + if (EditorUserBuildSettings.development) { + if (!File.Exists("Assets/Plugins/Android/WebView.aar") + || !File.ReadAllBytes("Assets/Plugins/Android/WebView.aar").SequenceEqual(File.ReadAllBytes("Assets/Plugins/Android/WebViewPlugin-development.aar.tmpl"))) { + File.Copy("Assets/Plugins/Android/WebViewPlugin-development.aar.tmpl", "Assets/Plugins/Android/WebView.aar", true); + changed = true; + } + } else { + if (!File.Exists("Assets/Plugins/Android/WebView.aar") + || !File.ReadAllBytes("Assets/Plugins/Android/WebView.aar").SequenceEqual(File.ReadAllBytes("Assets/Plugins/Android/WebViewPlugin-release.aar.tmpl"))) { + File.Copy("Assets/Plugins/Android/WebViewPlugin-release.aar.tmpl", "Assets/Plugins/Android/WebView.aar", true); + changed = true; + } + } + var androidManifest = new AndroidManifest(manifest); + if (!nofragment) { + changed = (androidManifest.AddFileProvider("Assets/Plugins/Android") || changed); + var files = Directory.GetFiles("Assets/Plugins/Android/"); + var found = false; + foreach (var file in files) { + if (Regex.IsMatch(file, @"^Assets/Plugins/Android/(androidx\.core\.)?core-.*.aar$")) { + found = true; + break; + } + } + if (!found) { + foreach (var file in files) { + var match = Regex.Match(file, @"^Assets/Plugins/Android/(core.*.aar).tmpl$"); + if (match.Success) { + var name = match.Groups[1].Value; + File.Copy(file, "Assets/Plugins/Android/" + name, true); + break; + } + } + } + } + changed = (androidManifest.SetWindowSoftInputMode("adjustPan") || changed); + changed = (androidManifest.SetHardwareAccelerated(true) || changed); +#if UNITYWEBVIEW_ANDROID_USES_CLEARTEXT_TRAFFIC + changed = (androidManifest.SetUsesCleartextTraffic(true) || changed); +#endif + if (!nofragment) { + changed = (androidManifest.AddGallery() || changed); +#if UNITYWEBVIEW_ANDROID_ENABLE_CAMERA + changed = (androidManifest.AddCamera() || changed); +#endif +#if UNITYWEBVIEW_ANDROID_ENABLE_MICROPHONE + changed = (androidManifest.AddMicrophone() || changed); +#endif + } +#if UNITY_5_6_0 || UNITY_5_6_1 + changed = (androidManifest.SetActivityName("net.gree.unitywebview.CUnityPlayerActivity") || changed); +#endif + if (changed) { + androidManifest.Save(); + Debug.LogError("unitywebview: adjusted AndroidManifest.xml and/or WebView.aar. Please rebuild the app."); + } } #endif - //proj.AddFrameworkToProject(target, "WebKit.framework", false); - { - var method = type.GetMethod("AddFrameworkToProject"); - method.Invoke(proj, new object[]{target, "WebKit.framework", false}); - } - var cflags = ""; - if (EditorUserBuildSettings.development) { - cflags += " -DUNITYWEBVIEW_DEVELOPMENT"; - } + if (buildTarget == BuildTarget.iOS) { + string projPath = path + "/Unity-iPhone.xcodeproj/project.pbxproj"; + var type = Type.GetType("UnityEditor.iOS.Xcode.PBXProject, UnityEditor.iOS.Extensions.Xcode"); + if (type == null) + { + Debug.LogError("unitywebview: failed to get PBXProject. please install iOS build support."); + return; + } + var src = File.ReadAllText(projPath); + //dynamic proj = type.GetConstructor(Type.EmptyTypes).Invoke(null); + var proj = type.GetConstructor(Type.EmptyTypes).Invoke(null); + //proj.ReadFromString(src); + { + var method = type.GetMethod("ReadFromString"); + method.Invoke(proj, new object[]{src}); + } + var target = ""; +#if UNITY_2019_3_OR_NEWER + //target = proj.GetUnityFrameworkTargetGuid(); + { + var method = type.GetMethod("GetUnityFrameworkTargetGuid"); + target = (string)method.Invoke(proj, null); + } +#else + //target = proj.TargetGuidByName("Unity-iPhone"); + { + var method = type.GetMethod("TargetGuidByName"); + target = (string)method.Invoke(proj, new object[]{"Unity-iPhone"}); + } +#endif + //proj.AddFrameworkToProject(target, "WebKit.framework", false); + { + var method = type.GetMethod("AddFrameworkToProject"); + method.Invoke(proj, new object[]{target, "WebKit.framework", false}); + } + var cflags = ""; + if (EditorUserBuildSettings.development) { + cflags += " -DUNITYWEBVIEW_DEVELOPMENT"; + } #if UNITYWEBVIEW_IOS_ALLOW_FILE_URLS - cflags += " -DUNITYWEBVIEW_IOS_ALLOW_FILE_URLS"; + cflags += " -DUNITYWEBVIEW_IOS_ALLOW_FILE_URLS"; #endif - cflags = cflags.Trim(); - if (!string.IsNullOrEmpty(cflags)) { - // proj.AddBuildProperty(target, "OTHER_LDFLAGS", cflags); - var method = type.GetMethod("AddBuildProperty", new Type[]{typeof(string), typeof(string), typeof(string)}); - method.Invoke(proj, new object[]{target, "OTHER_CFLAGS", cflags}); - } - var dst = ""; - //dst = proj.WriteToString(); - { - var method = type.GetMethod("WriteToString"); - dst = (string)method.Invoke(proj, null); - } - File.WriteAllText(projPath, dst); - } - } -} - -internal class AndroidXmlDocument : XmlDocument { - private string m_Path; - protected XmlNamespaceManager nsMgr; - public readonly string AndroidXmlNamespace = "http://schemas.android.com/apk/res/android"; - - public AndroidXmlDocument(string path) { - m_Path = path; - using (var reader = new XmlTextReader(m_Path)) { - reader.Read(); - Load(reader); - } - nsMgr = new XmlNamespaceManager(NameTable); - nsMgr.AddNamespace("android", AndroidXmlNamespace); - } - - public string Save() { - return SaveAs(m_Path); - } - - public string SaveAs(string path) { - using (var writer = new XmlTextWriter(path, new UTF8Encoding(false))) { - writer.Formatting = Formatting.Indented; - Save(writer); - } - return path; - } -} - -internal class AndroidManifest : AndroidXmlDocument { - private readonly XmlElement ManifestElement; - private readonly XmlElement ApplicationElement; - - public AndroidManifest(string path) : base(path) { - ManifestElement = SelectSingleNode("/manifest") as XmlElement; - ApplicationElement = SelectSingleNode("/manifest/application") as XmlElement; - } - - private XmlAttribute CreateAndroidAttribute(string key, string value) { - XmlAttribute attr = CreateAttribute("android", key, AndroidXmlNamespace); - attr.Value = value; - return attr; - } - - internal XmlNode GetActivityWithLaunchIntent() { - return - SelectSingleNode( - "/manifest/application/activity[intent-filter/action/@android:name='android.intent.action.MAIN' and " - + "intent-filter/category/@android:name='android.intent.category.LAUNCHER']", - nsMgr); - } - - internal bool SetUsesCleartextTraffic(bool enabled) { - // android:usesCleartextTraffic - bool changed = false; - if (ApplicationElement.GetAttribute("usesCleartextTraffic", AndroidXmlNamespace) != ((enabled) ? "true" : "false")) { - ApplicationElement.SetAttribute("usesCleartextTraffic", AndroidXmlNamespace, (enabled) ? "true" : "false"); - changed = true; - } - return changed; - } - - // for api level 33 - internal bool SetExported(bool enabled) { - bool changed = false; - var activity = GetActivityWithLaunchIntent() as XmlElement; - if (activity.GetAttribute("exported", AndroidXmlNamespace) != ((enabled) ? "true" : "false")) { - activity.SetAttribute("exported", AndroidXmlNamespace, (enabled) ? "true" : "false"); - changed = true; - } - return changed; - } - - internal bool SetWindowSoftInputMode(string mode) { - bool changed = false; - var activity = GetActivityWithLaunchIntent() as XmlElement; - if (activity.GetAttribute("windowSoftInputMode", AndroidXmlNamespace) != mode) { - activity.SetAttribute("windowSoftInputMode", AndroidXmlNamespace, mode); - changed = true; - } - return changed; - } - - internal bool SetHardwareAccelerated(bool enabled) { - bool changed = false; - var activity = GetActivityWithLaunchIntent() as XmlElement; - if (activity.GetAttribute("hardwareAccelerated", AndroidXmlNamespace) != ((enabled) ? "true" : "false")) { - activity.SetAttribute("hardwareAccelerated", AndroidXmlNamespace, (enabled) ? "true" : "false"); - changed = true; - } - return changed; - } - - internal bool SetActivityName(string name) { - bool changed = false; - var activity = GetActivityWithLaunchIntent() as XmlElement; - if (activity.GetAttribute("name", AndroidXmlNamespace) != name) { - activity.SetAttribute("name", AndroidXmlNamespace, name); - changed = true; - } - return changed; - } - - internal bool AddFileProvider(string basePath) { - bool changed = false; - var authorities = PlayerSettings.applicationIdentifier + ".unitywebview.fileprovider"; - if (SelectNodes("/manifest/application/provider[@android:authorities='" + authorities + "']", nsMgr).Count == 0) { - var elem = CreateElement("provider"); - elem.Attributes.Append(CreateAndroidAttribute("name", "androidx.core.content.FileProvider")); - elem.Attributes.Append(CreateAndroidAttribute("authorities", authorities)); - elem.Attributes.Append(CreateAndroidAttribute("exported", "false")); - elem.Attributes.Append(CreateAndroidAttribute("grantUriPermissions", "true")); - var meta = CreateElement("meta-data"); - meta.Attributes.Append(CreateAndroidAttribute("name", "android.support.FILE_PROVIDER_PATHS")); - meta.Attributes.Append(CreateAndroidAttribute("resource", "@xml/unitywebview_file_provider_paths")); - elem.AppendChild(meta); - ApplicationElement.AppendChild(elem); - changed = true; - var xml = GetFileProviderSettingPath(basePath); - if (!File.Exists(xml)) { - Directory.CreateDirectory(Path.GetDirectoryName(xml)); - File.WriteAllText( - xml, - "\n" + - " \n" + - "\n"); + cflags = cflags.Trim(); + if (!string.IsNullOrEmpty(cflags)) { + // proj.AddBuildProperty(target, "OTHER_LDFLAGS", cflags); + var method = type.GetMethod("AddBuildProperty", new Type[]{typeof(string), typeof(string), typeof(string)}); + method.Invoke(proj, new object[]{target, "OTHER_CFLAGS", cflags}); + } + var dst = ""; + //dst = proj.WriteToString(); + { + var method = type.GetMethod("WriteToString"); + dst = (string)method.Invoke(proj, null); + } + File.WriteAllText(projPath, dst); } } - return changed; } - private string GetFileProviderSettingPath(string basePath) { - var pathBuilder = new StringBuilder(basePath); - pathBuilder.Append(Path.DirectorySeparatorChar).Append("src"); - pathBuilder.Append(Path.DirectorySeparatorChar).Append("main"); - pathBuilder.Append(Path.DirectorySeparatorChar).Append("res"); - pathBuilder.Append(Path.DirectorySeparatorChar).Append("xml"); - pathBuilder.Append(Path.DirectorySeparatorChar).Append("unitywebview_file_provider_paths.xml"); - return pathBuilder.ToString(); + internal class AndroidXmlDocument : XmlDocument { + private string m_Path; + protected XmlNamespaceManager nsMgr; + public readonly string AndroidXmlNamespace = "http://schemas.android.com/apk/res/android"; + + public AndroidXmlDocument(string path) { + m_Path = path; + using (var reader = new XmlTextReader(m_Path)) { + reader.Read(); + Load(reader); + } + nsMgr = new XmlNamespaceManager(NameTable); + nsMgr.AddNamespace("android", AndroidXmlNamespace); + } + + public string Save() { + return SaveAs(m_Path); + } + + public string SaveAs(string path) { + using (var writer = new XmlTextWriter(path, new UTF8Encoding(false))) { + writer.Formatting = Formatting.Indented; + Save(writer); + } + return path; + } } - internal bool AddCamera() { - bool changed = false; - if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.CAMERA']", nsMgr).Count == 0) { - var elem = CreateElement("uses-permission"); - elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.CAMERA")); - ManifestElement.AppendChild(elem); - changed = true; - } - if (SelectNodes("/manifest/uses-feature[@android:name='android.hardware.camera']", nsMgr).Count == 0) { - var elem = CreateElement("uses-feature"); - elem.Attributes.Append(CreateAndroidAttribute("name", "android.hardware.camera")); - ManifestElement.AppendChild(elem); - changed = true; - } - // cf. https://developer.android.com/training/data-storage/shared/media#media-location-permission - if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.ACCESS_MEDIA_LOCATION']", nsMgr).Count == 0) { - var elem = CreateElement("uses-permission"); - elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.ACCESS_MEDIA_LOCATION")); - ManifestElement.AppendChild(elem); - changed = true; - } - // cf. https://developer.android.com/training/package-visibility/declaring - if (SelectNodes("/manifest/queries", nsMgr).Count == 0) { - var elem = CreateElement("queries"); - ManifestElement.AppendChild(elem); - changed = true; - } - if (SelectNodes("/manifest/queries/intent/action[@android:name='android.media.action.IMAGE_CAPTURE']", nsMgr).Count == 0) { - var action = CreateElement("action"); - action.Attributes.Append(CreateAndroidAttribute("name", "android.media.action.IMAGE_CAPTURE")); - var intent = CreateElement("intent"); - intent.AppendChild(action); - var queries = SelectSingleNode("/manifest/queries") as XmlElement; - queries.AppendChild(intent); - changed = true; - } - return changed; - } + internal class AndroidManifest : AndroidXmlDocument { + private readonly XmlElement ManifestElement; + private readonly XmlElement ApplicationElement; + + public AndroidManifest(string path) : base(path) { + ManifestElement = SelectSingleNode("/manifest") as XmlElement; + ApplicationElement = SelectSingleNode("/manifest/application") as XmlElement; + } + + private XmlAttribute CreateAndroidAttribute(string key, string value) { + XmlAttribute attr = CreateAttribute("android", key, AndroidXmlNamespace); + attr.Value = value; + return attr; + } + + internal XmlNode GetActivityWithLaunchIntent() { + return + SelectSingleNode( + "/manifest/application/activity[intent-filter/action/@android:name='android.intent.action.MAIN' and " + + "intent-filter/category/@android:name='android.intent.category.LAUNCHER']", + nsMgr); + } + + internal bool SetUsesCleartextTraffic(bool enabled) { + // android:usesCleartextTraffic + bool changed = false; + if (ApplicationElement.GetAttribute("usesCleartextTraffic", AndroidXmlNamespace) != ((enabled) ? "true" : "false")) { + ApplicationElement.SetAttribute("usesCleartextTraffic", AndroidXmlNamespace, (enabled) ? "true" : "false"); + changed = true; + } + return changed; + } - internal bool AddGallery() { - bool changed = false; // for api level 33 - if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.READ_MEDIA_IMAGES']", nsMgr).Count == 0) { - var elem = CreateElement("uses-permission"); - elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.READ_MEDIA_IMAGES")); - ManifestElement.AppendChild(elem); - changed = true; + internal bool SetExported(bool enabled) { + bool changed = false; + var activity = GetActivityWithLaunchIntent() as XmlElement; + if (activity == null) { + return false; + } + if (activity.GetAttribute("exported", AndroidXmlNamespace) != ((enabled) ? "true" : "false")) { + activity.SetAttribute("exported", AndroidXmlNamespace, (enabled) ? "true" : "false"); + changed = true; + } + return changed; } - if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.READ_MEDIA_VIDEO']", nsMgr).Count == 0) { - var elem = CreateElement("uses-permission"); - elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.READ_MEDIA_VIDEO")); - ManifestElement.AppendChild(elem); - changed = true; - } - if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.READ_MEDIA_AUDIO']", nsMgr).Count == 0) { - var elem = CreateElement("uses-permission"); - elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.READ_MEDIA_AUDIO")); - ManifestElement.AppendChild(elem); - changed = true; - } - // cf. https://developer.android.com/training/package-visibility/declaring - if (SelectNodes("/manifest/queries", nsMgr).Count == 0) { - var elem = CreateElement("queries"); - ManifestElement.AppendChild(elem); - changed = true; - } - if (SelectNodes("/manifest/queries/intent/action[@android:name='android.media.action.GET_CONTENT']", nsMgr).Count == 0) { - var action = CreateElement("action"); - action.Attributes.Append(CreateAndroidAttribute("name", "android.media.action.GET_CONTENT")); - var intent = CreateElement("intent"); - intent.AppendChild(action); - var queries = SelectSingleNode("/manifest/queries") as XmlElement; - queries.AppendChild(intent); - changed = true; - } - return changed; - } - internal bool AddMicrophone() { - bool changed = false; - if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.MICROPHONE']", nsMgr).Count == 0) { - var elem = CreateElement("uses-permission"); - elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.MICROPHONE")); - ManifestElement.AppendChild(elem); - changed = true; + internal bool SetWindowSoftInputMode(string mode) { + bool changed = false; + var activity = GetActivityWithLaunchIntent() as XmlElement; + if (activity == null) { + return false; + } + if (activity.GetAttribute("windowSoftInputMode", AndroidXmlNamespace) != mode) { + activity.SetAttribute("windowSoftInputMode", AndroidXmlNamespace, mode); + changed = true; + } + return changed; } - if (SelectNodes("/manifest/uses-feature[@android:name='android.hardware.microphone']", nsMgr).Count == 0) { - var elem = CreateElement("uses-feature"); - elem.Attributes.Append(CreateAndroidAttribute("name", "android.hardware.microphone")); - ManifestElement.AppendChild(elem); - changed = true; + + internal bool SetHardwareAccelerated(bool enabled) { + bool changed = false; + var activity = GetActivityWithLaunchIntent() as XmlElement; + if (activity == null) { + return false; + } + if (activity.GetAttribute("hardwareAccelerated", AndroidXmlNamespace) != ((enabled) ? "true" : "false")) { + activity.SetAttribute("hardwareAccelerated", AndroidXmlNamespace, (enabled) ? "true" : "false"); + changed = true; + } + return changed; } - // cf. https://github.com/gree/unity-webview/issues/679 - // cf. https://github.com/fluttercommunity/flutter_webview_plugin/issues/138#issuecomment-559307558 - // cf. https://stackoverflow.com/questions/38917751/webview-webrtc-not-working/68024032#68024032 - // cf. https://stackoverflow.com/questions/40236925/allowing-microphone-accesspermission-in-webview-android-studio-java/47410311#47410311 - if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.MODIFY_AUDIO_SETTINGS']", nsMgr).Count == 0) { - var elem = CreateElement("uses-permission"); - elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.MODIFY_AUDIO_SETTINGS")); - ManifestElement.AppendChild(elem); - changed = true; + + internal bool SetActivityName(string name) { + bool changed = false; + var activity = GetActivityWithLaunchIntent() as XmlElement; + if (activity == null) { + return false; + } + if (activity.GetAttribute("name", AndroidXmlNamespace) != name) { + activity.SetAttribute("name", AndroidXmlNamespace, name); + changed = true; + } + return changed; } - if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.RECORD_AUDIO']", nsMgr).Count == 0) { - var elem = CreateElement("uses-permission"); - elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.RECORD_AUDIO")); - ManifestElement.AppendChild(elem); - changed = true; + + internal bool AddFileProvider(string basePath) { + bool changed = false; + var authorities = PlayerSettings.applicationIdentifier + ".unitywebview.fileprovider"; + if (SelectNodes("/manifest/application/provider[@android:authorities='" + authorities + "']", nsMgr).Count == 0) { + var elem = CreateElement("provider"); + elem.Attributes.Append(CreateAndroidAttribute("name", "androidx.core.content.FileProvider")); + elem.Attributes.Append(CreateAndroidAttribute("authorities", authorities)); + elem.Attributes.Append(CreateAndroidAttribute("exported", "false")); + elem.Attributes.Append(CreateAndroidAttribute("grantUriPermissions", "true")); + var meta = CreateElement("meta-data"); + meta.Attributes.Append(CreateAndroidAttribute("name", "android.support.FILE_PROVIDER_PATHS")); + meta.Attributes.Append(CreateAndroidAttribute("resource", "@xml/unitywebview_file_provider_paths")); + elem.AppendChild(meta); + ApplicationElement.AppendChild(elem); + changed = true; + var xml = GetFileProviderSettingPath(basePath); + if (!File.Exists(xml)) { + Directory.CreateDirectory(Path.GetDirectoryName(xml)); + File.WriteAllText( + xml, + "\n" + + " \n" + + "\n"); + } + } + return changed; + } + + private string GetFileProviderSettingPath(string basePath) { + var pathBuilder = new StringBuilder(basePath); + pathBuilder.Append(Path.DirectorySeparatorChar).Append("src"); + pathBuilder.Append(Path.DirectorySeparatorChar).Append("main"); + pathBuilder.Append(Path.DirectorySeparatorChar).Append("res"); + pathBuilder.Append(Path.DirectorySeparatorChar).Append("xml"); + pathBuilder.Append(Path.DirectorySeparatorChar).Append("unitywebview_file_provider_paths.xml"); + return pathBuilder.ToString(); + } + + internal bool AddCamera() { + bool changed = false; + if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.CAMERA']", nsMgr).Count == 0) { + var elem = CreateElement("uses-permission"); + elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.CAMERA")); + ManifestElement.AppendChild(elem); + changed = true; + } + if (SelectNodes("/manifest/uses-feature[@android:name='android.hardware.camera']", nsMgr).Count == 0) { + var elem = CreateElement("uses-feature"); + elem.Attributes.Append(CreateAndroidAttribute("name", "android.hardware.camera")); + ManifestElement.AppendChild(elem); + changed = true; + } + // cf. https://developer.android.com/training/data-storage/shared/media#media-location-permission + if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.ACCESS_MEDIA_LOCATION']", nsMgr).Count == 0) { + var elem = CreateElement("uses-permission"); + elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.ACCESS_MEDIA_LOCATION")); + ManifestElement.AppendChild(elem); + changed = true; + } + // cf. https://developer.android.com/training/package-visibility/declaring + if (SelectNodes("/manifest/queries", nsMgr).Count == 0) { + var elem = CreateElement("queries"); + ManifestElement.AppendChild(elem); + changed = true; + } + if (SelectNodes("/manifest/queries/intent/action[@android:name='android.media.action.IMAGE_CAPTURE']", nsMgr).Count == 0) { + var action = CreateElement("action"); + action.Attributes.Append(CreateAndroidAttribute("name", "android.media.action.IMAGE_CAPTURE")); + var intent = CreateElement("intent"); + intent.AppendChild(action); + var queries = SelectSingleNode("/manifest/queries") as XmlElement; + queries.AppendChild(intent); + changed = true; + } + return changed; + } + + internal bool AddGallery() { + bool changed = false; + // for api level 33 + if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.READ_MEDIA_IMAGES']", nsMgr).Count == 0) { + var elem = CreateElement("uses-permission"); + elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.READ_MEDIA_IMAGES")); + ManifestElement.AppendChild(elem); + changed = true; + } + if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.READ_MEDIA_VIDEO']", nsMgr).Count == 0) { + var elem = CreateElement("uses-permission"); + elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.READ_MEDIA_VIDEO")); + ManifestElement.AppendChild(elem); + changed = true; + } + if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.READ_MEDIA_AUDIO']", nsMgr).Count == 0) { + var elem = CreateElement("uses-permission"); + elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.READ_MEDIA_AUDIO")); + ManifestElement.AppendChild(elem); + changed = true; + } + // cf. https://developer.android.com/training/package-visibility/declaring + if (SelectNodes("/manifest/queries", nsMgr).Count == 0) { + var elem = CreateElement("queries"); + ManifestElement.AppendChild(elem); + changed = true; + } + if (SelectNodes("/manifest/queries/intent/action[@android:name='android.media.action.GET_CONTENT']", nsMgr).Count == 0) { + var action = CreateElement("action"); + action.Attributes.Append(CreateAndroidAttribute("name", "android.media.action.GET_CONTENT")); + var intent = CreateElement("intent"); + intent.AppendChild(action); + var queries = SelectSingleNode("/manifest/queries") as XmlElement; + queries.AppendChild(intent); + changed = true; + } + return changed; + } + + internal bool AddMicrophone() { + bool changed = false; + if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.MICROPHONE']", nsMgr).Count == 0) { + var elem = CreateElement("uses-permission"); + elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.MICROPHONE")); + ManifestElement.AppendChild(elem); + changed = true; + } + if (SelectNodes("/manifest/uses-feature[@android:name='android.hardware.microphone']", nsMgr).Count == 0) { + var elem = CreateElement("uses-feature"); + elem.Attributes.Append(CreateAndroidAttribute("name", "android.hardware.microphone")); + ManifestElement.AppendChild(elem); + changed = true; + } + // cf. https://github.com/gree/unity-webview/issues/679 + // cf. https://github.com/fluttercommunity/flutter_webview_plugin/issues/138#issuecomment-559307558 + // cf. https://stackoverflow.com/questions/38917751/webview-webrtc-not-working/68024032#68024032 + // cf. https://stackoverflow.com/questions/40236925/allowing-microphone-accesspermission-in-webview-android-studio-java/47410311#47410311 + if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.MODIFY_AUDIO_SETTINGS']", nsMgr).Count == 0) { + var elem = CreateElement("uses-permission"); + elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.MODIFY_AUDIO_SETTINGS")); + ManifestElement.AppendChild(elem); + changed = true; + } + if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.RECORD_AUDIO']", nsMgr).Count == 0) { + var elem = CreateElement("uses-permission"); + elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.RECORD_AUDIO")); + ManifestElement.AppendChild(elem); + changed = true; + } + return changed; } - return changed; } } #endif diff --git a/Assets/Plugins/WebView.bundle.meta b/Assets/Plugins/WebView.bundle.meta new file mode 100644 index 00000000..42a688b6 --- /dev/null +++ b/Assets/Plugins/WebView.bundle.meta @@ -0,0 +1,58 @@ +fileFormatVersion: 2 +guid: 60e7bf38137eb4950b2f02b7d57c1ad3 +folderAsset: yes +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + platformData: + Android: + enabled: 0 + settings: + CPU: AnyCPU + Any: + enabled: 0 + settings: {} + Editor: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: OSX + Linux: + enabled: 0 + settings: + CPU: x86 + Linux64: + enabled: 0 + settings: + CPU: x86_64 + OSXIntel: + enabled: 1 + settings: + CPU: AnyCPU + OSXIntel64: + enabled: 1 + settings: + CPU: AnyCPU + OSXUniversal: + enabled: 1 + settings: + CPU: AnyCPU + Win: + enabled: 0 + settings: + CPU: AnyCPU + Win64: + enabled: 0 + settings: + CPU: AnyCPU + iOS: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/WebView.bundle/Contents/Info.plist b/Assets/Plugins/WebView.bundle/Contents/Info.plist new file mode 100644 index 00000000..de16a012 --- /dev/null +++ b/Assets/Plugins/WebView.bundle/Contents/Info.plist @@ -0,0 +1,48 @@ + + + + + BuildMachineOSBuild + 25F80 + CFBundleDevelopmentRegion + English + CFBundleExecutable + WebView + CFBundleIdentifier + net.gree.unitywebview.WebView + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + WebView + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + 1 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 25F70 + DTPlatformName + macosx + DTPlatformVersion + 26.5 + DTSDKBuild + 25F70 + DTSDKName + macosx26.5 + DTXcode + 2650 + DTXcodeBuild + 17F42 + LSMinimumSystemVersion + 10.13 + + diff --git a/Assets/Plugins/WebView.bundle/Contents/MacOS/WebView b/Assets/Plugins/WebView.bundle/Contents/MacOS/WebView new file mode 100644 index 00000000..2befd9c7 Binary files /dev/null and b/Assets/Plugins/WebView.bundle/Contents/MacOS/WebView differ diff --git a/Assets/Plugins/WebView.bundle/Contents/Resources/InfoPlist.strings b/Assets/Plugins/WebView.bundle/Contents/Resources/InfoPlist.strings new file mode 100644 index 00000000..5e45963c Binary files /dev/null and b/Assets/Plugins/WebView.bundle/Contents/Resources/InfoPlist.strings differ diff --git a/Assets/Plugins/WebView.bundle/Contents/_CodeSignature/CodeResources b/Assets/Plugins/WebView.bundle/Contents/_CodeSignature/CodeResources new file mode 100644 index 00000000..f4d2e431 --- /dev/null +++ b/Assets/Plugins/WebView.bundle/Contents/_CodeSignature/CodeResources @@ -0,0 +1,128 @@ + + + + + files + + Resources/InfoPlist.strings + + MiLKDDnrUKr4EmuvhS5VQwxHGK8= + + + files2 + + Resources/InfoPlist.strings + + hash2 + + Oc8u4Ht7Mz58F50L9NeYpbcq9qTlhPUeZCcDu/pPyCg= + + + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/Assets/Plugins/Windows.meta b/Assets/Plugins/Windows.meta new file mode 100644 index 00000000..4c07dfab --- /dev/null +++ b/Assets/Plugins/Windows.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9a69d5fe42677e84b8100f858cb66df7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Windows/x64.meta b/Assets/Plugins/Windows/x64.meta new file mode 100644 index 00000000..6d0d8b42 --- /dev/null +++ b/Assets/Plugins/Windows/x64.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0763797fead754049b4255cee0993cb7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Windows/x64/README.txt b/Assets/Plugins/Windows/x64/README.txt new file mode 100644 index 00000000..51c69ca2 --- /dev/null +++ b/Assets/Plugins/Windows/x64/README.txt @@ -0,0 +1,4 @@ +Place the Windows WebView plugin DLL here: + WebView.dll (64-bit, built from plugins/Windows) + +Build instructions: see plugins/Windows/README.md diff --git a/Assets/Plugins/Windows/x64/README.txt.meta b/Assets/Plugins/Windows/x64/README.txt.meta new file mode 100644 index 00000000..f1b77afa --- /dev/null +++ b/Assets/Plugins/Windows/x64/README.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f62969be983297d4aa100a72a1ef672d +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Windows/x64/WebView.dll b/Assets/Plugins/Windows/x64/WebView.dll new file mode 100644 index 00000000..34243f2e Binary files /dev/null and b/Assets/Plugins/Windows/x64/WebView.dll differ diff --git a/Assets/Plugins/Windows/x64/WebView.dll.meta b/Assets/Plugins/Windows/x64/WebView.dll.meta new file mode 100644 index 00000000..a9dd066f --- /dev/null +++ b/Assets/Plugins/Windows/x64/WebView.dll.meta @@ -0,0 +1,70 @@ +fileFormatVersion: 2 +guid: 8c2ac249de280af4ca5514719b5a934a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : + second: + enabled: 0 + settings: {} + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 0 + Exclude Linux64: 0 + Exclude OSXUniversal: 0 + Exclude Win: 1 + Exclude Win64: 0 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: x86_64 + DefaultValueInitialized: true + OS: Windows + - first: + Standalone: Linux64 + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: x86_64 + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 1 + settings: + CPU: x86_64 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Windows/x86.meta b/Assets/Plugins/Windows/x86.meta new file mode 100644 index 00000000..0dab753e --- /dev/null +++ b/Assets/Plugins/Windows/x86.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 796e71d62d97fe14fa9d58010d2976fb +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Windows/x86/README.txt b/Assets/Plugins/Windows/x86/README.txt new file mode 100644 index 00000000..ceabd77e --- /dev/null +++ b/Assets/Plugins/Windows/x86/README.txt @@ -0,0 +1,4 @@ +Place the Windows WebView plugin DLL here: + WebView.dll (32-bit, built from plugins/Windows) + +Build instructions: see plugins/Windows/README.md diff --git a/Assets/Plugins/Windows/x86/README.txt.meta b/Assets/Plugins/Windows/x86/README.txt.meta new file mode 100644 index 00000000..e8efe961 --- /dev/null +++ b/Assets/Plugins/Windows/x86/README.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ea032e1e67ffb2845b15ed2d0ca48d7a +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Windows/x86/WebView.dll b/Assets/Plugins/Windows/x86/WebView.dll new file mode 100644 index 00000000..908e4d9c Binary files /dev/null and b/Assets/Plugins/Windows/x86/WebView.dll differ diff --git a/Assets/Plugins/Windows/x86/WebView.dll.meta b/Assets/Plugins/Windows/x86/WebView.dll.meta new file mode 100644 index 00000000..7ce685e3 --- /dev/null +++ b/Assets/Plugins/Windows/x86/WebView.dll.meta @@ -0,0 +1,70 @@ +fileFormatVersion: 2 +guid: ed66942567a0baa4e99daba51749d1c5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : + second: + enabled: 0 + settings: {} + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 0 + Exclude Linux64: 0 + Exclude OSXUniversal: 0 + Exclude Win: 0 + Exclude Win64: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: x86 + DefaultValueInitialized: true + OS: Windows + - first: + Standalone: Linux64 + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: x86_64 + - first: + Standalone: Win + second: + enabled: 1 + settings: + CPU: x86 + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: None + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/WebView.mm b/Assets/Plugins/iOS/WebView.mm index 4620012e..01d6dfc4 100644 --- a/Assets/Plugins/iOS/WebView.mm +++ b/Assets/Plugins/iOS/WebView.mm @@ -129,6 +129,7 @@ extern "C" void UnitySendMessage(const char *, const char *, const char *); UIView *webView; NSString *gameObjectName; NSMutableDictionary *customRequestHeader; + BOOL googleAppRedirectionEnabled; BOOL alertDialogEnabled; NSRegularExpression *allowRegex; NSRegularExpression *denyRegex; @@ -154,6 +155,7 @@ static NSMutableArray *_instances = [[NSMutableArray alloc] init]; gameObjectName = [NSString stringWithUTF8String:gameObjectName_]; customRequestHeader = [[NSMutableDictionary alloc] init]; + googleAppRedirectionEnabled = false; alertDialogEnabled = true; allowRegex = nil; denyRegex = nil; @@ -169,7 +171,8 @@ static NSMutableArray *_instances = [[NSMutableArray alloc] init]; WKUserContentController *controller = [[WKUserContentController alloc] init]; [controller addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"unityControl"]; [controller addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"saveDataURL"]; - NSString *str = @"\ + { + NSString *str = @"\ window.Unity = { \ call: function(msg) { \ window.webkit.messageHandlers.unityControl.postMessage(msg); \ @@ -179,8 +182,11 @@ window.Unity = { \ } \ }; \ "; + WKUserScript *script = [[WKUserScript alloc] initWithSource:str injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; + [controller addUserScript:script]; + } if (!zoom) { - str = [str stringByAppendingString:@"\ + NSString *str = @"\ (function() { \ var meta = document.querySelector('meta[name=viewport]'); \ if (meta == null) { \ @@ -191,12 +197,10 @@ window.Unity = { \ var head = document.getElementsByTagName('head')[0]; \ head.appendChild(meta); \ })(); \ -" - ]; +"; + WKUserScript *script = [[WKUserScript alloc] initWithSource:str injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES]; + [controller addUserScript:script]; } - WKUserScript *script - = [[WKUserScript alloc] initWithSource:str injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES]; - [controller addUserScript:script]; configuration.userContentController = controller; configuration.allowsInlineMediaPlayback = true; if (@available(iOS 10.0, *)) { @@ -267,6 +271,12 @@ window.Unity = { \ [view addSubview:webView]; + //set webview for Unity 6 accessibility hierarchy + NSMutableArray *accessibilityElements + = view.accessibilityElements ? [view.accessibilityElements mutableCopy] : [NSMutableArray array]; + [accessibilityElements addObject:(UIAccessibilityElement *)webView]; + view.accessibilityElements = accessibilityElements; + return self; } @@ -284,6 +294,13 @@ window.Unity = { \ [webView0 stopLoading]; [webView0 removeFromSuperview]; [webView0 removeObserver:self forKeyPath:@"loading"]; + + //remove the WebViewObject from Unity hierarchy tree + UIView *view = UnityGetGLViewController().view; + NSMutableArray *accessibilityElements + = view.accessibilityElements ? [view.accessibilityElements mutableCopy] : [NSMutableArray array]; + [accessibilityElements removeObject: (UIAccessibilityElement *)webView0]; + view.accessibilityElements = accessibilityElements; } basicAuthPassword = nil; basicAuthUserName = nil; @@ -306,6 +323,42 @@ window.Unity = { \ }]; } ++ (void)clearCookie:(const char *)name of:(const char *)url +{ + NSURL *nsurl = [NSURL URLWithString:[[NSString alloc] initWithUTF8String:url]]; + if (nsurl == nil) { + return; + } + NSString *nsname = [NSString stringWithUTF8String:name]; + if (@available(iOS 9.0, *)) { + WKHTTPCookieStore *cookieStore = WKWebsiteDataStore.defaultDataStore.httpCookieStore; + [cookieStore + getAllCookies:^(NSArray *array) { + [array + enumerateObjectsUsingBlock:^(NSHTTPCookie *cookie, NSUInteger idx, BOOL *stop) { + if ([cookie.name isEqualToString:nsname] + && [cookie.domain isEqualToString:nsurl.host] + && [cookie.path isEqualToString:nsurl.path]) { + [cookieStore deleteCookie:cookie completionHandler:^{}]; + } + }]; + }]; + } else { + NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; + if (cookieStorage == nil) { + // cf. https://stackoverflow.com/questions/33876295/nshttpcookiestorage-sharedhttpcookiestorage-comes-up-empty-in-10-11 + cookieStorage = [NSHTTPCookieStorage sharedCookieStorageForGroupContainerIdentifier:@"Cookies"]; + } + [[cookieStorage cookies] enumerateObjectsUsingBlock:^(NSHTTPCookie *cookie, NSUInteger idx, BOOL *stop) { + if ([cookie.name isEqualToString:nsname] + && [cookie.domain isEqualToString:nsurl.host] + && [cookie.path isEqualToString:nsurl.path]) { + [cookieStorage deleteCookie:cookie]; + } + }]; + } +} + + (void)clearCookies { [CWebViewPlugin resetSharedProcessPool]; @@ -537,7 +590,11 @@ window.Unity = { \ return; } if ([url rangeOfString:@"//itunes.apple.com/"].location != NSNotFound) { - [[UIApplication sharedApplication] openURL:nsurl]; + if (@available(iOS 10.0, *)) { + [[UIApplication sharedApplication] openURL:nsurl options:@{} completionHandler:nil]; + } else { + [[UIApplication sharedApplication] openURL:nsurl]; + } decisionHandler(WKNavigationActionPolicyCancel); return; } else if ([url hasPrefix:@"unity:"]) { @@ -554,7 +611,11 @@ window.Unity = { \ && ![url hasPrefix:@"http:"] && ![url hasPrefix:@"https:"]) { if([[UIApplication sharedApplication] canOpenURL:nsurl]) { - [[UIApplication sharedApplication] openURL:nsurl]; + if (@available(iOS 10.0, *)) { + [[UIApplication sharedApplication] openURL:nsurl options:@{} completionHandler:nil]; + } else { + [[UIApplication sharedApplication] openURL:nsurl]; + } } decisionHandler(WKNavigationActionPolicyCancel); return; @@ -568,7 +629,7 @@ window.Unity = { \ if (navigationAction.targetFrame != nil && navigationAction.targetFrame.isMainFrame) { // If the custom header is not attached, give it and make a request again. if (![self isSetupedCustomHeader:[navigationAction request]]) { - NSLog(@"navi ... %@", navigationAction); + //NSLog(@"navi ... %@", navigationAction); [wkWebView loadRequest:[self constructionCustomHeader:navigationAction.request]]; decisionHandler(WKNavigationActionPolicyCancel); return; @@ -576,6 +637,14 @@ window.Unity = { \ } } UnitySendMessage([gameObjectName UTF8String], "CallOnStarted", [url UTF8String]); + // cf. https://stackoverflow.com/questions/37086605/disable-wkwebview-for-opening-links-to-redirect-to-apps-installed-on-my-iphone/76948270#76948270 + if (!googleAppRedirectionEnabled + && [url hasPrefix:@"https://www.google.com/"] + && navigationAction.navigationType == WKNavigationTypeLinkActivated) { + [webView load:navigationAction.request]; + decisionHandler(WKNavigationActionPolicyCancel); + return; + } decisionHandler(WKNavigationActionPolicyAllow); } @@ -737,6 +806,13 @@ window.Unity = { \ webView.userInteractionEnabled = enabled; } +- (void)setGoogleAppRedirectionEnabled:(BOOL)enabled +{ + if (webView == nil) + return; + googleAppRedirectionEnabled = enabled; +} + - (void)setAlertDialogEnabled:(BOOL)enabled { alertDialogEnabled = enabled; @@ -951,6 +1027,7 @@ extern "C" { void *instance, float left, float top, float right, float bottom, BOOL relative); void _CWebViewPlugin_SetVisibility(void *instance, BOOL visibility); void _CWebViewPlugin_SetInteractionEnabled(void *instance, BOOL enabled); + void _CWebViewPlugin_SetGoogleAppRedirectionEnabled(void *instance, BOOL enabled); void _CWebViewPlugin_SetAlertDialogEnabled(void *instance, BOOL visibility); void _CWebViewPlugin_SetScrollbarsVisibility(void *instance, BOOL visibility); void _CWebViewPlugin_SetScrollBounceEnabled(void *instance, BOOL enabled); @@ -967,6 +1044,7 @@ extern "C" { void _CWebViewPlugin_AddCustomHeader(void *instance, const char *headerKey, const char *headerValue); void _CWebViewPlugin_RemoveCustomHeader(void *instance, const char *headerKey); void _CWebViewPlugin_ClearCustomHeader(void *instance); + void _CWebViewPlugin_ClearCookie(const char *url, const char *name); void _CWebViewPlugin_ClearCookies(); void _CWebViewPlugin_SaveCookies(); void _CWebViewPlugin_GetCookies(void *instance, const char *url); @@ -1040,6 +1118,14 @@ void _CWebViewPlugin_SetInteractionEnabled(void *instance, BOOL enabled) [webViewPlugin setInteractionEnabled:enabled]; } +void _CWebViewPlugin_SetGoogleAppRedirectionEnabled(void *instance, BOOL enabled) +{ + if (instance == NULL) + return; + CWebViewPlugin *webViewPlugin = (__bridge CWebViewPlugin *)instance; + [webViewPlugin setGoogleAppRedirectionEnabled:enabled]; +} + void _CWebViewPlugin_SetAlertDialogEnabled(void *instance, BOOL enabled) { if (instance == NULL) @@ -1168,6 +1254,11 @@ void _CWebViewPlugin_ClearCustomHeader(void *instance) [webViewPlugin clearCustomRequestHeader]; } +void _CWebViewPlugin_ClearCookie(const char *url, const char *name) +{ + [CWebViewPlugin clearCookie:name of:url]; +} + void _CWebViewPlugin_ClearCookies() { [CWebViewPlugin clearCookies]; diff --git a/Assets/Plugins/iOS/WebViewWithUIWebView.mm b/Assets/Plugins/iOS/WebViewWithUIWebView.mm index 1f288658..7909a36f 100644 --- a/Assets/Plugins/iOS/WebViewWithUIWebView.mm +++ b/Assets/Plugins/iOS/WebViewWithUIWebView.mm @@ -182,6 +182,7 @@ extern "C" void UnitySendMessage(const char *, const char *, const char *); UIView *webView; NSString *gameObjectName; NSMutableDictionary *customRequestHeader; + BOOL googleAppRedirectionEnabled; BOOL alertDialogEnabled; NSRegularExpression *allowRegex; NSRegularExpression *denyRegex; @@ -207,6 +208,7 @@ static NSMutableArray *_instances = [[NSMutableArray alloc] init]; gameObjectName = [NSString stringWithUTF8String:gameObjectName_]; customRequestHeader = [[NSMutableDictionary alloc] init]; + googleAppRedirectionEnabled = false; alertDialogEnabled = true; allowRegex = nil; denyRegex = nil; @@ -222,7 +224,8 @@ static NSMutableArray *_instances = [[NSMutableArray alloc] init]; WKUserContentController *controller = [[WKUserContentController alloc] init]; [controller addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"unityControl"]; [controller addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"saveDataURL"]; - NSString *str = @"\ + { + NSString *str = @"\ window.Unity = { \ call: function(msg) { \ window.webkit.messageHandlers.unityControl.postMessage(msg); \ @@ -232,8 +235,11 @@ window.Unity = { \ } \ }; \ "; + WKUserScript *script = [[WKUserScript alloc] initWithSource:str injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; + [controller addUserScript:script]; + } if (!zoom) { - str = [str stringByAppendingString:@"\ + NSString *str = @"\ (function() { \ var meta = document.querySelector('meta[name=viewport]'); \ if (meta == null) { \ @@ -244,12 +250,10 @@ window.Unity = { \ var head = document.getElementsByTagName('head')[0]; \ head.appendChild(meta); \ })(); \ -" - ]; +"; + WKUserScript *script = [[WKUserScript alloc] initWithSource:str injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES]; + [controller addUserScript:script]; } - WKUserScript *script - = [[WKUserScript alloc] initWithSource:str injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES]; - [controller addUserScript:script]; configuration.userContentController = controller; configuration.allowsInlineMediaPlayback = true; if (@available(iOS 10.0, *)) { @@ -368,6 +372,42 @@ window.Unity = { \ }]; } ++ (void)clearCookie:(const char *)name of:(const char *)url +{ + NSURL *nsurl = [NSURL URLWithString:[[NSString alloc] initWithUTF8String:url]]; + if (nsurl == nil) { + return; + } + NSString *nsname = [NSString stringWithUTF8String:name]; + if (@available(iOS 9.0, *)) { + WKHTTPCookieStore *cookieStore = WKWebsiteDataStore.defaultDataStore.httpCookieStore; + [cookieStore + getAllCookies:^(NSArray *array) { + [array + enumerateObjectsUsingBlock:^(NSHTTPCookie *cookie, NSUInteger idx, BOOL *stop) { + if ([cookie.name isEqualToString:nsname] + && [cookie.domain isEqualToString:nsurl.host] + && [cookie.path isEqualToString:nsurl.path]) { + [cookieStore deleteCookie:cookie completionHandler:^{}]; + } + }]; + }]; + } else { + NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; + if (cookieStorage == nil) { + // cf. https://stackoverflow.com/questions/33876295/nshttpcookiestorage-sharedhttpcookiestorage-comes-up-empty-in-10-11 + cookieStorage = [NSHTTPCookieStorage sharedCookieStorageForGroupContainerIdentifier:@"Cookies"]; + } + [[cookieStorage cookies] enumerateObjectsUsingBlock:^(NSHTTPCookie *cookie, NSUInteger idx, BOOL *stop) { + if ([cookie.name isEqualToString:nsname] + && [cookie.domain isEqualToString:nsurl.host] + && [cookie.path isEqualToString:nsurl.path]) { + [cookieStorage deleteCookie:cookie]; + } + }]; + } +} + + (void)clearCookies { [CWebViewPlugin resetSharedProcessPool]; @@ -606,7 +646,11 @@ window.Unity = { \ return NO; } if ([url rangeOfString:@"//itunes.apple.com/"].location != NSNotFound) { - [[UIApplication sharedApplication] openURL:nsurl]; + if (@available(iOS 10.0, *)) { + [[UIApplication sharedApplication] openURL:nsurl options:@{} completionHandler:nil]; + } else { + [[UIApplication sharedApplication] openURL:nsurl]; + } return NO; } else if ([url hasPrefix:@"unity:"]) { UnitySendMessage([gameObjectName UTF8String], "CallFromJS", [[url substringFromIndex:6] UTF8String]); @@ -652,7 +696,11 @@ window.Unity = { \ return; } if ([url rangeOfString:@"//itunes.apple.com/"].location != NSNotFound) { - [[UIApplication sharedApplication] openURL:nsurl]; + if (@available(iOS 10.0, *)) { + [[UIApplication sharedApplication] openURL:nsurl options:@{} completionHandler:nil]; + } else { + [[UIApplication sharedApplication] openURL:nsurl]; + } decisionHandler(WKNavigationActionPolicyCancel); return; } else if ([url hasPrefix:@"unity:"]) { @@ -669,7 +717,11 @@ window.Unity = { \ && ![url hasPrefix:@"http:"] && ![url hasPrefix:@"https:"]) { if([[UIApplication sharedApplication] canOpenURL:nsurl]) { - [[UIApplication sharedApplication] openURL:nsurl]; + if (@available(iOS 10.0, *)) { + [[UIApplication sharedApplication] openURL:nsurl options:@{} completionHandler:nil]; + } else { + [[UIApplication sharedApplication] openURL:nsurl]; + } } decisionHandler(WKNavigationActionPolicyCancel); return; @@ -683,7 +735,7 @@ window.Unity = { \ if (navigationAction.targetFrame != nil && navigationAction.targetFrame.isMainFrame) { // If the custom header is not attached, give it and make a request again. if (![self isSetupedCustomHeader:[navigationAction request]]) { - NSLog(@"navi ... %@", navigationAction); + //NSLog(@"navi ... %@", navigationAction); [wkWebView loadRequest:[self constructionCustomHeader:navigationAction.request]]; decisionHandler(WKNavigationActionPolicyCancel); return; @@ -691,6 +743,14 @@ window.Unity = { \ } } UnitySendMessage([gameObjectName UTF8String], "CallOnStarted", [url UTF8String]); + // cf. https://stackoverflow.com/questions/37086605/disable-wkwebview-for-opening-links-to-redirect-to-apps-installed-on-my-iphone/76948270#76948270 + if (!googleAppRedirectionEnabled + && [url hasPrefix:@"https://www.google.com/"] + && navigationAction.navigationType == WKNavigationTypeLinkActivated) { + [webView load:navigationAction.request]; + decisionHandler(WKNavigationActionPolicyCancel); + return; + } decisionHandler(WKNavigationActionPolicyAllow); } @@ -852,6 +912,13 @@ window.Unity = { \ webView.userInteractionEnabled = enabled; } +- (void)setGoogleAppRedirectionEnabled:(BOOL)enabled +{ + if (webView == nil) + return; + googleAppRedirectionEnabled = enabled; +} + - (void)setAlertDialogEnabled:(BOOL)enabled { alertDialogEnabled = enabled; @@ -1044,6 +1111,7 @@ extern "C" { void *instance, float left, float top, float right, float bottom, BOOL relative); void _CWebViewPlugin_SetVisibility(void *instance, BOOL visibility); void _CWebViewPlugin_SetInteractionEnabled(void *instance, BOOL enabled); + void _CWebViewPlugin_SetGoogleAppRedirectionEnabled(void *instance, BOOL enabled); void _CWebViewPlugin_SetAlertDialogEnabled(void *instance, BOOL visibility); void _CWebViewPlugin_SetScrollbarsVisibility(void *instance, BOOL visibility); void _CWebViewPlugin_SetScrollBounceEnabled(void *instance, BOOL enabled); @@ -1060,6 +1128,7 @@ extern "C" { void _CWebViewPlugin_AddCustomHeader(void *instance, const char *headerKey, const char *headerValue); void _CWebViewPlugin_RemoveCustomHeader(void *instance, const char *headerKey); void _CWebViewPlugin_ClearCustomHeader(void *instance); + void _CWebViewPlugin_ClearCookie(const char *url, const char *name); void _CWebViewPlugin_ClearCookies(); void _CWebViewPlugin_SaveCookies(); void _CWebViewPlugin_GetCookies(void *instance, const char *url); @@ -1131,6 +1200,14 @@ void _CWebViewPlugin_SetInteractionEnabled(void *instance, BOOL enabled) [webViewPlugin setInteractionEnabled:enabled]; } +void _CWebViewPlugin_SetGoogleAppRedirectionEnabled(void *instance, BOOL enabled) +{ + if (instance == NULL) + return; + CWebViewPlugin *webViewPlugin = (__bridge CWebViewPlugin *)instance; + [webViewPlugin setGoogleAppRedirectionEnabled:enabled]; +} + void _CWebViewPlugin_SetAlertDialogEnabled(void *instance, BOOL enabled) { if (instance == NULL) @@ -1259,6 +1336,11 @@ void _CWebViewPlugin_ClearCustomHeader(void *instance) [webViewPlugin clearCustomRequestHeader]; } +void _CWebViewPlugin_ClearCookie(const char *url, const char *name) +{ + [CWebViewPlugin clearCookie:name of:url]; +} + void _CWebViewPlugin_ClearCookies() { [CWebViewPlugin clearCookies]; diff --git a/Assets/RedHotRoast/Define/Model/Config/Game/CommonModel.cs b/Assets/RedHotRoast/Define/Model/Config/Game/CommonModel.cs index ffa89413..0109ce57 100644 --- a/Assets/RedHotRoast/Define/Model/Config/Game/CommonModel.cs +++ b/Assets/RedHotRoast/Define/Model/Config/Game/CommonModel.cs @@ -99,6 +99,7 @@ namespace RedHotRoast public int[] BalanceExchange; public int[] PotExchange; public int StatementSwitch; - + public string X_Redeemcode; + public string X_ShopURL; } } diff --git a/Assets/RedHotRoast/FGUI/package/tixian/com_confirm.cs b/Assets/RedHotRoast/FGUI/package/tixian/com_confirm.cs index 05bf6b61..91fcd618 100644 --- a/Assets/RedHotRoast/FGUI/package/tixian/com_confirm.cs +++ b/Assets/RedHotRoast/FGUI/package/tixian/com_confirm.cs @@ -50,8 +50,10 @@ namespace FGUI.tixian public cash_levelcom com_chlevel; public GGroup group_; public GTextField lab_mn; + public GTextField text_rate1; public GList list_kicket; public GTextField lab_mn2; + public GTextField text_rate; public GTextField lab_ticket; public GTextField lab_code; public btn_code btn_copy; @@ -116,8 +118,10 @@ namespace FGUI.tixian com_chlevel = (cash_levelcom)GetChildAt(60); group_ = (GGroup)GetChildAt(61); lab_mn = (GTextField)GetChildAt(65); + text_rate1 = (GTextField)GetChildAt(68); list_kicket = (GList)GetChildAt(70); lab_mn2 = (GTextField)GetChildAt(75); + text_rate = (GTextField)GetChildAt(78); lab_ticket = (GTextField)GetChildAt(83); lab_code = (GTextField)GetChildAt(85); btn_copy = (btn_code)GetChildAt(86); diff --git a/Assets/RedHotRoast/FGUI/package/tixian/com_redeem_code.cs b/Assets/RedHotRoast/FGUI/package/tixian/com_redeem_code.cs index 5f930f7f..7483eaeb 100644 --- a/Assets/RedHotRoast/FGUI/package/tixian/com_redeem_code.cs +++ b/Assets/RedHotRoast/FGUI/package/tixian/com_redeem_code.cs @@ -10,6 +10,7 @@ namespace FGUI.tixian public GTextField text_title; public GButton btn_close1; public GTextField lab_mn2; + public GTextField text_rate; public GTextField lab_ticket; public GTextField lab_code; public btn_code btn_copy; @@ -29,6 +30,7 @@ namespace FGUI.tixian text_title = (GTextField)GetChildAt(1); btn_close1 = (GButton)GetChildAt(2); lab_mn2 = (GTextField)GetChildAt(6); + text_rate = (GTextField)GetChildAt(9); lab_ticket = (GTextField)GetChildAt(14); lab_code = (GTextField)GetChildAt(16); btn_copy = (btn_code)GetChildAt(17); diff --git a/Assets/RedHotRoast/FGUI/package/tixian/com_saveingpot.cs b/Assets/RedHotRoast/FGUI/package/tixian/com_saveingpot.cs index 1c030633..21b73c22 100644 --- a/Assets/RedHotRoast/FGUI/package/tixian/com_saveingpot.cs +++ b/Assets/RedHotRoast/FGUI/package/tixian/com_saveingpot.cs @@ -40,8 +40,10 @@ namespace FGUI.tixian public btn_pay btn_watch; public GImage card_; public GTextField lab_mn; + public GTextField text_rate1; public GList list_kicket; public GTextField lab_mn2; + public GTextField text_rate; public GTextField lab_ticket; public GTextField lab_code; public btn_code btn_copy; @@ -95,8 +97,10 @@ namespace FGUI.tixian btn_watch = (btn_pay)GetChildAt(40); card_ = (GImage)GetChildAt(42); lab_mn = (GTextField)GetChildAt(45); + text_rate1 = (GTextField)GetChildAt(47); list_kicket = (GList)GetChildAt(51); lab_mn2 = (GTextField)GetChildAt(55); + text_rate = (GTextField)GetChildAt(57); lab_ticket = (GTextField)GetChildAt(62); lab_code = (GTextField)GetChildAt(64); btn_copy = (btn_code)GetChildAt(65); diff --git a/Assets/RedHotRoast/Helper/GameHelper.cs b/Assets/RedHotRoast/Helper/GameHelper.cs index 75947201..d1fb389d 100644 --- a/Assets/RedHotRoast/Helper/GameHelper.cs +++ b/Assets/RedHotRoast/Helper/GameHelper.cs @@ -1205,7 +1205,7 @@ namespace RedHotRoast { if (RainPlayUI == null) { - RainPlayUI = GameObject.Find("(RainPlayUI)sheep_play"); + RainPlayUI = GameObject.Find("(ArrowGameUI)com_arrow_game"); } if (RainPlayUI != null) { @@ -1906,7 +1906,9 @@ namespace RedHotRoast public static string GetPriceInt(decimal ch) { - return $"${ch:N0}"; + var vo = GetExchangeRateVo(); + ch *= (decimal)vo.Multi; + return $"{vo.Payicon}{ch:N0}"; } public static void InitNewWatchCDList(bool isNew = false) diff --git a/Assets/RedHotRoast/Manager/HallManager.cs b/Assets/RedHotRoast/Manager/HallManager.cs index f1d4a1f4..49eb9d7a 100644 --- a/Assets/RedHotRoast/Manager/HallManager.cs +++ b/Assets/RedHotRoast/Manager/HallManager.cs @@ -41,6 +41,7 @@ namespace RedHotRoast EnterHall(); UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.MainUI_Open); }); + CtrlDispatcher.Instance.AddListener(CtrlMsg.open_wb, OpenWb); AppDispatcher.Instance.AddListener(MainThreadMsg.App_Focus_True, BackToGame); InitSystem(); @@ -182,6 +183,43 @@ namespace RedHotRoast AudioManager.Instance.PlayBGM(AudioConst.GameBg); } } + + private void OpenWb(object obj) { + + if (obj is not SDKOpenConfig openConfig) return; + + // SdkConfigMgr.Instance.Open(openConfig.normal, openConfig.url); + SetCameraVisible(false); + + UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.H5UI_Open, openConfig); + + GameDispatcher.Instance.Dispatch(GameMsg.hideBroadCast); + } + + private Camera _gameCamera; + + public void SetCameraVisible(bool visible) + { + // 只在首次调用时查找 + if (_gameCamera == null) + { + // 使用 FindWithTag 确保能找到非激活对象 + + _gameCamera = GameObject.Find("GameCamera").GetComponent(); + + } + if (_gameCamera != null) + { + _gameCamera.enabled = visible; + } + else + { + Debug.LogError("GameCamera reference not found!"); + } + + GameHelper.ShowSheepPlayUI(visible); + } + #region 缓存资源 diff --git a/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Common_01_fui.bytes b/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Common_01_fui.bytes index 6c230c7a..fd222a10 100644 Binary files a/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Common_01_fui.bytes and b/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Common_01_fui.bytes differ diff --git a/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Img_02_atlas0.png b/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Img_02_atlas0.png index e9f4a121..fe581153 100644 Binary files a/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Img_02_atlas0.png and b/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Img_02_atlas0.png differ diff --git a/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Img_02_fui.bytes b/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Img_02_fui.bytes index 39f62185..57e31b4e 100644 Binary files a/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Img_02_fui.bytes and b/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Img_02_fui.bytes differ diff --git a/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Login_05_fui.bytes b/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Login_05_fui.bytes index ae811246..22a5a121 100644 Binary files a/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Login_05_fui.bytes and b/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Login_05_fui.bytes differ diff --git a/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Sign_06_fui.bytes b/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Sign_06_fui.bytes index b02f0923..f386ab60 100644 Binary files a/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Sign_06_fui.bytes and b/Assets/Resources/RedHotRoastAssets/FGUI/ZM_Sign_06_fui.bytes differ diff --git a/Assets/Resources/RedHotRoastAssets/FGUI/tixian_fui.bytes b/Assets/Resources/RedHotRoastAssets/FGUI/tixian_fui.bytes index 130a4358..5a80da84 100644 Binary files a/Assets/Resources/RedHotRoastAssets/FGUI/tixian_fui.bytes and b/Assets/Resources/RedHotRoastAssets/FGUI/tixian_fui.bytes differ diff --git a/Assets/Scenes/MainScene.unity b/Assets/Scenes/MainScene.unity index c2b9b527..c936b4f3 100644 --- a/Assets/Scenes/MainScene.unity +++ b/Assets/Scenes/MainScene.unity @@ -2255,6 +2255,50 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!1 &1944924004 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1944924006} + - component: {fileID: 1944924005} + m_Layer: 0 + m_Name: FreeWebViewManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1944924005 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1944924004} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 04c76fa88d6e411bbe47d0cfa321fc13, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!4 &1944924006 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1944924004} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 10004.443, y: 9995.665, z: 0.34530076} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1969760103 GameObject: m_ObjectHideFlags: 0 @@ -2491,3 +2535,4 @@ SceneRoots: - {fileID: 292594112} - {fileID: 1659410219} - {fileID: 1969760105} + - {fileID: 1944924006} diff --git a/Assets/Scripts/FreeWebViewManager.cs b/Assets/Scripts/FreeWebViewManager.cs new file mode 100644 index 00000000..b59f31f2 --- /dev/null +++ b/Assets/Scripts/FreeWebViewManager.cs @@ -0,0 +1,124 @@ +using Gree.UnityWebView; +using UnityEngine; + +public class FreeWebViewManager : MonoBehaviour +{ + public static FreeWebViewManager Instance; + private GameObject _webObj; + private WebViewObject1 _webView; + + private void Awake() + { + if (Instance != null) Destroy(gameObject); + else + { + Instance = this; + DontDestroyOnLoad(gameObject); + } + } + + private void Start() + { + initView(); + } + + public void initView() + { + if (_webObj != null) return; + + // 创建WebView对象 + _webObj = new GameObject("WebViewObject1"); + _webView = _webObj.AddComponent(); + + // 关键:开启WKWebView,规避苹果审核拒绝 + _webView.Init( + enableWKWebView: true, + cb: OnWebMessage // JS调用Unity回调 + ); + + float top_offset = 0;//fgui中的顶部信息的高度 + float buttom_offset = 155; + if (Screen.safeArea.y != 0) + {//刘海屏 + top_offset += Screen.safeArea.y; + } + + // 铺满屏幕,适配刘海安全区 + _webView.SetMargins(0, (int)top_offset, 0, (int)buttom_offset); + // 禁止下拉回弹(可选) + _webView.SetScrollBounceEnabled(false); + + _webView.LoadURL("about:blank"); + _webView.SetVisibility(false); + + } + + /// + /// 打开网页 + /// + public void OpenWeb(string url) + { + // if (_webObj != null) return; + // + // // 创建WebView对象 + // _webObj = new GameObject("WebViewObject1"); + // _webView = _webObj.AddComponent(); + // + // // 关键:开启WKWebView,规避苹果审核拒绝 + // _webView.Init( + // enableWKWebView: true, + // cb: OnWebMessage // JS调用Unity回调 + // ); + // + // float top_offset = 0;//fgui中的顶部信息的高度 + // float buttom_offset = 155; + // if (Screen.safeArea.y != 0) + // {//刘海屏 + // top_offset += Screen.safeArea.y; + // } + // + // // 铺满屏幕,适配刘海安全区 + // _webView.SetMargins(0, (int)top_offset, 0, (int)buttom_offset); + // // 禁止下拉回弹(可选) + // _webView.SetScrollBounceEnabled(false); + // + // 加载网页并显示 + _webView.LoadURL(url); + _webView.SetVisibility(true); + } + + // JS向Unity发消息:window.unity.call("func","参数") + void OnWebMessage(string msg) + { + Debug.Log("收到网页消息:" + msg); + } + + // C#调用网页JS + public void CallJs(string jsCode) + { + if (_webView != null) + _webView.EvaluateJS(jsCode); + } + + /// + /// 关闭网页(必调用,释放原生资源) + /// + public void CloseWeb() + { + if (_webObj != null) + { + _webView.SetVisibility(false); + } + } + + private void OnDestroy() + { + if (_webObj != null) + { + _webView.SetVisibility(false); + Destroy(_webObj); + _webObj = null; + _webView = null; + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/FreeWebViewManager.cs.meta b/Assets/Scripts/FreeWebViewManager.cs.meta new file mode 100644 index 00000000..effc2d29 --- /dev/null +++ b/Assets/Scripts/FreeWebViewManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 04c76fa88d6e411bbe47d0cfa321fc13 +timeCreated: 1784015216 \ No newline at end of file diff --git a/Assets/Scripts/ModuleManager/CtrlConst.cs b/Assets/Scripts/ModuleManager/CtrlConst.cs index 6cf813e2..d3a9ac5e 100644 --- a/Assets/Scripts/ModuleManager/CtrlConst.cs +++ b/Assets/Scripts/ModuleManager/CtrlConst.cs @@ -85,5 +85,6 @@ namespace RedHotRoast public const string GameAgainCtrl = "GameAgainCtrl"; public const string ArrowSettingCtrl = "ArrowSettingCtrl"; public const string ArrowGameResultCtrl = "ArrowGameResultCtrl"; + public const string RedeemCodeCtrl = "RedeemCodeCtrl"; } } \ No newline at end of file diff --git a/Assets/Scripts/ModuleManager/ModelConst.cs b/Assets/Scripts/ModuleManager/ModelConst.cs index fd2d9ee1..715a7cce 100644 --- a/Assets/Scripts/ModuleManager/ModelConst.cs +++ b/Assets/Scripts/ModuleManager/ModelConst.cs @@ -83,5 +83,6 @@ namespace RedHotRoast public const string GameAgainModel = "GameAgainModel"; public const string ArrowSettingModel = "ArrowSettingModel"; public const string ArrowGameResultModel = "ArrowGameResultModel"; + public const string RedeemCodeModel = "RedeemCodeModel"; } } \ No newline at end of file diff --git a/Assets/Scripts/ModuleManager/ModuleManagerRegister.cs b/Assets/Scripts/ModuleManager/ModuleManagerRegister.cs index eb985ed4..5e6c46ae 100644 --- a/Assets/Scripts/ModuleManager/ModuleManagerRegister.cs +++ b/Assets/Scripts/ModuleManager/ModuleManagerRegister.cs @@ -77,6 +77,7 @@ namespace RedHotRoast moduleManager.AddModel(ModelConst.GameAgainModel, new GameAgainModel()); moduleManager.AddModel(ModelConst.ArrowSettingModel, new ArrowSettingModel()); moduleManager.AddModel(ModelConst.ArrowGameResultModel, new ArrowGameResultModel()); + moduleManager.AddModel(ModelConst.RedeemCodeModel, new RedeemCodeModel()); } public static void AutoRegisterUICtrl() { @@ -154,6 +155,7 @@ namespace RedHotRoast moduleManager.AddUICtrl(UICtrlConst.GameAgainUICtrl, new GameAgainUICtrl()); moduleManager.AddUICtrl(UICtrlConst.ArrowSettingUICtrl, new ArrowSettingUICtrl()); moduleManager.AddUICtrl(UICtrlConst.ArrowGameResultUICtrl, new ArrowGameResultUICtrl()); + moduleManager.AddUICtrl(UICtrlConst.RedeemCodeUICtrl, new RedeemCodeUICtrl()); } public static void AutoRegisterCtrl() @@ -238,6 +240,7 @@ namespace RedHotRoast moduleManager.AddCtrl(CtrlConst.GameAgainCtrl, new GameAgainCtrl()); moduleManager.AddCtrl(CtrlConst.ArrowSettingCtrl, new ArrowSettingCtrl()); moduleManager.AddCtrl(CtrlConst.ArrowGameResultCtrl, new ArrowGameResultCtrl()); + moduleManager.AddCtrl(CtrlConst.RedeemCodeCtrl, new RedeemCodeCtrl()); } public static void AutoRegisterUIType() @@ -319,6 +322,7 @@ namespace RedHotRoast moduleManager.AddUIType(UIConst.GameAgainUI, typeof(GameAgainUI)); moduleManager.AddUIType(UIConst.ArrowSettingUI, typeof(ArrowSettingUI)); moduleManager.AddUIType(UIConst.ArrowGameResultUI, typeof(ArrowGameResultUI)); + moduleManager.AddUIType(UIConst.RedeemCodeUI, typeof(RedeemCodeUI)); } diff --git a/Assets/Scripts/ModuleManager/UIConst.cs b/Assets/Scripts/ModuleManager/UIConst.cs index b4e54453..4bd78a06 100644 --- a/Assets/Scripts/ModuleManager/UIConst.cs +++ b/Assets/Scripts/ModuleManager/UIConst.cs @@ -82,6 +82,7 @@ namespace RedHotRoast public const string GameAgainUI = "GameAgainUI"; public const string ArrowSettingUI = "ArrowSettingUI"; public const string ArrowGameResultUI = "ArrowGameResultUI"; + public const string RedeemCodeUI = "RedeemCodeUI"; } diff --git a/Assets/Scripts/ModuleManager/UICtrlConst.cs b/Assets/Scripts/ModuleManager/UICtrlConst.cs index a7271db1..753455ab 100644 --- a/Assets/Scripts/ModuleManager/UICtrlConst.cs +++ b/Assets/Scripts/ModuleManager/UICtrlConst.cs @@ -83,5 +83,6 @@ namespace RedHotRoast public const string GameAgainUICtrl = "GameAgainUICtrl"; public const string ArrowSettingUICtrl = "ArrowSettingUICtrl"; public const string ArrowGameResultUICtrl = "ArrowGameResultUICtrl"; + public const string RedeemCodeUICtrl = "RedeemCodeUICtrl"; } } \ No newline at end of file diff --git a/Assets/Scripts/ModuleUI/ArrowGame/ArrowGameUI.cs b/Assets/Scripts/ModuleUI/ArrowGame/ArrowGameUI.cs index 56b12327..60c57ca6 100644 --- a/Assets/Scripts/ModuleUI/ArrowGame/ArrowGameUI.cs +++ b/Assets/Scripts/ModuleUI/ArrowGame/ArrowGameUI.cs @@ -2028,7 +2028,7 @@ namespace RedHotRoast var start = fguiPosition; var end = GameHelper.GetUICenterPosition(ui.com_money.GetChild("text_gold")); float[] cash_array = GameHelper.GetRewardValue(0); - var littleReward = GameHelper.GetExchangeRateVo().Multi * cash_array[0]; + var littleReward = Math.Round(GameHelper.GetExchangeRateVo().Multi * cash_array[0],2); Debug.Log($"小额奖励:{cash_array[0]} {littleReward}"); var rewardSingleData = new RewardSingleData(102, (decimal)littleReward, RewardOrigin.AdTask) diff --git a/Assets/Scripts/ModuleUI/ArrowGameResult/ArrowGameResultUI.cs b/Assets/Scripts/ModuleUI/ArrowGameResult/ArrowGameResultUI.cs index 97f169b9..bec1a468 100644 --- a/Assets/Scripts/ModuleUI/ArrowGameResult/ArrowGameResultUI.cs +++ b/Assets/Scripts/ModuleUI/ArrowGameResult/ArrowGameResultUI.cs @@ -344,7 +344,7 @@ namespace RedHotRoast GameDispatcher.Instance.Dispatch(GameMsg.GetReward, rewardData); DOVirtual.DelayedCall(1, () => { - DOVirtual.Float(0, (float)DataMgr.Ticket.Value, 1, + DOVirtual.Float(0, (float)DataMgr.Ticket.Value * GameHelper.GetExchangeRateVo().Multi, 1, value => { ui.top_money.GetChild("text_gold").text = ((decimal)value).ToString("0.00"); }); }); } diff --git a/Assets/Scripts/ModuleUI/H5/H5UI.cs b/Assets/Scripts/ModuleUI/H5/H5UI.cs index 9758be33..062f47c5 100644 --- a/Assets/Scripts/ModuleUI/H5/H5UI.cs +++ b/Assets/Scripts/ModuleUI/H5/H5UI.cs @@ -1,4 +1,5 @@ +using DG.Tweening; using DontConfuse; using FGUI.ZM_H5_15; using RedHotRoast; @@ -36,10 +37,24 @@ namespace RedHotRoast protected override void OnClose() { + GameDispatcher.Instance.Dispatch(GameMsg.StopArrowTouch, true); + GameDispatcher.Instance.Dispatch(GameMsg.showBroadCast); - WebviewManager.Instance.setInH5View(false); - WebviewManager.Instance.ShowH5View(false); + + HallManager.Instance.SetCameraVisible(true); + + if (_config.normal) + { + WebviewManager.Instance.setInH5View(false); + WebviewManager.Instance.ShowH5View(false); + } + else + { + FreeWebViewManager.Instance.CloseWeb(); + } } + + private SDKOpenConfig _config; protected override void OnBind() { @@ -48,12 +63,26 @@ namespace RedHotRoast protected override void OnOpenBefore(object args) { + if (args is not SDKOpenConfig openConfig) return; + + _config = openConfig; + GameDispatcher.Instance.Dispatch(GameMsg.StopArrowTouch, false); - WebviewManager.Instance.setInH5View(true); GameDispatcher.Instance.Dispatch(GameMsg.hideBroadCast); // delayedCall = DOVirtual.DelayedCall(0.3f, () => // { - WebviewManager.Instance.ShowH5View(true); + if (_config.normal) + { + WebviewManager.Instance.setInH5View(true); + WebviewManager.Instance.ShowH5View(true); + } + else + { + DOVirtual.DelayedCall(0.2f, () => + { + FreeWebViewManager.Instance.OpenWeb(_config.url); + }); + } ui.btn_close.SetClick(() => { diff --git a/Assets/Scripts/ModuleUI/Hall/HallUI.cs b/Assets/Scripts/ModuleUI/Hall/HallUI.cs index 542eb209..e0916944 100644 --- a/Assets/Scripts/ModuleUI/Hall/HallUI.cs +++ b/Assets/Scripts/ModuleUI/Hall/HallUI.cs @@ -491,7 +491,7 @@ namespace RedHotRoast ui.btn_wv.visible = GameHelper.IsGiftSwitch(); ui.btn_wv.SetClick(() => { - UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.H5UI_Open); + // UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.H5UI_Open); }); ui.btn_egg.SetClick(OnClickEgg); diff --git a/Assets/Scripts/ModuleUI/PettyAward/PettyAwardUI.cs b/Assets/Scripts/ModuleUI/PettyAward/PettyAwardUI.cs index 3d14fd94..7134c8dc 100644 --- a/Assets/Scripts/ModuleUI/PettyAward/PettyAwardUI.cs +++ b/Assets/Scripts/ModuleUI/PettyAward/PettyAwardUI.cs @@ -90,7 +90,7 @@ namespace RedHotRoast _mLastState = DataMgr.PettyState.Value; // Debug.Log($"PettyState============: {DataMgr.PettyState.Value}"); var num = GameHelper.GetCommonModel().SmallReward; - ui.com_get_panel.text_reward.text = $"{GameHelper.GetExchangeRateVo().Payicon}{GameHelper.Get102Str(num)}"; + ui.com_get_panel.text_reward.text = $"{GameHelper.Get102Str(num)}"; ui.com_get_panel.btn_get.SetClick(GotoEnterAccount); @@ -252,12 +252,12 @@ namespace RedHotRoast var pettyAmount = DataMgr.PettyAmount.Value; if (pettyAmount != 0) { - ui.com_detail.text_amount.SetVar("num", $" {GameHelper.GetExchangeRateVo().Payicon}{GameHelper.Get102Str(pettyAmount)}").FlushVars(); + ui.com_detail.text_amount.SetVar("num", $" {GameHelper.Get102Str(pettyAmount)}").FlushVars(); } else { var num = GameHelper.GetCommonModel().SmallReward; - ui.com_detail.text_amount.SetVar("num", $" {GameHelper.GetExchangeRateVo().Payicon}{GameHelper.Get102Str(num)}").FlushVars(); + ui.com_detail.text_amount.SetVar("num", $" {GameHelper.Get102Str(num)}").FlushVars(); DataMgr.PettyAmount.Value = num; } diff --git a/Assets/Scripts/ModuleUI/RedeemCode.meta b/Assets/Scripts/ModuleUI/RedeemCode.meta new file mode 100644 index 00000000..5bd1f21d --- /dev/null +++ b/Assets/Scripts/ModuleUI/RedeemCode.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d727ad32d6e44862ba3e6eff7fe909aa +timeCreated: 1784016283 \ No newline at end of file diff --git a/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeCtrl.cs b/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeCtrl.cs new file mode 100644 index 00000000..bcfe8cb9 --- /dev/null +++ b/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeCtrl.cs @@ -0,0 +1,19 @@ +namespace RedHotRoast +{ + public class RedeemCodeCtrl : BaseCtrl + { + public static RedeemCodeCtrl Instance { get; private set; } + + private RedeemCodeModel model; + + protected override void OnInit() + { + Instance = this; + } + + protected override void OnDispose() + { + Instance = null; + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeCtrl.cs.meta b/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeCtrl.cs.meta new file mode 100644 index 00000000..d42646ae --- /dev/null +++ b/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeCtrl.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a93167d1dab140d2917cf72e64e89770 +timeCreated: 1782269723 \ No newline at end of file diff --git a/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeModel.cs b/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeModel.cs new file mode 100644 index 00000000..c23ad94a --- /dev/null +++ b/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeModel.cs @@ -0,0 +1,15 @@ +namespace RedHotRoast +{ + public class RedeemCodeModel : BaseModel + { + protected override void OnInit() + { + } + + protected override void OnDispose() + { + } + + + } +} \ No newline at end of file diff --git a/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeModel.cs.meta b/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeModel.cs.meta new file mode 100644 index 00000000..79e6eea8 --- /dev/null +++ b/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeModel.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 20b6c254390a48eabb165d883f54bf67 +timeCreated: 1782269723 \ No newline at end of file diff --git a/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeUI.cs b/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeUI.cs new file mode 100644 index 00000000..d8cb52af --- /dev/null +++ b/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeUI.cs @@ -0,0 +1,103 @@ + +using FGUI.tixian; +using IgnoreOPS; + +namespace RedHotRoast +{ + public class RedeemCodeUI : BaseUI + { + private RedeemCodeUICtrl ctrl; + private RedeemCodeModel model; + private com_redeem_code ui; + + public RedeemCodeUI(RedeemCodeUICtrl ctrl) : base(ctrl) + { + uiName = UIConst.RedeemCodeUI; + this.ctrl = ctrl; + } + + protected override void SetUIInfo(UIInfo uiInfo) + { + uiInfo.packageName = "tixian"; + uiInfo.assetName = "com_redeem_code"; + uiInfo.layerType = UILayerType.Popup; + uiInfo.isNeedOpenAnim = true; + uiInfo.isNeedCloseAnim = true; + uiInfo.isNeedUIMask = true; + } + + #region 生命周期 + + protected override void OnInit() + { + } + + protected override void OnClose() + { + GameDispatcher.Instance.Dispatch(GameMsg.StopArrowTouch, true); + } + + protected override void OnBind() + { + ui = baseUI as com_redeem_code; + } + + protected override void OnOpenBefore(object args) + { + GameDispatcher.Instance.Dispatch(GameMsg.StopArrowTouch, false); + + InitView(); + } + + protected override void OnOpen(object args) + { + } + + #endregion + + + private void InitView() + { + ui.lab_mn2.text = GameHelper.Get101Str(0); + + ui.lab_ticket.text = GameHelper.GetPriceInt(DataMgr.PettyAmount.Value); + + var strings = ConfigSystem.GetCommonConf().X_Redeemcode; + ui.lab_code.text = strings; + ui.text_rate.text = GameHelper.GetExchangeRateVo().Payicon + " 1"; + ui.btn_copy.SetClick(() => + { + GameHelper.CopyText(ui.lab_code.text); + }); + + ui.btn_contact_us.SetClick(() => + { + SDKOpenConfig openConfig = new SDKOpenConfig + { + normal = false, + url = ConfigSystem.GetCommonConf().X_ShopURL + }; + + CtrlDispatcher.Instance.Dispatch(CtrlMsg.open_wb, openConfig); + CtrlCloseUI(); + }); + + ui.btn_close1.SetClick(CtrlCloseUI); + + + } + #region 消息 + + protected override void AddListener() + { + + } + + protected override void RemoveListener() + { + + } + + #endregion + } +} diff --git a/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeUI.cs.meta b/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeUI.cs.meta new file mode 100644 index 00000000..cd1ea9c2 --- /dev/null +++ b/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeUI.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 02aaefad43c146b18cb726f31814007e +timeCreated: 1782269723 \ No newline at end of file diff --git a/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeUICtrl.cs b/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeUICtrl.cs new file mode 100644 index 00000000..ee12abcc --- /dev/null +++ b/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeUICtrl.cs @@ -0,0 +1,71 @@ +namespace RedHotRoast +{ + public class RedeemCodeUICtrl : BaseUICtrl + { + private RedeemCodeUI ui; + private RedeemCodeModel model; + + private uint openUIMsg = UICtrlMsg.RedeemCodeUI_Open; + private uint closeUIMsg = UICtrlMsg.RedeemCodeUI_Close; + + #region 生命周期 + protected override void OnInit() + { + //model = ModuleManager.Instance.GetModel(ModelConst.PettyAwardModel) as PettyAwardModel; + } + + protected override void OnDispose() + { + } + + public override void OpenUI(object args = null) + { + if (ui == null) + { + ui = new RedeemCodeUI(this); + ui.Open(args); + } + } + + public override void CloseUI(object args = null) + { + if (ui != null && !ui.isClose) + { + ui.Close(); + } + ui = null; + } + #endregion + + #region 消息 + public override uint GetOpenUIMsg(string uiName) + { + return openUIMsg; + } + public override uint GetCloseUIMsg(string uiName) + { + return closeUIMsg; + } + + protected override void AddListener() + { + uiCtrlDispatcher.AddListener(openUIMsg, OpenUI); + uiCtrlDispatcher.AddListener(closeUIMsg, CloseUI); + } + protected override void RemoveListener() + { + uiCtrlDispatcher.RemoveListener(openUIMsg, OpenUI); + uiCtrlDispatcher.RemoveListener(closeUIMsg, CloseUI); + } + + protected override void AddServerListener() + { + + } + protected override void RemoveServerListener() + { + + } + #endregion + } +} \ No newline at end of file diff --git a/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeUICtrl.cs.meta b/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeUICtrl.cs.meta new file mode 100644 index 00000000..7340c60d --- /dev/null +++ b/Assets/Scripts/ModuleUI/RedeemCode/RedeemCodeUICtrl.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: db2d94c85bfc42988faab968658f117e +timeCreated: 1782269723 \ No newline at end of file diff --git a/Assets/Scripts/ModuleUI/SaveingPot/SaveingPotUI.cs b/Assets/Scripts/ModuleUI/SaveingPot/SaveingPotUI.cs index a5a18ba2..81ac3c21 100644 --- a/Assets/Scripts/ModuleUI/SaveingPot/SaveingPotUI.cs +++ b/Assets/Scripts/ModuleUI/SaveingPot/SaveingPotUI.cs @@ -109,6 +109,9 @@ namespace RedHotRoast ui.btn_watch.SetClick(WatchBtnClick); AdExchangeManager.Instance.SetWatchAd(AdExchangeManager.SavingPotMakeupAd, ui.btn_task_watch as btn_watchAd, () => { }); AdExchangeManager.Instance.Start(); + + ui.text_rate1.text = GameHelper.GetExchangeRateVo().Payicon + " 1"; + ui.text_rate.text = GameHelper.GetExchangeRateVo().Payicon + " 1"; ad_cool_down = ConfigSystem.GetCommonConf().WwalaccelerationCD; HallManager.Instance.UpdateSecondEvent += updateSpeedCD; @@ -156,7 +159,8 @@ namespace RedHotRoast private void InitView() { Makeup_2 makeupVo = MakeupModel_2.GetData(makeupTaskData.tableId); - ui.text_ad.text = string.Format(GameHelper.getDesByKey("saving_pot_5"), makeupVo.ADIncrease); + ui.text_ad.text = string.Format(GameHelper.getDesByKey("saving_pot_5"), + SaveingPotHelper.getChNumber(makeupVo.ADIncrease)); string str = string.Format(GameHelper.getDesByKey("saving_pot_2"), makeupVo.PayIncrease); ui.text_pay.text = str; initTop(); @@ -213,7 +217,7 @@ namespace RedHotRoast }); HallManager.Instance.UpdateSecondEvent -= upLvWatchAdsBtn; - InitView(); + DOVirtual.DelayedCall(0.1f, InitView); } if (SaveData.GetSaveObject().saveingpot_ch > SaveData.GetSaveObject().last_saveingpot_ch) { @@ -344,7 +348,6 @@ namespace RedHotRoast btn_watchad.enabled = true; btn_watchad.can_buy.selectedIndex = 0; if (GameHelper.IsGiftSwitch() && ConfigSystem.GetCommonConf().PiggyBankSwitch == 1) btn_watchad.img_saveingpot.visible = true; - InitView(); } } diff --git a/Assets/Scripts/ModuleUI/SignInView/SignInViewUI.cs b/Assets/Scripts/ModuleUI/SignInView/SignInViewUI.cs index 5b8ccfee..9a3b2658 100644 --- a/Assets/Scripts/ModuleUI/SignInView/SignInViewUI.cs +++ b/Assets/Scripts/ModuleUI/SignInView/SignInViewUI.cs @@ -138,7 +138,7 @@ namespace RedHotRoast btnSign.title = signList[index].id + ""; btnSign.touchable = false; - btnSign.reward_num.text = GameHelper.Get101Str(signList[index].quantity[0]); + btnSign.reward_num.text = GameHelper.IsGiftSwitch()?GameHelper.getChString(signList[index].quantity[0]):GameHelper.Get101Str(signList[index].quantity[0]); var animName = "appear2"; if (index % 5 == 4) diff --git a/Assets/Scripts/SaveingPotClass.cs b/Assets/Scripts/SaveingPotClass.cs index 0d841b50..48b06a7f 100644 --- a/Assets/Scripts/SaveingPotClass.cs +++ b/Assets/Scripts/SaveingPotClass.cs @@ -63,7 +63,9 @@ public class SaveingPotClass // } // else // { - return $"{amount:N}"; + var exchangeRateVo = GameHelper.GetExchangeRateVo(); + var cash = exchangeRateVo.Multi * amount; + return $"{cash:N}"; //} } @@ -172,6 +174,8 @@ public class SaveingPotHelper } public static string getChNumber(float cash) { + var exchangeRateVo = GameHelper.GetExchangeRateVo(); + cash = exchangeRateVo.Multi * cash; return $"{cash:N}"; } diff --git a/Assets/TCJPLYRM1xJTSDK/ThirdParty/WebView/WebViewObject1.cs b/Assets/TCJPLYRM1xJTSDK/ThirdParty/WebView/WebViewObject1.cs new file mode 100644 index 00000000..712587f9 --- /dev/null +++ b/Assets/TCJPLYRM1xJTSDK/ThirdParty/WebView/WebViewObject1.cs @@ -0,0 +1,2161 @@ +/* + * Copyright (C) 2011 Keijiro Takahashi + * Copyright (C) 2012 GREE, Inc. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +using UnityEngine; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; +#if UNITY_2018_4_OR_NEWER +using UnityEngine.Networking; +#endif +#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX +using System.IO; +using System.Text.RegularExpressions; +using UnityEngine.EventSystems; +using UnityEngine.Rendering; +using UnityEngine.UI; +#endif +#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN +using UnityEngine.Rendering; +using UnityEngine.UI; +#endif +#if UNITY_ANDROID +using UnityEngine.Android; +#endif + +using Callback = System.Action; + +namespace Gree.UnityWebView +{ +#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + public class UnitySendMessageDispatcher + { + public static void Dispatch(string name, string method, string message) + { + GameObject obj = GameObject.Find(name); + if (obj != null) + obj.SendMessage(method, message); + } + } +#endif + + public class WebViewObject1 : MonoBehaviour + { + Callback onJS; + Callback onError; + Callback onHttpError; + Callback onStarted; + Callback onLoaded; + Callback onHooked; + Callback onCookies; + bool paused; + bool visibility; + bool alertDialogEnabled; + bool scrollBounceEnabled; + int mMarginLeft; + int mMarginTop; + int mMarginRight; + int mMarginBottom; + bool mMarginRelative; + float mMarginLeftComputed; + float mMarginTopComputed; + float mMarginRightComputed; + float mMarginBottomComputed; + bool mMarginRelativeComputed; +#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + public GameObject canvas; + Image bg; + IntPtr webView; + Rect rect; + Texture2D texture; +#if UNITY_2018_2_OR_NEWER +#else + byte[] textureDataBuffer; +#endif + string inputString = ""; + bool hasFocus; +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + public GameObject canvas; + Image bg; + IntPtr webView; + Rect rect; + Texture2D texture; + byte[] textureDataBuffer; + string inputString = ""; + bool hasFocus; +#elif UNITY_IPHONE + IntPtr webView; +#elif UNITY_ANDROID + AndroidJavaObject webView; + + bool mVisibility; + int mKeyboardVisibleHeight; + float mResumedTimestamp; + int mLastScreenHeight; +#if UNITYWEBVIEW_ANDROID_ENABLE_NAVIGATOR_ONLINE + float androidNetworkReachabilityCheckT0 = -1.0f; + NetworkReachability? androidNetworkReachability0 = null; +#endif + bool mAllowVideoCapture; + bool mAllowAudioCapture; + + void OnApplicationPause(bool paused) + { + this.paused = paused; + if (webView == null) + return; + // if (!paused && mKeyboardVisibleHeight > 0) + // { + // webView.Call("SetVisibility", false); + // mResumedTimestamp = Time.realtimeSinceStartup; + // } + webView.Call("OnApplicationPause", paused); + } + + void Update() + { + // NOTE: + // + // When OnApplicationPause(true) is called and the app is in closing, webView.Call(...) + // after that could cause crashes because underlying java instances were closed. + // + // This has not been cleary confirmed yet. However, as Update() is called once after + // OnApplicationPause(true), it is likely correct. + // + // Base on this assumption, we do nothing here if the app is paused. + // + // cf. https://github.com/gree/unity-webview/issues/991#issuecomment-1776628648 + // cf. https://docs.unity3d.com/2020.3/Documentation/Manual/ExecutionOrder.html + // + // In between frames + // + // * OnApplicationPause: This is called at the end of the frame where the pause is detected, + // effectively between the normal frame updates. One extra frame will be issued after + // OnApplicationPause is called to allow the game to show graphics that indicate the + // paused state. + // + if (paused) + return; + if (webView == null) + return; +#if UNITYWEBVIEW_ANDROID_ENABLE_NAVIGATOR_ONLINE + var t = Time.time; + if (t - 1.0f >= androidNetworkReachabilityCheckT0) + { + androidNetworkReachabilityCheckT0 = t; + var androidNetworkReachability = Application.internetReachability; + if (androidNetworkReachability0 != androidNetworkReachability) + { + androidNetworkReachability0 = androidNetworkReachability; + webView.Call("SetNetworkAvailable", androidNetworkReachability != NetworkReachability.NotReachable); + } + } +#endif + if (mResumedTimestamp != 0.0f && Time.realtimeSinceStartup - mResumedTimestamp > 0.5f) + { + mResumedTimestamp = 0.0f; + webView.Call("SetVisibility", mVisibility); + } + if (Screen.height != mLastScreenHeight) + { + mLastScreenHeight = Screen.height; + webView.Call("EvaluateJS", "(function() {var e = document.activeElement; if (e != null && e.tagName.toLowerCase() != 'body') {e.blur(); e.focus();}})()"); + } + for (;;) { + if (webView == null) + break; + var s = webView.Call("GetMessage"); + if (s == null) + break; + var i = s.IndexOf(':', 0); + if (i == -1) + continue; + switch (s.Substring(0, i)) { + case "CallFromJS": + CallFromJS(s.Substring(i + 1)); + break; + case "CallOnError": + CallOnError(s.Substring(i + 1)); + break; + case "CallOnHttpError": + CallOnHttpError(s.Substring(i + 1)); + break; + case "CallOnLoaded": + CallOnLoaded(s.Substring(i + 1)); + break; + case "CallOnStarted": + CallOnStarted(s.Substring(i + 1)); + break; + case "CallOnHooked": + CallOnHooked(s.Substring(i + 1)); + break; + case "CallOnCookies": + CallOnCookies(s.Substring(i + 1)); + break; + case "SetKeyboardVisible": + SetKeyboardVisible(s.Substring(i + 1)); + break; + case "RequestFileChooserPermissions": + RequestFileChooserPermissions(); + break; + } + } + } + + /// Called from Java native plugin to set when the keyboard is opened + public void SetKeyboardVisible(string keyboardVisibleHeight) + { + if (BottomAdjustmentDisabled()) + { + return; + } + var keyboardVisibleHeight0 = mKeyboardVisibleHeight; + var keyboardVisibleHeight1 = Int32.Parse(keyboardVisibleHeight); + if (keyboardVisibleHeight0 != keyboardVisibleHeight1) + { + mKeyboardVisibleHeight = keyboardVisibleHeight1; + SetMargins(mMarginLeft, mMarginTop, mMarginRight, mMarginBottom, mMarginRelative); + EvaluateJS("setTimeout(function(){if(document&&document.activeElement){document.activeElement.scrollIntoView();}}, 200);"); + } + } + + /// Called from Java native plugin to request permissions for the file chooser. + public void RequestFileChooserPermissions() + { + var permissions = new List(); + using (var version = new AndroidJavaClass("android.os.Build$VERSION")) + { + if (version.GetStatic("SDK_INT") >= 33) + { + if (!Permission.HasUserAuthorizedPermission("android.permission.READ_MEDIA_IMAGES")) + { + permissions.Add("android.permission.READ_MEDIA_IMAGES"); + } + if (!Permission.HasUserAuthorizedPermission("android.permission.READ_MEDIA_VIDEO")) + { + permissions.Add("android.permission.READ_MEDIA_VIDEO"); + } + if (!Permission.HasUserAuthorizedPermission("android.permission.READ_MEDIA_AUDIO")) + { + permissions.Add("android.permission.READ_MEDIA_AUDIO"); + } + } + else + { + if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageRead)) + { + permissions.Add(Permission.ExternalStorageRead); + } + if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite)) + { + permissions.Add(Permission.ExternalStorageWrite); + } + } + } +#if UNITYWEBVIEW_ANDROID_ENABLE_CAMERA + if (!Permission.HasUserAuthorizedPermission(Permission.Camera) && mAllowVideoCapture) + { + permissions.Add(Permission.Camera); + } +#endif +#if UNITYWEBVIEW_ANDROID_ENABLE_MICROPHONE + if (!Permission.HasUserAuthorizedPermission(Permission.Microphone) && mAllowAudioCapture) + { + permissions.Add(Permission.Microphone); + } +#endif + if (permissions.Count > 0) + { +#if UNITY_2020_2_OR_NEWER + var grantedCount = 0; + var deniedCount = 0; + var callbacks = new PermissionCallbacks(); + callbacks.PermissionGranted += (permission) => + { + grantedCount++; + if (grantedCount + deniedCount == permissions.Count) + { + StartCoroutine(CallOnRequestFileChooserPermissionsResult(grantedCount == permissions.Count)); + } + }; + callbacks.PermissionDenied += (permission) => + { + deniedCount++; + if (grantedCount + deniedCount == permissions.Count) + { + StartCoroutine(CallOnRequestFileChooserPermissionsResult(grantedCount == permissions.Count)); + } + }; + callbacks.PermissionDeniedAndDontAskAgain += (permission) => + { + deniedCount++; + if (grantedCount + deniedCount == permissions.Count) + { + StartCoroutine(CallOnRequestFileChooserPermissionsResult(grantedCount == permissions.Count)); + } + }; + Permission.RequestUserPermissions(permissions.ToArray(), callbacks); +#else + StartCoroutine(RequestFileChooserPermissionsCoroutine(permissions.ToArray())); +#endif + } + else + { + StartCoroutine(CallOnRequestFileChooserPermissionsResult(true)); + } + } + +#if UNITY_2020_2_OR_NEWER +#else + int mRequestPermissionPhase; + + IEnumerator RequestFileChooserPermissionsCoroutine(string[] permissions) + { + foreach (var permission in permissions) + { + mRequestPermissionPhase = 0; + Permission.RequestUserPermission(permission); + // waiting permission dialog that may not be opened. + for (var i = 0; i < 8 && mRequestPermissionPhase == 0; i++) + { + yield return new WaitForSeconds(0.25f); + } + if (mRequestPermissionPhase == 0) + { + // permission dialog was not opened. + continue; + } + while (mRequestPermissionPhase == 1) + { + yield return new WaitForSeconds(0.3f); + } + } + yield return new WaitForSeconds(0.3f); + var granted = 0; + foreach (var permission in permissions) + { + if (Permission.HasUserAuthorizedPermission(permission)) + { + granted++; + } + } + StartCoroutine(CallOnRequestFileChooserPermissionsResult(granted == permissions.Length)); + } + + void OnApplicationFocus(bool hasFocus) + { + if (hasFocus) + { + if (mRequestPermissionPhase == 1) + { + mRequestPermissionPhase = 2; + } + } + else + { + if (mRequestPermissionPhase == 0) + { + mRequestPermissionPhase = 1; + } + } + } +#endif + + private IEnumerator CallOnRequestFileChooserPermissionsResult(bool granted) + { + for (var i = 0; i < 3; i++) + { + yield return null; + } + webView.Call("OnRequestFileChooserPermissionsResult", granted); + } + + public int AdjustBottomMargin(int bottom) + { + if (BottomAdjustmentDisabled()) + { + return bottom; + } + else if (mKeyboardVisibleHeight <= 0) + { + return bottom; + } + else + { + int keyboardHeight = 0; + using (var unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) + using (var activity = unityClass.GetStatic("currentActivity")) + using (var player = activity.Get("mUnityPlayer")) + using (var view = player.Call("getView")) + using (var rect = new AndroidJavaObject("android.graphics.Rect")) + { + if (view.Call("getGlobalVisibleRect", rect)) + { + int h0 = rect.Get("bottom"); + view.Call("getWindowVisibleDisplayFrame", rect); + int h1 = rect.Get("bottom"); + keyboardHeight = h0 - h1; + } + } + return (bottom > keyboardHeight) ? bottom : keyboardHeight; + } + } + + private bool BottomAdjustmentDisabled() + { +#if UNITYWEBVIEW_ANDROID_FORCE_MARGIN_ADJUSTMENT_FOR_KEYBOARD + return false; +#else + return + !Screen.fullScreen + || ((Screen.autorotateToLandscapeLeft || Screen.autorotateToLandscapeRight) + && (Screen.autorotateToPortrait || Screen.autorotateToPortraitUpsideDown)); +#endif + } +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + IntPtr webView; +#else + IntPtr webView; +#endif + + void Awake() + { + alertDialogEnabled = true; + scrollBounceEnabled = true; + mMarginLeftComputed = -9999; + mMarginTopComputed = -9999; + mMarginRightComputed = -9999; + mMarginBottomComputed = -9999; + } + + public bool IsKeyboardVisible + { + get + { +#if !UNITY_EDITOR && UNITY_ANDROID + return mKeyboardVisibleHeight > 0; +#elif !UNITY_EDITOR && UNITY_IPHONE + return TouchScreenKeyboard.visible; +#else + return false; +#endif + } + } + +#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + [DllImport("WebView")] + private static extern string _CWebViewPlugin_GetAppPath(); + [DllImport("WebView")] + private static extern IntPtr _CWebViewPlugin_InitStatic( + bool inEditor, bool useMetal); + [DllImport("WebView")] + private static extern bool _CWebViewPlugin_IsInitialized( + IntPtr instance); + [DllImport("WebView")] + private static extern IntPtr _CWebViewPlugin_Init( + string gameObject, bool transparent, bool zoom, int width, int height, string ua, bool separated); + [DllImport("WebView")] + private static extern int _CWebViewPlugin_Destroy(IntPtr instance); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_SetRect( + IntPtr instance, int width, int height); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_SetVisibility( + IntPtr instance, bool visibility); + [DllImport("WebView")] + private static extern bool _CWebViewPlugin_SetURLPattern( + IntPtr instance, string allowPattern, string denyPattern, string hookPattern); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_LoadURL( + IntPtr instance, string url); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_LoadHTML( + IntPtr instance, string html, string baseUrl); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_EvaluateJS( + IntPtr instance, string url); + [DllImport("WebView")] + private static extern int _CWebViewPlugin_Progress( + IntPtr instance); + [DllImport("WebView")] + private static extern bool _CWebViewPlugin_CanGoBack( + IntPtr instance); + [DllImport("WebView")] + private static extern bool _CWebViewPlugin_CanGoForward( + IntPtr instance); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_GoBack( + IntPtr instance); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_GoForward( + IntPtr instance); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_Reload( + IntPtr instance); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_SendMouseEvent(IntPtr instance, int x, int y, float deltaY, int mouseState); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_SendKeyEvent(IntPtr instance, int x, int y, string keyChars, ushort keyCode, int keyState); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_Update(IntPtr instance, bool refreshBitmap, int devicePixelRatio); + [DllImport("WebView")] + private static extern int _CWebViewPlugin_BitmapWidth(IntPtr instance); + [DllImport("WebView")] + private static extern int _CWebViewPlugin_BitmapHeight(IntPtr instance); + [DllImport("WebView")] + private static extern bool _CWebViewPlugin_BitmapARGB(IntPtr instance); + [DllImport("WebView")] + private static extern IntPtr _CWebViewPlugin_Render(IntPtr instance, IntPtr textureBuffer); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_AddCustomHeader(IntPtr instance, string headerKey, string headerValue); + [DllImport("WebView")] + private static extern string _CWebViewPlugin_GetCustomHeaderValue(IntPtr instance, string headerKey); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_RemoveCustomHeader(IntPtr instance, string headerKey); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_ClearCustomHeader(IntPtr instance); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_ClearCookie(string url, string name); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_ClearCookies(); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_SaveCookies(); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_GetCookies(IntPtr instance, string url); + [DllImport("WebView")] + private static extern string _CWebViewPlugin_GetMessage(IntPtr instance); +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + [DllImport("WebView")] + private static extern string _CWebViewPlugin_GetAppPath(); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_InitStatic(bool inEditor, bool useMetal); + [DllImport("WebView")] + private static extern bool _CWebViewPlugin_IsInitialized(IntPtr instance); + [DllImport("WebView")] + private static extern IntPtr _CWebViewPlugin_Init(string gameObject, bool transparent, bool zoom, int width, int height, string ua, bool separated); + [DllImport("WebView")] + private static extern int _CWebViewPlugin_Destroy(IntPtr instance); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_SetRect(IntPtr instance, int width, int height); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_SetVisibility(IntPtr instance, bool visibility); + [DllImport("WebView")] + private static extern bool _CWebViewPlugin_SetURLPattern(IntPtr instance, string allowPattern, string denyPattern, string hookPattern); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_LoadURL(IntPtr instance, string url); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_LoadHTML(IntPtr instance, string html, string baseUrl); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_EvaluateJS(IntPtr instance, string url); + [DllImport("WebView")] + private static extern int _CWebViewPlugin_Progress(IntPtr instance); + [DllImport("WebView")] + private static extern bool _CWebViewPlugin_CanGoBack(IntPtr instance); + [DllImport("WebView")] + private static extern bool _CWebViewPlugin_CanGoForward(IntPtr instance); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_GoBack(IntPtr instance); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_GoForward(IntPtr instance); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_Reload(IntPtr instance); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_SendMouseEvent(IntPtr instance, int x, int y, float deltaY, int mouseState); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_SendKeyEvent(IntPtr instance, int x, int y, string keyChars, ushort keyCode, int keyState); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_Update(IntPtr instance, bool refreshBitmap, int devicePixelRatio); + [DllImport("WebView")] + private static extern int _CWebViewPlugin_BitmapWidth(IntPtr instance); + [DllImport("WebView")] + private static extern int _CWebViewPlugin_BitmapHeight(IntPtr instance); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_Render(IntPtr instance, IntPtr textureBuffer); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_AddCustomHeader(IntPtr instance, string headerKey, string headerValue); + [DllImport("WebView")] + private static extern string _CWebViewPlugin_GetCustomHeaderValue(IntPtr instance, string headerKey); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_RemoveCustomHeader(IntPtr instance, string headerKey); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_ClearCustomHeader(IntPtr instance); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_ClearCookie(string url, string name); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_ClearCookies(); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_SaveCookies(); + [DllImport("WebView")] + private static extern void _CWebViewPlugin_GetCookies(IntPtr instance, string url); + [DllImport("WebView")] + private static extern string _CWebViewPlugin_GetMessage(IntPtr instance); +#elif UNITY_IPHONE + [DllImport("__Internal")] + private static extern bool _CWebViewPlugin_IsInitialized( + IntPtr instance); + [DllImport("__Internal")] + private static extern IntPtr _CWebViewPlugin_Init(string gameObject, bool transparent, bool zoom, string ua, bool enableWKWebView, int wkContentMode, bool wkAllowsLinkPreview, bool wkAllowsBackForwardNavigationGestures, int radius); + [DllImport("__Internal")] + private static extern int _CWebViewPlugin_Destroy(IntPtr instance); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_SetMargins( + IntPtr instance, float left, float top, float right, float bottom, bool relative); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_SetVisibility( + IntPtr instance, bool visibility); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_SetScrollbarsVisibility( + IntPtr instance, bool visibility); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_SetAlertDialogEnabled( + IntPtr instance, bool enabled); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_SetScrollBounceEnabled( + IntPtr instance, bool enabled); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_SetInteractionEnabled( + IntPtr instance, bool enabled); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_SetGoogleAppRedirectionEnabled( + IntPtr instance, bool enabled); + [DllImport("__Internal")] + private static extern bool _CWebViewPlugin_SetURLPattern( + IntPtr instance, string allowPattern, string denyPattern, string hookPattern); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_LoadURL( + IntPtr instance, string url); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_LoadHTML( + IntPtr instance, string html, string baseUrl); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_EvaluateJS( + IntPtr instance, string url); + [DllImport("__Internal")] + private static extern int _CWebViewPlugin_Progress( + IntPtr instance); + [DllImport("__Internal")] + private static extern bool _CWebViewPlugin_CanGoBack( + IntPtr instance); + [DllImport("__Internal")] + private static extern bool _CWebViewPlugin_CanGoForward( + IntPtr instance); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_GoBack( + IntPtr instance); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_GoForward( + IntPtr instance); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_Reload( + IntPtr instance); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_AddCustomHeader(IntPtr instance, string headerKey, string headerValue); + [DllImport("__Internal")] + private static extern string _CWebViewPlugin_GetCustomHeaderValue(IntPtr instance, string headerKey); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_RemoveCustomHeader(IntPtr instance, string headerKey); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_ClearCustomHeader(IntPtr instance); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_ClearCookie(string url, string name); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_ClearCookies(); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_SaveCookies(); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_GetCookies(IntPtr instance, string url); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_SetBasicAuthInfo(IntPtr instance, string userName, string password); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_ClearCache(IntPtr instance, bool includeDiskFiles); + [DllImport("__Internal")] + private static extern void _CWebViewPlugin_SetSuspended(IntPtr instance, bool suspended); +#elif UNITY_WEBGL + [DllImport("__Internal")] + private static extern void _gree_unity_webview_init(string name); + [DllImport("__Internal")] + private static extern void _gree_unity_webview_setMargins(string name, int left, int top, int right, int bottom); + [DllImport("__Internal")] + private static extern void _gree_unity_webview_setVisibility(string name, bool visible); + [DllImport("__Internal")] + private static extern void _gree_unity_webview_loadURL(string name, string url); + [DllImport("__Internal")] + private static extern void _gree_unity_webview_evaluateJS(string name, string js); + [DllImport("__Internal")] + private static extern void _gree_unity_webview_destroy(string name); +#endif + + public static bool IsWebViewAvailable() + { +#if !UNITY_EDITOR && UNITY_ANDROID + using (var plugin = new AndroidJavaObject("net.gree.unitywebview.CWebViewPlugin")) + { + return plugin.CallStatic("IsWebViewAvailable"); + } +#else + return true; +#endif + } + + public bool IsInitialized() + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED + return true; +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED + return true; +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return false; + return _CWebViewPlugin_IsInitialized(webView); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return false; + return _CWebViewPlugin_IsInitialized(webView); +#elif UNITY_ANDROID + if (webView == null) + return false; + return webView.Call("IsInitialized"); +#endif + } + + public void Init( + Callback cb = null, + Callback err = null, + Callback httpErr = null, + Callback ld = null, + Callback started = null, + Callback hooked = null, + Callback cookies = null, + bool transparent = false, + bool zoom = true, + string ua = "", + int radius = 0, + // android + int androidForceDarkMode = 0, // 0: follow system setting, 1: force dark off, 2: force dark on + // ios + bool enableWKWebView = true, + int wkContentMode = 0, // 0: recommended, 1: mobile, 2: desktop + bool wkAllowsLinkPreview = true, + bool wkAllowsBackForwardNavigationGestures = true, + // editor + bool separated = false) + { +#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + _CWebViewPlugin_InitStatic( + Application.platform == RuntimePlatform.OSXEditor, + SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal); +#endif + onJS = cb; + onError = err; + onHttpError = httpErr; + onStarted = started; + onLoaded = ld; + onHooked = hooked; + onCookies = cookies; +#if UNITY_WEBGL +#if !UNITY_EDITOR + _gree_unity_webview_init(name); +#endif +#elif UNITY_WEBPLAYER + Application.ExternalCall("unityWebView.init", name); +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED + Debug.LogError("Webview is not supported on this platform."); +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + _CWebViewPlugin_InitStatic( + Application.platform == RuntimePlatform.WindowsEditor, + SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D11); + webView = _CWebViewPlugin_Init( + name, + transparent, + zoom, + Screen.width, + Screen.height, + ua +#if UNITY_EDITOR + , separated +#else + , false +#endif + ); + rect = new Rect(0, 0, Screen.width, Screen.height); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + { + var uri = new Uri(_CWebViewPlugin_GetAppPath()); + var info = File.ReadAllText(uri.LocalPath + "Contents/Info.plist"); + if (Regex.IsMatch(info, @"CFBundleGetInfoString\s*Unity version [5-9]\.[3-9]") + && !Regex.IsMatch(info, @"NSAppTransportSecurity\s*\s*NSAllowsArbitraryLoads\s*\s*")) { + Debug.LogWarning("WebViewObject: NSAppTransportSecurity isn't configured to allow HTTP. If you need to allow any HTTP access, please shutdown Unity and invoke:\n/usr/libexec/PlistBuddy -c \"Add NSAppTransportSecurity:NSAllowsArbitraryLoads bool true\" /Applications/Unity/Unity.app/Contents/Info.plist"); + } + } +#if UNITY_EDITOR_OSX + // if (string.IsNullOrEmpty(ua)) { + // ua = @"Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53"; + // } +#endif + webView = _CWebViewPlugin_Init( + name, + transparent, + zoom, + Screen.width, + Screen.height, + ua +#if UNITY_EDITOR + , separated +#else + , false +#endif + ); + rect = new Rect(0, 0, Screen.width, Screen.height); +#elif UNITY_IPHONE + webView = _CWebViewPlugin_Init(name, transparent, zoom, ua, enableWKWebView, wkContentMode, wkAllowsLinkPreview, wkAllowsBackForwardNavigationGestures, radius); +#elif UNITY_ANDROID + webView = new AndroidJavaObject("net.gree.unitywebview.CWebViewPlugin"); +#if UNITY_2021_1_OR_NEWER + webView.SetStatic("forceBringToFront", true); +#endif + webView.Call("Init", name, transparent, zoom, androidForceDarkMode, ua, radius); +#else + Debug.LogError("Webview is not supported on this platform."); +#endif + } + + protected virtual void OnDestroy() + { +#if UNITY_WEBGL +#if !UNITY_EDITOR + _gree_unity_webview_destroy(name); +#endif +#elif UNITY_WEBPLAYER + Application.ExternalCall("unityWebView.destroy", name); +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (bg != null) + { + Destroy(bg.gameObject); + } + if (webView == IntPtr.Zero) + return; + var ptr = webView; + webView = IntPtr.Zero; + _CWebViewPlugin_Destroy(ptr); + Destroy(texture); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + if (bg != null) { + Destroy(bg.gameObject); + } + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_Destroy(webView); + webView = IntPtr.Zero; + Destroy(texture); +#elif UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_Destroy(webView); + webView = IntPtr.Zero; +#elif UNITY_ANDROID + if (webView == null) + return; + webView.Call("Destroy"); + webView.Dispose(); + webView = null; +#endif + } + + public void Pause() + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN || UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + //TODO: UNSUPPORTED +#elif UNITY_IPHONE + // NOTE: this suspends media playback only. + if (webView == null) + return; + _CWebViewPlugin_SetSuspended(webView, true); +#elif UNITY_ANDROID + if (webView == null) + return; + webView.Call("Pause"); +#endif + } + + public void Resume() + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN || UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + //TODO: UNSUPPORTED +#elif UNITY_IPHONE + // NOTE: this resumes media playback only. + _CWebViewPlugin_SetSuspended(webView, false); +#elif UNITY_ANDROID + if (webView == null) + return; + webView.Call("Resume"); +#endif + } + + // Use this function instead of SetMargins to easily set up a centered window + // NOTE: for historical reasons, `center` means the lower left corner and positive y values extend up. + public void SetCenterPositionWithScale(Vector2 center, Vector2 scale) + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + float left = (Screen.width - scale.x) / 2.0f + center.x; + float right = Screen.width - (left + scale.x); + float bottom = (Screen.height - scale.y) / 2.0f + center.y; + float top = Screen.height - (bottom + scale.y); + SetMargins((int)left, (int)top, (int)right, (int)bottom); +#else + float left = (Screen.width - scale.x) / 2.0f + center.x; + float right = Screen.width - (left + scale.x); + float bottom = (Screen.height - scale.y) / 2.0f + center.y; + float top = Screen.height - (bottom + scale.y); + SetMargins((int)left, (int)top, (int)right, (int)bottom); +#endif + } + + public void SetMargins(int left, int top, int right, int bottom, bool relative = false) + { +#if UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED + return; +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return; +#elif UNITY_WEBPLAYER || UNITY_WEBGL +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + if (webView == IntPtr.Zero) + return; +#elif UNITY_IPHONE + if (webView == IntPtr.Zero) + return; +#elif UNITY_ANDROID + if (webView == null) + return; +#endif + + mMarginLeft = left; + mMarginTop = top; + mMarginRight = right; + mMarginBottom = bottom; + mMarginRelative = relative; + float ml, mt, mr, mb; +#if UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + ml = left; + mt = top; + mr = right; + mb = bottom; +#elif UNITY_WEBPLAYER || UNITY_WEBGL + ml = left; + mt = top; + mr = right; + mb = bottom; +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + ml = left; + mt = top; + mr = right; + mb = bottom; +#elif UNITY_IPHONE + if (relative) + { + float w = (float)Screen.width; + float h = (float)Screen.height; + ml = left / w; + mt = top / h; + mr = right / w; + mb = bottom / h; + } + else + { + ml = left; + mt = top; + mr = right; + mb = bottom; + } +#elif UNITY_ANDROID + if (relative) + { + float w = (float)Screen.width; + float h = (float)Screen.height; + int iw = Display.main.systemWidth; + int ih = Display.main.systemHeight; + if (!Screen.fullScreen) + { + using (var unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) + using (var activity = unityClass.GetStatic("currentActivity")) + using (var player = activity.Get("mUnityPlayer")) + using (var view = player.Call("getView")) + using (var rect = new AndroidJavaObject("android.graphics.Rect")) + { + view.Call("getDrawingRect", rect); + iw = rect.Call("width"); + ih = rect.Call("height"); + } + } + ml = left / w * iw; + mt = top / h * ih; + mr = right / w * iw; + mb = AdjustBottomMargin((int)(bottom / h * ih)); + } + else + { + ml = left; + mt = top; + mr = right; + mb = AdjustBottomMargin(bottom); + } +#endif + bool r = relative; + + if (ml == mMarginLeftComputed + && mt == mMarginTopComputed + && mr == mMarginRightComputed + && mb == mMarginBottomComputed + && r == mMarginRelativeComputed) + { + return; + } + mMarginLeftComputed = ml; + mMarginTopComputed = mt; + mMarginRightComputed = mr; + mMarginBottomComputed = mb; + mMarginRelativeComputed = r; + +#if UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + int width = (int)(Screen.width - (ml + mr)); + int height = (int)(Screen.height - (mb + mt)); + _CWebViewPlugin_SetRect(webView, width, height); + rect = new Rect(left, bottom, width, height); + UpdateBGTransform(); +#elif UNITY_WEBPLAYER + Application.ExternalCall("unityWebView.setMargins", name, (int)ml, (int)mt, (int)mr, (int)mb); +#elif UNITY_WEBGL && !UNITY_EDITOR + _gree_unity_webview_setMargins(name, (int)ml, (int)mt, (int)mr, (int)mb); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + int width = (int)(Screen.width - (ml + mr)); + int height = (int)(Screen.height - (mb + mt)); + _CWebViewPlugin_SetRect(webView, width, height); + rect = new Rect(left, bottom, width, height); + UpdateBGTransform(); +#elif UNITY_IPHONE + _CWebViewPlugin_SetMargins(webView, ml, mt, mr, mb, r); +#elif UNITY_ANDROID + webView.Call("SetMargins", (int)ml, (int)mt, (int)mr, (int)mb); +#endif + } + + public void SetVisibility(bool v) + { +#if UNITY_EDITOR || UNITY_STANDALONE + if (bg != null) + { + bg.gameObject.SetActive(v); + } +#endif + if (GetVisibility() && !v) + { + EvaluateJS("if (document && document.activeElement) document.activeElement.blur();"); + } +#if UNITY_WEBGL +#if !UNITY_EDITOR + _gree_unity_webview_setVisibility(name, v); +#endif +#elif UNITY_WEBPLAYER + Application.ExternalCall("unityWebView.setVisibility", name, v); +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_SetVisibility(webView, v); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_SetVisibility(webView, v); +#elif UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_SetVisibility(webView, v); +#elif UNITY_ANDROID + if (webView == null) + return; + mVisibility = v; + webView.Call("SetVisibility", v); +#endif + visibility = v; + } + + public bool GetVisibility() + { + return visibility; + } + + public void SetScrollbarsVisibility(bool v) + { +#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + // TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + // TODO: WebView2 not implemented in native plugin +#elif UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_SetScrollbarsVisibility(webView, v); +#elif UNITY_ANDROID + if (webView == null) + return; + webView.Call("SetScrollbarsVisibility", v); +#else + // TODO: UNSUPPORTED +#endif + } + + public void SetInteractionEnabled(bool enabled) + { +#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + // TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + // TODO: WebView2 not implemented in native plugin +#elif UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_SetInteractionEnabled(webView, enabled); +#elif UNITY_ANDROID + if (webView == null) + return; + webView.Call("SetInteractionEnabled", enabled); +#else + // TODO: UNSUPPORTED +#endif + } + + public void SetGoogleAppRedirectionEnabled(bool enabled) + { +#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + // TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + // TODO: WebView2 not implemented in native plugin +#elif UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_SetGoogleAppRedirectionEnabled(webView, enabled); +#elif UNITY_ANDROID + if (webView == null) + return; + webView.Call("SetGoogleAppRedirectionEnabled", enabled); +#else + // TODO: UNSUPPORTED +#endif + } + + public void SetAlertDialogEnabled(bool e) + { +#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + // TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + // TODO: WebView2 not implemented in native plugin +#elif UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_SetAlertDialogEnabled(webView, e); +#elif UNITY_ANDROID + if (webView == null) + return; + webView.Call("SetAlertDialogEnabled", e); +#else + // TODO: UNSUPPORTED +#endif + alertDialogEnabled = e; + } + + public bool GetAlertDialogEnabled() + { + return alertDialogEnabled; + } + + public void SetScrollBounceEnabled(bool e) + { +#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + // TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + // TODO: WebView2 not implemented in native plugin +#elif UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_SetScrollBounceEnabled(webView, e); +#elif UNITY_ANDROID + // TODO: UNSUPPORTED +#else + // TODO: UNSUPPORTED +#endif + scrollBounceEnabled = e; + } + + public bool GetScrollBounceEnabled() + { + return scrollBounceEnabled; + } + + public void SetCameraAccess(bool allowed) + { +#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + // TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + // TODO: WebView2 not implemented in native plugin +#elif UNITY_IPHONE + // TODO: UNSUPPORTED +#elif UNITY_ANDROID +#if UNITYWEBVIEW_ANDROID_ENABLE_CAMERA + if (webView == null) + return; + webView.Call("SetCameraAccess", allowed); + mAllowVideoCapture = allowed; +#endif +#else + // TODO: UNSUPPORTED +#endif + } + + public void SetMicrophoneAccess(bool allowed) + { +#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + // TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + // TODO: WebView2 not implemented in native plugin +#elif UNITY_IPHONE + // TODO: UNSUPPORTED +#elif UNITY_ANDROID +#if UNITYWEBVIEW_ANDROID_ENABLE_MICROPHONE + if (webView == null) + return; + webView.Call("SetMicrophoneAccess", allowed); + mAllowAudioCapture = allowed; +#endif +#else + // TODO: UNSUPPORTED +#endif + } + + public bool SetURLPattern(string allowPattern, string denyPattern, string hookPattern) + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED + return false; +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED + return false; +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return false; + return _CWebViewPlugin_SetURLPattern(webView, allowPattern, denyPattern, hookPattern); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return false; + return _CWebViewPlugin_SetURLPattern(webView, allowPattern, denyPattern, hookPattern); +#elif UNITY_ANDROID + if (webView == null) + return false; + return webView.Call("SetURLPattern", allowPattern, denyPattern, hookPattern); +#endif + } + + public void LoadURL(string url) + { + if (string.IsNullOrEmpty(url)) + return; +#if UNITY_WEBGL +#if !UNITY_EDITOR + _gree_unity_webview_loadURL(name, url); +#endif +#elif UNITY_WEBPLAYER + Application.ExternalCall("unityWebView.loadURL", name, url); +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_LoadURL(webView, url); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_LoadURL(webView, url); +#elif UNITY_ANDROID + if (webView == null) + return; + webView.Call("LoadURL", url); +#endif + } + + public void LoadHTML(string html, string baseUrl) + { + if (string.IsNullOrEmpty(html)) + return; + if (string.IsNullOrEmpty(baseUrl)) + baseUrl = ""; +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_LoadHTML(webView, html, baseUrl); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_LoadHTML(webView, html, baseUrl); +#elif UNITY_ANDROID + if (webView == null) + return; + webView.Call("LoadHTML", html, baseUrl); +#endif + } + + public void EvaluateJS(string js) + { +#if UNITY_WEBGL +#if !UNITY_EDITOR + _gree_unity_webview_evaluateJS(name, js); +#endif +#elif UNITY_WEBPLAYER + Application.ExternalCall("unityWebView.evaluateJS", name, js); +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_EvaluateJS(webView, js); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_EvaluateJS(webView, js); +#elif UNITY_ANDROID + if (webView == null) + return; + webView.Call("EvaluateJS", js); +#endif + } + + public int Progress() + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED + return 0; +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED + return 0; +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return 0; + return _CWebViewPlugin_Progress(webView); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return 0; + return _CWebViewPlugin_Progress(webView); +#elif UNITY_ANDROID + if (webView == null) + return 0; + return webView.Get("progress"); +#endif + } + + public bool CanGoBack() + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED + return false; +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED + return false; +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return false; + return _CWebViewPlugin_CanGoBack(webView); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return false; + return _CWebViewPlugin_CanGoBack(webView); +#elif UNITY_ANDROID + if (webView == null) + return false; + return webView.Get("canGoBack"); +#endif + } + + public bool CanGoForward() + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED + return false; +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED + return false; +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return false; + return _CWebViewPlugin_CanGoForward(webView); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return false; + return _CWebViewPlugin_CanGoForward(webView); +#elif UNITY_ANDROID + if (webView == null) + return false; + return webView.Get("canGoForward"); +#endif + } + + public void GoBack() + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_GoBack(webView); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_GoBack(webView); +#elif UNITY_ANDROID + if (webView == null) + return; + webView.Call("GoBack"); +#endif + } + + public void GoForward() + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_GoForward(webView); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_GoForward(webView); +#elif UNITY_ANDROID + if (webView == null) + return; + webView.Call("GoForward"); +#endif + } + + public void Reload() + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_Reload(webView); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_Reload(webView); +#elif UNITY_ANDROID + if (webView == null) + return; + webView.Call("Reload"); +#endif + } + + public void CallOnError(string error) + { + if (onError != null) + { + onError(error); + } + } + + public void CallOnHttpError(string error) + { + if (onHttpError != null) + { + onHttpError(error); + } + } + + public void CallOnStarted(string url) + { + if (onStarted != null) + { + onStarted(url); + } + } + + public void CallOnLoaded(string url) + { + if (onLoaded != null) + { + onLoaded(url); + } + } + + public void CallFromJS(string message) + { + if (onJS != null) + { +#if !UNITY_ANDROID +#if UNITY_2018_4_OR_NEWER + message = UnityWebRequest.UnEscapeURL(message); +#else // UNITY_2018_4_OR_NEWER + message = WWW.UnEscapeURL(message); +#endif // UNITY_2018_4_OR_NEWER +#endif // !UNITY_ANDROID + onJS(message); + } + } + + public void CallOnHooked(string message) + { + if (onHooked != null) + { +#if !UNITY_ANDROID +#if UNITY_2018_4_OR_NEWER + message = UnityWebRequest.UnEscapeURL(message); +#else // UNITY_2018_4_OR_NEWER + message = WWW.UnEscapeURL(message); +#endif // UNITY_2018_4_OR_NEWER +#endif // !UNITY_ANDROID + onHooked(message); + } + } + + public void CallOnCookies(string cookies) + { + if (onCookies != null) + { + onCookies(cookies); + } + } + + public void AddCustomHeader(string headerKey, string headerValue) + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_AddCustomHeader(webView, headerKey, headerValue); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_AddCustomHeader(webView, headerKey, headerValue); +#elif UNITY_ANDROID + if (webView == null) + return; + webView.Call("AddCustomHeader", headerKey, headerValue); +#endif + } + + public string GetCustomHeaderValue(string headerKey) + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED + return null; +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED + return null; +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return null; + return _CWebViewPlugin_GetCustomHeaderValue(webView, headerKey); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return null; + return _CWebViewPlugin_GetCustomHeaderValue(webView, headerKey); +#elif UNITY_ANDROID + if (webView == null) + return null; + return webView.Call("GetCustomHeaderValue", headerKey); +#endif + } + + public void RemoveCustomHeader(string headerKey) + { +#if UNITY_WEBPLAYER || UNITY_WEBGL +#elif UNITY_EDITOR_LINUX || UNITY_SERVER +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_RemoveCustomHeader(webView, headerKey); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_RemoveCustomHeader(webView, headerKey); +#elif UNITY_ANDROID + if (webView == null) + return; + webView.Call("RemoveCustomHeader", headerKey); +#endif + } + + public void ClearCustomHeader() + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_ClearCustomHeader(webView); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_ClearCustomHeader(webView); +#elif UNITY_ANDROID + if (webView == null) + return; + webView.Call("ClearCustomHeader"); +#endif + } + + public void ClearCookie(string url, string name) + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + _CWebViewPlugin_ClearCookie(url, name); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_ClearCookie(url, name); +#elif UNITY_ANDROID && !UNITY_EDITOR + if (webView == null) + return; + webView.Call("ClearCookie", url, name); +#endif + } + + public void ClearCookies() + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + _CWebViewPlugin_ClearCookies(); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_ClearCookies(); +#elif UNITY_ANDROID && !UNITY_EDITOR + if (webView == null) + return; + webView.Call("ClearCookies"); +#endif + } + + + public void SaveCookies() + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + _CWebViewPlugin_SaveCookies(); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_SaveCookies(); +#elif UNITY_ANDROID && !UNITY_EDITOR + if (webView == null) + return; + webView.Call("SaveCookies"); +#endif + } + + + public void GetCookies(string url) + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_GetCookies(webView, url); +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_GetCookies(webView, url); +#elif UNITY_ANDROID && !UNITY_EDITOR + if (webView == null) + return; + webView.Call("GetCookies", url); +#else + //TODO: UNSUPPORTED +#endif + } + + public void SetBasicAuthInfo(string userName, string password) + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + //TODO: WebView2 basic auth not implemented in native plugin +#elif UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + //TODO: UNSUPPORTED +#elif UNITY_IPHONE + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_SetBasicAuthInfo(webView, userName, password); +#elif UNITY_ANDROID + if (webView == null) + return; + webView.Call("SetBasicAuthInfo", userName, password); +#endif + } + + public void ClearCache(bool includeDiskFiles) + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + //TODO: WebView2 cache clear not implemented in native plugin +#elif UNITY_IPHONE && !UNITY_EDITOR + if (webView == IntPtr.Zero) + return; + _CWebViewPlugin_ClearCache(webView, includeDiskFiles); +#elif UNITY_ANDROID && !UNITY_EDITOR + if (webView == null) + return; + webView.Call("ClearCache", includeDiskFiles); +#endif + } + + + public void SetTextZoom(int textZoom) + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + //TODO: WebView2 text zoom not implemented in native plugin +#elif UNITY_IPHONE && !UNITY_EDITOR + //TODO: UNSUPPORTED +#elif UNITY_ANDROID && !UNITY_EDITOR + if (webView == null) + return; + webView.Call("SetTextZoom", textZoom); +#endif + } + + public void SetMixedContentMode(int mode) // 0: MIXED_CONTENT_ALWAYS_ALLOW, 1: MIXED_CONTENT_NEVER_ALLOW, 2: MIXED_CONTENT_COMPATIBILITY_MODE + { +#if UNITY_WEBPLAYER || UNITY_WEBGL + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_LINUX || UNITY_SERVER + //TODO: UNSUPPORTED +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + //TODO: WebView2 mixed content mode not implemented in native plugin +#elif UNITY_IPHONE && !UNITY_EDITOR + //TODO: UNSUPPORTED +#elif UNITY_ANDROID && !UNITY_EDITOR + if (webView == null) + return; + webView.Call("SetMixedContentMode", mode); +#endif + } + +#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + void OnApplicationFocus(bool focus) + { + if (!focus) + { + hasFocus = false; + } + } + + void Start() + { + if (canvas != null) + { + var g = new GameObject(gameObject.name + "BG"); + g.transform.parent = canvas.transform; + bg = g.AddComponent(); + UpdateBGTransform(); + } + } + + void Update() + { + if (bg != null) { + bg.transform.SetAsLastSibling(); + } + if (hasFocus) { + inputString += Input.inputString; + } + for (;;) { + if (webView == IntPtr.Zero) + break; + string s = _CWebViewPlugin_GetMessage(webView); + if (s == null) + break; + var i = s.IndexOf(':', 0); + if (i == -1) + continue; + switch (s.Substring(0, i)) { + case "CallFromJS": + CallFromJS(s.Substring(i + 1)); + break; + case "CallOnError": + CallOnError(s.Substring(i + 1)); + break; + case "CallOnHttpError": + CallOnHttpError(s.Substring(i + 1)); + break; + case "CallOnLoaded": + CallOnLoaded(s.Substring(i + 1)); + break; + case "CallOnStarted": + CallOnStarted(s.Substring(i + 1)); + break; + case "CallOnHooked": + CallOnHooked(s.Substring(i + 1)); + break; + case "CallOnCookies": + CallOnCookies(s.Substring(i + 1)); + break; + } + } + if (webView == IntPtr.Zero || !visibility) + return; + bool refreshBitmap = (Time.frameCount % bitmapRefreshCycle == 0); + _CWebViewPlugin_Update(webView, refreshBitmap, devicePixelRatio); + if (refreshBitmap) { + var w = _CWebViewPlugin_BitmapWidth(webView); + var h = _CWebViewPlugin_BitmapHeight(webView); + var f = (_CWebViewPlugin_BitmapARGB(webView)) ? TextureFormat.ARGB32 : TextureFormat.RGBA32; + if (w > 0 && h > 0) { + if (texture == null || texture.width != w || texture.height != h) { + bool isLinearSpace = QualitySettings.activeColorSpace == ColorSpace.Linear; + texture = new Texture2D(w, h, f, false, !isLinearSpace); + texture.filterMode = FilterMode.Bilinear; + texture.wrapMode = TextureWrapMode.Clamp; +#if UNITY_2018_2_OR_NEWER +#else + textureDataBuffer = new byte[w * h * 4]; +#endif + } + if (texture != null) { +#if UNITY_2018_2_OR_NEWER + var ptr = _CWebViewPlugin_Render(webView, IntPtr.Zero); + if (ptr != IntPtr.Zero) { + texture.LoadRawTextureData(ptr, w * h * 4); + texture.Apply(); + } +#else + var gch = GCHandle.Alloc(textureDataBuffer, GCHandleType.Pinned); + _CWebViewPlugin_Render(webView, gch.AddrOfPinnedObject()); + gch.Free(); + texture.LoadRawTextureData(textureDataBuffer); + texture.Apply(); +#endif + } + } + } + } + + void UpdateBGTransform() + { + if (bg != null) { + bg.rectTransform.anchorMin = Vector2.zero; + bg.rectTransform.anchorMax = Vector2.zero; + bg.rectTransform.pivot = Vector2.zero; + bg.rectTransform.position = rect.min; + bg.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, rect.size.x); + bg.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, rect.size.y); + } + } + + public int bitmapRefreshCycle = 1; + public int devicePixelRatio = 1; + + void OnGUI() + { + if (webView == IntPtr.Zero || !visibility) + return; + switch (Event.current.type) { + case EventType.MouseDown: + case EventType.MouseUp: + hasFocus = rect.Contains(Input.mousePosition); + break; + } + switch (Event.current.type) { + case EventType.MouseMove: + case EventType.MouseDown: + case EventType.MouseDrag: + case EventType.MouseUp: + case EventType.ScrollWheel: + if (hasFocus) { + Vector3 p; + p.x = Input.mousePosition.x - rect.x; + p.y = Input.mousePosition.y - rect.y; + { + int mouseState = 0; + if (Input.GetButtonDown("Fire1")) { + mouseState = 1; + } else if (Input.GetButton("Fire1")) { + mouseState = 2; + } else if (Input.GetButtonUp("Fire1")) { + mouseState = 3; + } + //_CWebViewPlugin_SendMouseEvent(webView, (int)p.x, (int)p.y, Input.GetAxis("Mouse ScrollWheel"), mouseState); + _CWebViewPlugin_SendMouseEvent(webView, (int)p.x, (int)p.y, Input.mouseScrollDelta.y, mouseState); + } + } + break; + case EventType.Repaint: + while (!string.IsNullOrEmpty(inputString)) { + var keyChars = inputString.Substring(0, 1); + var keyCode = (ushort)inputString[0]; + inputString = inputString.Substring(1); + if (!string.IsNullOrEmpty(keyChars) || keyCode != 0) { + Vector3 p; + p.x = Input.mousePosition.x - rect.x; + p.y = Input.mousePosition.y - rect.y; + _CWebViewPlugin_SendKeyEvent(webView, (int)p.x, (int)p.y, keyChars, keyCode, 1); + } + } + if (texture != null) { + Matrix4x4 m = GUI.matrix; + GUI.matrix + = Matrix4x4.TRS( + new Vector3(0, Screen.height, 0), + Quaternion.identity, + new Vector3(1, -1, 1)); + Graphics.DrawTexture(rect, texture); + GUI.matrix = m; + } + break; + } + } +#elif UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + void OnApplicationFocus(bool focus) + { + if (!focus) + { + hasFocus = false; + } + } + + void Start() + { + if (canvas != null) + { + var g = new GameObject(gameObject.name + "BG"); + g.transform.parent = canvas.transform; + bg = g.AddComponent(); + UpdateBGTransform(); + } + } + + void Update() + { + if (bg != null) + { + bg.transform.SetAsLastSibling(); + } + if (hasFocus) + { + inputString += Input.inputString; + } + for (;;) + { + if (webView == IntPtr.Zero) + break; + string s = _CWebViewPlugin_GetMessage(webView); + if (s == null) + break; + var i = s.IndexOf(':', 0); + if (i == -1) + continue; + switch (s.Substring(0, i)) + { + case "CallFromJS": + CallFromJS(s.Substring(i + 1)); + break; + case "CallOnError": + CallOnError(s.Substring(i + 1)); + break; + case "CallOnHttpError": + CallOnHttpError(s.Substring(i + 1)); + break; + case "CallOnLoaded": + CallOnLoaded(s.Substring(i + 1)); + break; + case "CallOnStarted": + CallOnStarted(s.Substring(i + 1)); + break; + case "CallOnHooked": + CallOnHooked(s.Substring(i + 1)); + break; + case "CallOnCookies": + CallOnCookies(s.Substring(i + 1)); + break; + } + } + if (webView == IntPtr.Zero || !visibility) + return; + bool refreshBitmap = (Time.frameCount % bitmapRefreshCycle == 0); + _CWebViewPlugin_Update(webView, refreshBitmap, devicePixelRatio); + if (refreshBitmap) + { + var w = _CWebViewPlugin_BitmapWidth(webView); + var h = _CWebViewPlugin_BitmapHeight(webView); + if (w > 0 && h > 0) + { + if (texture == null || texture.width != w || texture.height != h) + { + bool isLinearSpace = QualitySettings.activeColorSpace == ColorSpace.Linear; + texture = new Texture2D(w, h, TextureFormat.RGBA32, false, !isLinearSpace); + texture.filterMode = FilterMode.Bilinear; + texture.wrapMode = TextureWrapMode.Clamp; + textureDataBuffer = new byte[w * h * 4]; + } + if (textureDataBuffer != null && textureDataBuffer.Length > 0) + { + var gch = GCHandle.Alloc(textureDataBuffer, GCHandleType.Pinned); + _CWebViewPlugin_Render(webView, gch.AddrOfPinnedObject()); + gch.Free(); + texture.LoadRawTextureData(textureDataBuffer); + texture.Apply(); + } + } + } + } + + void UpdateBGTransform() + { + if (bg != null) + { + bg.rectTransform.anchorMin = Vector2.zero; + bg.rectTransform.anchorMax = Vector2.zero; + bg.rectTransform.pivot = Vector2.zero; + bg.rectTransform.position = rect.min; + bg.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, rect.size.x); + bg.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, rect.size.y); + } + } + + // On Windows, CapturePreview is heavy; default 10 = refresh every 10th frame for better FPS. + public int bitmapRefreshCycle = 10; + public int devicePixelRatio = 1; + + void OnGUI() + { + if (webView == IntPtr.Zero || !visibility) + return; + switch (Event.current.type) + { + case EventType.MouseDown: + case EventType.MouseUp: + hasFocus = rect.Contains(Input.mousePosition); + break; + } + switch (Event.current.type) + { + case EventType.MouseMove: + case EventType.MouseDown: + case EventType.MouseDrag: + case EventType.MouseUp: + case EventType.ScrollWheel: + if (hasFocus) + { + Vector3 p; + p.x = Input.mousePosition.x - rect.x; + p.y = Input.mousePosition.y - rect.y; + int mouseState = 0; + if (Input.GetButtonDown("Fire1")) + mouseState = 1; + else if (Input.GetButton("Fire1")) + mouseState = 2; + else if (Input.GetButtonUp("Fire1")) + mouseState = 3; + _CWebViewPlugin_SendMouseEvent(webView, (int)p.x, (int)p.y, Input.mouseScrollDelta.y, mouseState); + } + break; + case EventType.Repaint: + while (!string.IsNullOrEmpty(inputString)) + { + var keyChars = inputString.Substring(0, 1); + var keyCode = (ushort)inputString[0]; + inputString = inputString.Substring(1); + if (!string.IsNullOrEmpty(keyChars) || keyCode != 0) + { + Vector3 p; + p.x = Input.mousePosition.x - rect.x; + p.y = Input.mousePosition.y - rect.y; + _CWebViewPlugin_SendKeyEvent(webView, (int)p.x, (int)p.y, keyChars, keyCode, 1); + } + } + if (texture != null) + { + Matrix4x4 m = GUI.matrix; + GUI.matrix = Matrix4x4.TRS(new Vector3(0, Screen.height, 0), Quaternion.identity, new Vector3(1, -1, 1)); + Graphics.DrawTexture(rect, texture); + GUI.matrix = m; + } + break; + } + } +#endif + } +} diff --git a/Assets/TCJPLYRM1xJTSDK/ThirdParty/WebView/WebViewObject1.cs.meta b/Assets/TCJPLYRM1xJTSDK/ThirdParty/WebView/WebViewObject1.cs.meta new file mode 100644 index 00000000..36a26174 --- /dev/null +++ b/Assets/TCJPLYRM1xJTSDK/ThirdParty/WebView/WebViewObject1.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6f866181e8964a5db5ca2b5389ace632 +timeCreated: 1784015330 \ No newline at end of file diff --git a/Assets/WebGLTemplates.meta b/Assets/WebGLTemplates.meta new file mode 100644 index 00000000..1df8df3d --- /dev/null +++ b/Assets/WebGLTemplates.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 396d2c966866e4a8ca47369a69d03109 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/WebGLTemplates/unity-webview-2020.meta b/Assets/WebGLTemplates/unity-webview-2020.meta new file mode 100644 index 00000000..756a586c --- /dev/null +++ b/Assets/WebGLTemplates/unity-webview-2020.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d9e103622e8c14154a1cd918fb92795e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/WebGLTemplates/unity-webview-2020/index.html b/Assets/WebGLTemplates/unity-webview-2020/index.html new file mode 100644 index 00000000..84f13023 --- /dev/null +++ b/Assets/WebGLTemplates/unity-webview-2020/index.html @@ -0,0 +1,108 @@ + + + + + + Unity WebGL Player | {{{ PRODUCT_NAME }}} + + + + + + +
+ +
+ +
+
+
+
+ +
+ + + diff --git a/Assets/WebGLTemplates/unity-webview-2020/index.html.meta b/Assets/WebGLTemplates/unity-webview-2020/index.html.meta new file mode 100644 index 00000000..512f42c4 --- /dev/null +++ b/Assets/WebGLTemplates/unity-webview-2020/index.html.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7be04fa587d934a5c958c8fc02a10c40 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/WebGLTemplates/unity-webview-2020/unity-webview.js b/Assets/WebGLTemplates/unity-webview-2020/unity-webview.js new file mode 100644 index 00000000..6a9c777f --- /dev/null +++ b/Assets/WebGLTemplates/unity-webview-2020/unity-webview.js @@ -0,0 +1,103 @@ +var unityWebView = +{ + loaded: [], + + init : function (name) { + $containers = $('.webviewContainer'); + if ($containers.length === 0) { + $('
') + .appendTo($('#unity-container')); + } + var $last = $('.webviewContainer:last'); + var clonedTop = parseInt($last.css('top')) - 100; + var $clone = $last.clone().insertAfter($last).css('top', clonedTop + '%'); + var $iframe = + $('') + .attr('id', 'webview_' + name) + .appendTo($last) + .on('load', function () { + $(this).attr('loaded', 'true'); + var contents = $(this).contents(); + var w = $(this)[0].contentWindow; + contents.find('a').click(function (e) { + var href = $.trim($(this).attr('href')); + if (href.substr(0, 6) === 'unity:') { + unityInstance.SendMessage(name, "CallFromJS", href.substring(6, href.length)); + e.preventDefault(); + } + }); + + contents.find('form').submit(function () { + $this = $(this); + var action = $.trim($this.attr('action')); + if (action.substr(0, 6) === 'unity:') { + var message = action.substring(6, action.length); + if ($this.attr('method').toLowerCase() == 'get') { + message += '?' + $this.serialize(); + } + unityInstance.SendMessage(name, "CallFromJS", message); + return false; + } + return true; + }); + + unityInstance.SendMessage(name, "CallOnLoaded", location.href); + }); + }, + + sendMessage: function (name, message) { + unityInstance.SendMessage(name, "CallFromJS", message); + }, + + setMargins: function (name, left, top, right, bottom) { + var container = $('#unity-container'); + var r = (container.hasClass('unity-desktop')) ? window.devicePixelRatio : 1; + var w0 = container.width() * r; + var h0 = container.height() * r; + var canvas = $('#unity-canvas'); + var w1 = canvas.attr('width'); + var h1 = canvas.attr('height'); + + var lp = left / w0 * 100; + var tp = top / h0 * 100; + var wp = (w1 - left - right) / w0 * 100; + var hp = (h1 - top - bottom) / h0 * 100; + + this.iframe(name) + .css('left', lp + '%') + .css('top', tp + '%') + .css('width', wp + '%') + .css('height', hp + '%'); + }, + + setVisibility: function (name, visible) { + if (visible) + this.iframe(name).show(); + else + this.iframe(name).hide(); + }, + + loadURL: function(name, url) { + this.iframe(name).attr('loaded', 'false')[0].contentWindow.location.replace(url); + }, + + evaluateJS: function (name, js) { + $iframe = this.iframe(name); + if ($iframe.attr('loaded') === 'true') { + $iframe[0].contentWindow.eval(js); + } else { + $iframe.on('load', function(){ + $(this)[0].contentWindow.eval(js); + }); + } + }, + + destroy: function (name) { + this.iframe(name).parent().parent().remove(); + }, + + iframe: function (name) { + return $('#webview_' + name); + }, + +}; diff --git a/Assets/WebGLTemplates/unity-webview-2020/unity-webview.js.meta b/Assets/WebGLTemplates/unity-webview-2020/unity-webview.js.meta new file mode 100644 index 00000000..8ee7ab8c --- /dev/null +++ b/Assets/WebGLTemplates/unity-webview-2020/unity-webview.js.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5b98600d622f440fab913c56685e11bf +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/WebGLTemplates/unity-webview.meta b/Assets/WebGLTemplates/unity-webview.meta new file mode 100644 index 00000000..7c3eabcf --- /dev/null +++ b/Assets/WebGLTemplates/unity-webview.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 74f24ca1a6cc14b5c8da7e2a8e5de817 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/WebGLTemplates/unity-webview/index.html b/Assets/WebGLTemplates/unity-webview/index.html new file mode 100644 index 00000000..7474f1c4 --- /dev/null +++ b/Assets/WebGLTemplates/unity-webview/index.html @@ -0,0 +1,32 @@ + + + + + Unity Web Player + + + + + + + + + + +
+
+
+ +
+
+ + + + + diff --git a/Assets/WebGLTemplates/unity-webview/index.html.meta b/Assets/WebGLTemplates/unity-webview/index.html.meta new file mode 100644 index 00000000..5b8b18d1 --- /dev/null +++ b/Assets/WebGLTemplates/unity-webview/index.html.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: cd45543727a7e47d88051ca9ab86a6f5 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/WebGLTemplates/unity-webview/unity-webview.js b/Assets/WebGLTemplates/unity-webview/unity-webview.js new file mode 100644 index 00000000..64f473c0 --- /dev/null +++ b/Assets/WebGLTemplates/unity-webview/unity-webview.js @@ -0,0 +1,100 @@ +var unityWebView = +{ + loaded: [], + + init : function (name) { + $containers = $('.webviewContainer'); + if ($containers.length === 0) { + $('
') + .appendTo($('#gameContainer')); + } + var $last = $('.webviewContainer:last'); + var clonedTop = parseInt($last.css('top')) - 100; + var $clone = $last.clone().insertAfter($last).css('top', clonedTop + '%'); + var $iframe = + $('') + .attr('id', 'webview_' + name) + .appendTo($last) + .on('load', function () { + $(this).attr('loaded', 'true'); + var contents = $(this).contents(); + var w = $(this)[0].contentWindow; + contents.find('a').click(function (e) { + var href = $.trim($(this).attr('href')); + if (href.substr(0, 6) === 'unity:') { + unityInstance.SendMessage(name, "CallFromJS", href.substring(6, href.length)); + e.preventDefault(); + } + }); + + contents.find('form').submit(function () { + $this = $(this); + var action = $.trim($this.attr('action')); + if (action.substr(0, 6) === 'unity:') { + var message = action.substring(6, action.length); + if ($this.attr('method').toLowerCase() == 'get') { + message += '?' + $this.serialize(); + } + unityInstance.SendMessage(name, "CallFromJS", message); + return false; + } + return true; + }); + + unityInstance.SendMessage(name, "CallOnLoaded", location.href); + }); + }, + + sendMessage: function (name, message) { + unityInstance.SendMessage(name, "CallFromJS", message); + }, + + setMargins: function (name, left, top, right, bottom) { + var container = $('#gameContainer'); + var r = window.devicePixelRatio; + var w0 = container.width() * r; + var h0 = container.height() * r; + + var lp = left / w0 * 100; + var tp = top / h0 * 100; + var wp = (w0 - left - right) / w0 * 100; + var hp = (h0 - top - bottom) / h0 * 100; + + this.iframe(name) + .css('left', lp + '%') + .css('top', tp + '%') + .css('width', wp + '%') + .css('height', hp + '%'); + }, + + setVisibility: function (name, visible) { + if (visible) + this.iframe(name).show(); + else + this.iframe(name).hide(); + }, + + loadURL: function(name, url) { + this.iframe(name).attr('loaded', 'false')[0].contentWindow.location.replace(url); + }, + + evaluateJS: function (name, js) { + $iframe = this.iframe(name); + if ($iframe.attr('loaded') === 'true') { + $iframe[0].contentWindow.eval(js); + } else { + $iframe.on('load', function(){ + $(this)[0].contentWindow.eval(js); + }); + } + }, + + destroy: function (name) { + this.iframe(name).parent().parent().remove(); + }, + + iframe: function (name) { + return $('#webview_' + name); + }, + +}; diff --git a/Assets/WebGLTemplates/unity-webview/unity-webview.js.meta b/Assets/WebGLTemplates/unity-webview/unity-webview.js.meta new file mode 100644 index 00000000..b421d598 --- /dev/null +++ b/Assets/WebGLTemplates/unity-webview/unity-webview.js.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8de1ecd3ea5954800b53548d8c2e2d70 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/WebPlayerTemplates.meta b/Assets/WebPlayerTemplates.meta new file mode 100644 index 00000000..d1d66623 --- /dev/null +++ b/Assets/WebPlayerTemplates.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1ec4661d3c10c4d0e8b5e54ce1e46aa5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/WebPlayerTemplates/unity-webview.meta b/Assets/WebPlayerTemplates/unity-webview.meta new file mode 100644 index 00000000..06794cb6 --- /dev/null +++ b/Assets/WebPlayerTemplates/unity-webview.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e76c9a30b7f6447eca50079ce4d595ed +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/WebPlayerTemplates/unity-webview/index.html b/Assets/WebPlayerTemplates/unity-webview/index.html new file mode 100644 index 00000000..511e1137 --- /dev/null +++ b/Assets/WebPlayerTemplates/unity-webview/index.html @@ -0,0 +1,136 @@ + + + + + Unity Web Player | %UNITY_WEB_NAME% + %UNITY_UNITYOBJECT_DEPENDENCIES% + + + + + + +

Unity Web Player | %UNITY_WEB_NAME%

%UNITY_BETA_WARNING% +
+
+
+ + Unity Web Player. Install now! + +
+
+
+ + + + + + + \ No newline at end of file diff --git a/Assets/WebPlayerTemplates/unity-webview/index.html.meta b/Assets/WebPlayerTemplates/unity-webview/index.html.meta new file mode 100644 index 00000000..fcb667ad --- /dev/null +++ b/Assets/WebPlayerTemplates/unity-webview/index.html.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f6333062aa8e346f2abc78ef7a457580 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/WebPlayerTemplates/unity-webview/thumbnail.png b/Assets/WebPlayerTemplates/unity-webview/thumbnail.png new file mode 100644 index 00000000..773c2e2d Binary files /dev/null and b/Assets/WebPlayerTemplates/unity-webview/thumbnail.png differ diff --git a/Assets/WebPlayerTemplates/unity-webview/thumbnail.png.meta b/Assets/WebPlayerTemplates/unity-webview/thumbnail.png.meta new file mode 100644 index 00000000..b1c973ba --- /dev/null +++ b/Assets/WebPlayerTemplates/unity-webview/thumbnail.png.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 018355354713f41b2bed252c88e082c7 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/WebPlayerTemplates/unity-webview/unity-webview.js b/Assets/WebPlayerTemplates/unity-webview/unity-webview.js new file mode 100644 index 00000000..f2ebe5fb --- /dev/null +++ b/Assets/WebPlayerTemplates/unity-webview/unity-webview.js @@ -0,0 +1,99 @@ +var unityWebView = +{ + loaded: [], + + init : function (name) { + $containers = $('.webviewContainer'); + if ($containers.length === 0) { + $('
') + .attr('id', 'webview_' + name) + .appendTo($last) + .on('load', function () { + $(this).attr('loaded', 'true'); + var contents = $(this).contents(); + var w = $(this)[0].contentWindow; + contents.find('a').click(function (e) { + var href = $.trim($(this).attr('href')); + if (href.substr(0, 6) === 'unity:') { + u.getUnity().SendMessage(name, "CallFromJS", href.substring(6, href.length)); + e.preventDefault(); + } else { + w.location.replace(href); + } + }); + + contents.find('form').submit(function () { + $this = $(this); + var action = $.trim($this.attr('action')); + if (action.substr(0, 6) === 'unity:') { + var message = action.substring(6, action.length); + if ($this.attr('method').toLowerCase() == 'get') { + message += '?' + $this.serialize(); + } + u.getUnity().SendMessage(name, "CallFromJS", message); + return false; + } + return true; + }); + }); + }, + + sendMessage: function (name, message) { + u.getUnity().SendMessage(name, "CallFromJS", message); + }, + + setMargins: function (name, left, top, right, bottom) { + var $player = $('#unityPlayer'); + var width = $player.width(); + var height = $player.height(); + + var lp = left / width * 100; + var tp = top / height * 100; + var wp = (width - left - right) / width * 100; + var hp = (height - top - bottom) / height * 100; + + this.iframe(name) + .css('left', lp + '%') + .css('top', tp + '%') + .css('width', wp + '%') + .css('height', hp + '%'); + }, + + setVisibility: function (name, visible) { + if (visible) + this.iframe(name).show(); + else + this.iframe(name).hide(); + }, + + loadURL: function(name, url) { + this.iframe(name).attr('loaded', 'false')[0].contentWindow.location.replace(url); + }, + + evaluateJS: function (name, js) { + $iframe = this.iframe(name); + if ($iframe.attr('loaded') === 'true') { + $iframe[0].contentWindow.eval(js); + } else { + $iframe.on('load', function(){ + $(this)[0].contentWindow.eval(js); + }); + } + }, + + destroy: function (name) { + this.iframe(name).parent().parent().remove(); + }, + + iframe: function (name) { + return $('#webview_' + name); + }, + +}; diff --git a/Assets/WebPlayerTemplates/unity-webview/unity-webview.js.meta b/Assets/WebPlayerTemplates/unity-webview/unity-webview.js.meta new file mode 100644 index 00000000..ac69546e --- /dev/null +++ b/Assets/WebPlayerTemplates/unity-webview/unity-webview.js.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7bf88e2aa1e624d64b530ad0c2383b9e +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: