Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 

337 rader
14 KiB

  1. // #if UNITY_2023_2_OR_NEWER
  2. #if UNIWEBVIEW_NEW_ANDROID_BUILD_SYSTEM
  3. using System;
  4. using System.Linq;
  5. using Unity.Android.Gradle;
  6. using Unity.Android.Gradle.Manifest;
  7. using UnityEditor.Android;
  8. using UnityEngine;
  9. using Action = Unity.Android.Gradle.Manifest.Action;
  10. class UniWebViewPostBuildModifier : AndroidProjectFilesModifier {
  11. const string ContextSettingsKey = "uniwebview_settings";
  12. public override AndroidProjectFilesModifierContext Setup() {
  13. var context = new AndroidProjectFilesModifierContext {
  14. Dependencies = {
  15. DependencyFiles = new[] {
  16. // Set UniWebView editor settings asset path to be included in the build. With that we do not need
  17. // a clean build to update the settings anymore (maybe, not confirmed).
  18. UniWebViewEditorSettings.AssetPath
  19. }
  20. }
  21. };
  22. var settings = UniWebViewEditorSettings.GetOrCreateSettings();
  23. context.SetData(ContextSettingsKey, settings);
  24. return context;
  25. }
  26. public override void OnModifyAndroidProjectFiles(AndroidProjectFiles projectFiles) {
  27. var settings = projectFiles.GetData<UniWebViewEditorSettingsReading>(ContextSettingsKey);
  28. PatchUnityLibraryAndroidManifest(projectFiles.UnityLibraryManifest, settings);
  29. PatchUnityLibraryBuildGradle(projectFiles.UnityLibraryBuildGradle, settings);
  30. PatchGradleProperty(projectFiles.GradleProperties, settings);
  31. }
  32. private void PatchUnityLibraryAndroidManifest(
  33. AndroidManifestFile manifest, UniWebViewEditorSettingsReading settings
  34. ) {
  35. // Set hardwareAccelerated
  36. var launcherActivities = manifest.Manifest.GetActivitiesWithLauncherIntent();
  37. foreach (var activity in launcherActivities) {
  38. // Required for playing video in web view.
  39. activity.Attributes.HardwareAccelerated.Set(true);
  40. }
  41. // Set usesCleartextTraffic
  42. if (settings.usesCleartextTraffic) {
  43. manifest.Manifest.Application.Attributes.UsesCleartextTraffic.Set(true);
  44. }
  45. // Set WRITE_EXTERNAL_STORAGE permission
  46. if (settings.writeExternalStorage) {
  47. AddUsesPermission(manifest, "android.permission.WRITE_EXTERNAL_STORAGE");
  48. }
  49. // Set ACCESS_FINE_LOCATION permission
  50. if (settings.accessFineLocation) {
  51. AddUsesPermission(manifest, "android.permission.ACCESS_FINE_LOCATION");
  52. }
  53. // Set auth callback intent filter
  54. if (settings.authCallbackUrls.Length > 0 || settings.supportLINELogin) {
  55. var authActivity = new Activity();
  56. authActivity.Attributes.Name.Set("com.onevcat.uniwebview.UniWebViewAuthenticationActivity");
  57. authActivity.Attributes.Exported.Set(true);
  58. authActivity.Attributes.LaunchMode.Set(LaunchMode.SingleTask);
  59. authActivity.Attributes.ConfigChanges.Set(
  60. new[] {
  61. ConfigChanges.Orientation, ConfigChanges.ScreenSize, ConfigChanges.KeyboardHidden
  62. });
  63. foreach (var url in settings.authCallbackUrls) {
  64. AddAuthCallbacksIntentFilter(authActivity, url);
  65. }
  66. if (settings.supportLINELogin) {
  67. AddAuthCallbacksIntentFilter(authActivity, "lineauth://auth");
  68. }
  69. manifest.Manifest.Application.ActivityList.AddElement(authActivity);
  70. }
  71. }
  72. private void PatchUnityLibraryBuildGradle(ModuleBuildGradleFile gradleFile, UniWebViewEditorSettingsReading settings) {
  73. if (settings.addsKotlin) {
  74. var kotlinPrefix = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:";
  75. var kotlinVersion = String.IsNullOrWhiteSpace(settings.kotlinVersion)
  76. ? UniWebViewEditorSettings.defaultKotlinVersion : settings.kotlinVersion;
  77. ReplaceContentOrAddStartsWith(gradleFile.Dependencies,
  78. kotlinPrefix,
  79. kotlinVersion);
  80. Debug.Log("<UniWebView> Updated Kotlin dependency in build.gradle.");
  81. }
  82. if (settings.addsAndroidBrowser) {
  83. var browserPrefix = "androidx.browser:browser:";
  84. var browserVersion = String.IsNullOrWhiteSpace(settings.androidBrowserVersion)
  85. ? UniWebViewEditorSettings.defaultAndroidBrowserVersion : settings.androidBrowserVersion;
  86. ReplaceContentOrAddStartsWith(gradleFile.Dependencies,
  87. browserPrefix,
  88. browserVersion);
  89. Debug.Log("<UniWebView> Updated Browser dependency in build.gradle.");
  90. }
  91. if (!settings.addsAndroidBrowser && settings.addsAndroidXCore) {
  92. var androidXCorePrefix = "androidx.core:core:";
  93. var androidXCoreVersion = String.IsNullOrWhiteSpace(settings.androidXCoreVersion)
  94. ? UniWebViewEditorSettings.defaultAndroidXCoreVersion : settings.androidXCoreVersion;
  95. ReplaceContentOrAddStartsWith(gradleFile.Dependencies,
  96. androidXCorePrefix,
  97. androidXCoreVersion);
  98. Debug.Log("<UniWebView> Updated Android X Core dependency in build.gradle.");
  99. }
  100. }
  101. private void PatchGradleProperty(GradlePropertiesFile file, UniWebViewEditorSettingsReading settings) {
  102. var values = file.GetElements();
  103. foreach (var ele in values) {
  104. if (ele.GetRaw().Contains("android.enableJetifier")) {
  105. ele.SetRaw("android.enableJetifier=" + (settings.enableJetifier ? "true": "false"));
  106. }
  107. }
  108. }
  109. private void AddUsesPermission(AndroidManifestFile manifest, string name) {
  110. var list = manifest.Manifest.UsesPermissionList;
  111. foreach (var item in list) {
  112. Debug.LogError(item.GetName());
  113. }
  114. var existing = manifest.Manifest.UsesPermissionList
  115. .FirstOrDefault(ele => ele.Attributes.Name.Get() == name);
  116. if (existing != null) {
  117. return;
  118. }
  119. var permission = new UsesPermission();
  120. permission.Attributes.Name.Set(name);
  121. manifest.Manifest.UsesPermissionList.AddElement(permission);
  122. }
  123. private void AddAuthCallbacksIntentFilter(Activity activity, string callbackUrl) {
  124. var uri = new Uri(callbackUrl);
  125. var scheme = uri.Scheme;
  126. if (String.IsNullOrEmpty(scheme)) {
  127. Debug.LogError("<UniWebView> Auth callback url contains an empty scheme. Please check the url: " + callbackUrl);
  128. return;
  129. }
  130. var intentFilter = new IntentFilter();
  131. var action = new Action();
  132. action.Attributes.Name.Set("android.intent.action.VIEW");
  133. intentFilter.ActionList.AddElement(action);
  134. var defaultCategory = new Category();
  135. intentFilter.CategoryList.AddElement(defaultCategory);
  136. defaultCategory.Attributes.Name.Set("android.intent.category.DEFAULT");
  137. var browsableCategory = new Category();
  138. browsableCategory.Attributes.Name.Set("android.intent.category.BROWSABLE");
  139. intentFilter.CategoryList.AddElement(browsableCategory);
  140. var data = new Data();
  141. data.Attributes.Scheme.Set(scheme);
  142. if (!String.IsNullOrEmpty(uri.Host)) {
  143. data.Attributes.Host.Set(uri.Host);
  144. }
  145. if (uri.Port != -1) {
  146. data.Attributes.Port.Set(uri.Port.ToString());
  147. }
  148. if (!String.IsNullOrEmpty(uri.PathAndQuery) && uri.PathAndQuery != "/") {
  149. data.Attributes.Path.Set(uri.PathAndQuery);
  150. }
  151. intentFilter.DataList.AddElement(data);
  152. activity.IntentFilterList.AddElement(intentFilter);
  153. }
  154. private void ReplaceContentOrAddStartsWith(Dependencies dependencies, string prefix, string version) {
  155. var all = dependencies.GetElements();
  156. var matching = "implementation '" + prefix;
  157. var found = all.FirstOrDefault(ele => ele.GetRaw().StartsWith(matching));
  158. if (found != null) {
  159. found.SetRaw($"implementation '{prefix}{version}'");
  160. } else {
  161. dependencies.AddDependencyImplementationRaw($"'{prefix}{version}'");
  162. }
  163. }
  164. }
  165. #else
  166. using System;
  167. using UnityEditor;
  168. using UnityEditor.Android;
  169. using UnityEngine;
  170. using System.IO;
  171. using System.Text;
  172. class UniWebViewPostBuildProcessor : IPostGenerateGradleAndroidProject
  173. {
  174. public int callbackOrder { get { return 1; } }
  175. public void OnPostGenerateGradleAndroidProject(string path) {
  176. Debug.Log("<UniWebView> UniWebView Post Build Scirpt is patching manifest file and gradle file...");
  177. PatchAndroidManifest(path);
  178. PatchBuildGradle(path);
  179. PatchGradleProperty(path);
  180. }
  181. private void PatchAndroidManifest(string root) {
  182. var manifestFilePath = GetManifestFilePath(root);
  183. var manifest = new UniWebViewAndroidManifest(manifestFilePath);
  184. var changed = false;
  185. Debug.Log("<UniWebView> Set hardware accelerated to enable smooth web view experience and HTML5 support like video and canvas.");
  186. changed = manifest.SetHardwareAccelerated() || changed;
  187. var settings = UniWebViewEditorSettings.GetOrCreateSettings();
  188. if (settings.usesCleartextTraffic) {
  189. changed = manifest.SetUsesCleartextTraffic() || changed;
  190. }
  191. if (settings.writeExternalStorage) {
  192. changed = manifest.AddWriteExternalStoragePermission() || changed;
  193. }
  194. if (settings.accessFineLocation) {
  195. changed = manifest.AddAccessFineLocationPermission() || changed;
  196. }
  197. if (settings.authCallbackUrls.Length > 0) {
  198. changed = manifest.AddAuthCallbacksIntentFilter(settings.authCallbackUrls) || changed;
  199. }
  200. if (settings.supportLINELogin) {
  201. changed = manifest.AddAuthCallbacksIntentFilter(new string[] { "lineauth://auth" }) || changed;
  202. }
  203. if (changed) {
  204. manifest.Save();
  205. }
  206. }
  207. private void PatchBuildGradle(string root) {
  208. var gradleFilePath = GetGradleFilePath(root);
  209. var config = new UniWebViewGradleConfig(gradleFilePath);
  210. var settings = UniWebViewEditorSettings.GetOrCreateSettings();
  211. var kotlinPrefix = "implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:";
  212. var kotlinVersion = String.IsNullOrWhiteSpace(settings.kotlinVersion)
  213. ? UniWebViewEditorSettings.defaultKotlinVersion : settings.kotlinVersion;
  214. var browserPrefix = "implementation 'androidx.browser:browser:";
  215. var browserVersion = String.IsNullOrWhiteSpace(settings.androidBrowserVersion)
  216. ? UniWebViewEditorSettings.defaultAndroidBrowserVersion : settings.androidBrowserVersion;
  217. var androidXCorePrefix = "implementation 'androidx.core:core:";
  218. var androidXCoreVersion = String.IsNullOrWhiteSpace(settings.androidXCoreVersion)
  219. ? UniWebViewEditorSettings.defaultAndroidXCoreVersion : settings.androidXCoreVersion;
  220. var dependenciesNode = config.Root.FindChildNodeByName("dependencies");
  221. if (dependenciesNode != null) {
  222. // Add kotlin
  223. if (settings.addsKotlin) {
  224. dependenciesNode.ReplaceContentOrAddStartsWith(kotlinPrefix, kotlinPrefix + kotlinVersion + "'");
  225. Debug.Log("<UniWebView> Updated Kotlin dependency in build.gradle.");
  226. }
  227. // Add browser package
  228. if (settings.addsAndroidBrowser) {
  229. dependenciesNode.ReplaceContentOrAddStartsWith(browserPrefix, browserPrefix + browserVersion + "'");
  230. Debug.Log("<UniWebView> Updated Browser dependency in build.gradle.");
  231. }
  232. // Add Android X Core package
  233. if (!settings.addsAndroidBrowser && settings.addsAndroidXCore) {
  234. // When adding android browser to the project, we don't need to add Android X Core package, since gradle resolves for it.
  235. dependenciesNode.ReplaceContentOrAddStartsWith(androidXCorePrefix, androidXCorePrefix + androidXCoreVersion + "'");
  236. Debug.Log("<UniWebView> Updated Android X Core dependency in build.gradle.");
  237. }
  238. } else {
  239. Debug.LogError("UniWebViewPostBuildProcessor didn't find the `dependencies` field in build.gradle.");
  240. Debug.LogError("Although we can continue to add a `dependencies`, make sure you have setup Gradle and the template correctly.");
  241. var newNode = new UniWebViewGradleNode("dependencies", config.Root);
  242. if (settings.addsKotlin) {
  243. newNode.AppendContentNode(kotlinPrefix + kotlinVersion + "'");
  244. }
  245. if (settings.addsAndroidBrowser) {
  246. newNode.AppendContentNode(browserPrefix + browserVersion + "'");
  247. }
  248. if (settings.addsAndroidXCore) {
  249. newNode.AppendContentNode(androidXCorePrefix + androidXCoreVersion + "'");
  250. }
  251. newNode.AppendContentNode("implementation(name: 'UniWebView', ext:'aar')");
  252. config.Root.AppendChildNode(newNode);
  253. }
  254. config.Save();
  255. }
  256. private void PatchGradleProperty(string root) {
  257. var gradlePropertyFilePath = GetGradlePropertyFilePath(root);
  258. var patcher =
  259. new UniWebViewGradlePropertyPatcher(gradlePropertyFilePath, UniWebViewEditorSettings.GetOrCreateSettings());
  260. patcher.Patch();
  261. }
  262. private string CombinePaths(string[] paths) {
  263. var path = "";
  264. foreach (var item in paths) {
  265. path = Path.Combine(path, item);
  266. }
  267. return path;
  268. }
  269. private string GetManifestFilePath(string root) {
  270. string[] comps = {root, "src", "main", "AndroidManifest.xml"};
  271. return CombinePaths(comps);
  272. }
  273. private string GetGradleFilePath(string root) {
  274. string[] comps = {root, "build.gradle"};
  275. return CombinePaths(comps);
  276. }
  277. private string GetGradlePropertyFilePath(string root) {
  278. #if UNITY_2019_3_OR_NEWER
  279. string[] compos = {root, "..", "gradle.properties"};
  280. #else
  281. string[] compos = {root, "gradle.properties"};
  282. #endif
  283. return CombinePaths(compos);
  284. }
  285. }
  286. #endif