暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AndroidManifest.cs 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. using System.Xml;
  2. using System.Collections;
  3. using System.Text;
  4. using System.IO;
  5. using System;
  6. using UnityEditor;
  7. using UnityEngine;
  8. internal class UniWebViewAndroidXmlDocument : XmlDocument {
  9. private string path;
  10. protected XmlNamespaceManager nameSpaceManager;
  11. public readonly string AndroidXmlNamespace = "http://schemas.android.com/apk/res/android";
  12. public UniWebViewAndroidXmlDocument(string path) {
  13. this.path = path;
  14. using (var reader = new XmlTextReader(path)) {
  15. reader.Read();
  16. Load(reader);
  17. }
  18. nameSpaceManager = new XmlNamespaceManager(NameTable);
  19. nameSpaceManager.AddNamespace("android", AndroidXmlNamespace);
  20. }
  21. public string Save() {
  22. return SaveAs(path);
  23. }
  24. public string SaveAs(string path) {
  25. using (var writer = new XmlTextWriter(path, new UTF8Encoding(false))) {
  26. writer.Formatting = Formatting.Indented;
  27. Save(writer);
  28. }
  29. return path;
  30. }
  31. }
  32. internal class UniWebViewAndroidManifest : UniWebViewAndroidXmlDocument {
  33. private readonly XmlElement ManifestElement;
  34. private readonly XmlElement ApplicationElement;
  35. public UniWebViewAndroidManifest(string path) : base(path) {
  36. ManifestElement = SelectSingleNode("/manifest") as XmlElement;
  37. ApplicationElement = SelectSingleNode("/manifest/application") as XmlElement;
  38. }
  39. private XmlAttribute CreateAndroidAttribute(string key, string value) {
  40. XmlAttribute attr = CreateAttribute("android", key, AndroidXmlNamespace);
  41. attr.Value = value;
  42. return attr;
  43. }
  44. internal XmlNode GetActivityWithLaunchIntent() {
  45. return
  46. SelectSingleNode(
  47. "/manifest/application/activity[intent-filter/action/@android:name='android.intent.action.MAIN' and "
  48. + "intent-filter/category/@android:name='android.intent.category.LAUNCHER']",
  49. nameSpaceManager);
  50. }
  51. internal bool SetUsesCleartextTraffic() {
  52. bool changed = false;
  53. if (ApplicationElement.GetAttribute("usesCleartextTraffic", AndroidXmlNamespace) != "true") {
  54. ApplicationElement.SetAttribute("usesCleartextTraffic", AndroidXmlNamespace, "true");
  55. changed = true;
  56. }
  57. return changed;
  58. }
  59. internal bool SetHardwareAccelerated() {
  60. bool changed = false;
  61. var activity = GetActivityWithLaunchIntent() as XmlElement;
  62. if (activity.GetAttribute("hardwareAccelerated", AndroidXmlNamespace) != "true") {
  63. activity.SetAttribute("hardwareAccelerated", AndroidXmlNamespace, "true");
  64. changed = true;
  65. }
  66. return changed;
  67. }
  68. internal bool AddCameraPermission() {
  69. bool changed = false;
  70. if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.CAMERA']", nameSpaceManager).Count == 0) {
  71. var elem = CreateElement("uses-permission");
  72. elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.CAMERA"));
  73. ManifestElement.AppendChild(elem);
  74. changed = true;
  75. }
  76. if (SelectNodes("/manifest/uses-feature[@android:name='android.hardware.camera']", nameSpaceManager).Count == 0) {
  77. var elem = CreateElement("uses-feature");
  78. elem.Attributes.Append(CreateAndroidAttribute("name", "android.hardware.camera"));
  79. ManifestElement.AppendChild(elem);
  80. changed = true;
  81. }
  82. return changed;
  83. }
  84. internal bool AddMicrophonePermission() {
  85. bool changed = false;
  86. if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.MICROPHONE']", nameSpaceManager).Count == 0) {
  87. var elem = CreateElement("uses-permission");
  88. elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.MICROPHONE"));
  89. ManifestElement.AppendChild(elem);
  90. changed = true;
  91. }
  92. if (SelectNodes("/manifest/uses-feature[@android:name='android.hardware.microphone']", nameSpaceManager).Count == 0) {
  93. var elem = CreateElement("uses-feature");
  94. elem.Attributes.Append(CreateAndroidAttribute("name", "android.hardware.microphone"));
  95. ManifestElement.AppendChild(elem);
  96. changed = true;
  97. }
  98. return changed;
  99. }
  100. internal bool AddReadExternalStoragePermission() {
  101. bool changed = false;
  102. if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.READ_EXTERNAL_STORAGE']", nameSpaceManager).Count == 0) {
  103. var elem = CreateElement("uses-permission");
  104. elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.READ_EXTERNAL_STORAGE"));
  105. ManifestElement.AppendChild(elem);
  106. changed = true;
  107. }
  108. return changed;
  109. }
  110. internal bool AddWriteExternalStoragePermission() {
  111. bool changed = false;
  112. if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.WRITE_EXTERNAL_STORAGE']", nameSpaceManager).Count == 0) {
  113. var elem = CreateElement("uses-permission");
  114. elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.WRITE_EXTERNAL_STORAGE"));
  115. ManifestElement.AppendChild(elem);
  116. changed = true;
  117. }
  118. return changed;
  119. }
  120. internal bool AddAccessFineLocationPermission() {
  121. bool changed = false;
  122. if (SelectNodes("/manifest/uses-permission[@android:name='android.permission.ACCESS_FINE_LOCATION']", nameSpaceManager).Count == 0) {
  123. var elem = CreateElement("uses-permission");
  124. elem.Attributes.Append(CreateAndroidAttribute("name", "android.permission.ACCESS_FINE_LOCATION"));
  125. ManifestElement.AppendChild(elem);
  126. changed = true;
  127. }
  128. return changed;
  129. }
  130. internal bool AddAuthCallbacksIntentFilter(string[] authCallbackUrls) {
  131. bool changed = false;
  132. XmlElement authActivityNode;
  133. if (authCallbackUrls.Length > 0) {
  134. var list = SelectNodes("/manifest/application/activity[@android:name='com.onevcat.uniwebview.UniWebViewAuthenticationActivity']", nameSpaceManager);
  135. if (list.Count == 0) {
  136. var created = CreateElement("activity");
  137. created.SetAttribute("name", AndroidXmlNamespace, "com.onevcat.uniwebview.UniWebViewAuthenticationActivity");
  138. created.SetAttribute("exported", AndroidXmlNamespace, "true");
  139. created.SetAttribute("launchMode", AndroidXmlNamespace, "singleTop");
  140. created.SetAttribute("configChanges", AndroidXmlNamespace, "orientation|screenSize|keyboardHidden");
  141. authActivityNode = created;
  142. } else {
  143. authActivityNode = list[0] as XmlElement;
  144. }
  145. } else {
  146. return changed;
  147. }
  148. foreach (var url in authCallbackUrls) {
  149. var intentFilter = CreateIntentFilter(url);
  150. if (intentFilter != null) {
  151. authActivityNode.AppendChild(intentFilter);
  152. changed = true;
  153. }
  154. }
  155. ApplicationElement.AppendChild(authActivityNode);
  156. return changed;
  157. }
  158. private XmlElement CreateIntentFilter(string url) {
  159. var uri = new Uri(url);
  160. var scheme = uri.Scheme;
  161. if (String.IsNullOrEmpty(scheme)) {
  162. Debug.LogError("<UniWebView> Auth callback url contains an empty scheme. Please check the url: " + url);
  163. return null;
  164. }
  165. var filter = CreateElement("intent-filter");
  166. var action = CreateElement("action");
  167. action.SetAttribute("name", AndroidXmlNamespace, "android.intent.action.VIEW");
  168. filter.AppendChild(action);
  169. var defaultCategory = CreateElement("category");
  170. defaultCategory.SetAttribute("name", AndroidXmlNamespace, "android.intent.category.DEFAULT");
  171. filter.AppendChild(defaultCategory);
  172. var browseCategory = CreateElement("category");
  173. browseCategory.SetAttribute("name", AndroidXmlNamespace, "android.intent.category.BROWSABLE");
  174. filter.AppendChild(browseCategory);
  175. var data = CreateElement("data");
  176. data.SetAttribute("scheme", AndroidXmlNamespace, scheme);
  177. if (!String.IsNullOrEmpty(uri.Host)) {
  178. data.SetAttribute("host", AndroidXmlNamespace, uri.Host);
  179. }
  180. if (uri.Port != -1) {
  181. data.SetAttribute("port", AndroidXmlNamespace, uri.Port.ToString());
  182. }
  183. if (!String.IsNullOrEmpty(uri.PathAndQuery) && uri.PathAndQuery != "/") {
  184. data.SetAttribute("path", AndroidXmlNamespace, uri.PathAndQuery);
  185. }
  186. filter.AppendChild(data);
  187. return filter;
  188. }
  189. }