You've already forked Commercialization.tapadn
Implement TapADN commercialization module
This commit is contained in:
285
Tapadn_Adapter/Editor/TapadnBuildAndroidProcess.cs
Normal file
285
Tapadn_Adapter/Editor/TapadnBuildAndroidProcess.cs
Normal file
@@ -0,0 +1,285 @@
|
||||
#if UNITY_ANDROID
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Android;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Tapadn_Adapter.Editor
|
||||
{
|
||||
public sealed class TapadnBuildAndroidProcess : IPostGenerateGradleAndroidProject
|
||||
{
|
||||
private static readonly XNamespace AndroidNamespace = "http://schemas.android.com/apk/res/android";
|
||||
private static readonly XNamespace ToolsNamespace = "http://schemas.android.com/tools";
|
||||
|
||||
public int callbackOrder => 180;
|
||||
|
||||
public void OnPostGenerateGradleAndroidProject(string path)
|
||||
{
|
||||
ProcessGradleProperties(path);
|
||||
ProcessAndroidManifest(path);
|
||||
}
|
||||
|
||||
public static void ProcessAndroidManifest(string path)
|
||||
{
|
||||
var unityManifestPath = Path.Combine(path, "src/main/AndroidManifest.xml");
|
||||
var launcherManifestPath = Path.Combine(path, "../launcher/src/main/AndroidManifest.xml");
|
||||
var providerTargetManifestPath = File.Exists(launcherManifestPath) ? launcherManifestPath : unityManifestPath;
|
||||
|
||||
if (!File.Exists(unityManifestPath))
|
||||
{
|
||||
Debug.LogWarning($"[TapADN] AndroidManifest.xml is missing: {unityManifestPath}");
|
||||
return;
|
||||
}
|
||||
|
||||
var unityManifest = XDocument.Load(unityManifestPath);
|
||||
EnsureManifestPatch(unityManifest, true, false);
|
||||
unityManifest.Save(unityManifestPath);
|
||||
|
||||
if (File.Exists(providerTargetManifestPath))
|
||||
{
|
||||
var providerManifest = XDocument.Load(providerTargetManifestPath);
|
||||
EnsureManifestPatch(providerManifest, false, true);
|
||||
providerManifest.Save(providerTargetManifestPath);
|
||||
}
|
||||
|
||||
var resXmlPath = Path.Combine(path, "src/main/res/xml");
|
||||
Directory.CreateDirectory(resXmlPath);
|
||||
var sourceXmlPath = GetEditorAssetPath("tapad_ad_file_path.xml");
|
||||
if (!string.IsNullOrEmpty(sourceXmlPath) && File.Exists(sourceXmlPath))
|
||||
{
|
||||
File.Copy(sourceXmlPath, Path.Combine(resXmlPath, "tapad_ad_file_path.xml"), true);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnsureManifestPatch(XDocument manifest, bool includeWechatActivity, bool includeTapadProvider)
|
||||
{
|
||||
var manifestElement = manifest.Element("manifest");
|
||||
if (manifestElement == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureNamespace(manifestElement, "tools", ToolsNamespace.NamespaceName);
|
||||
|
||||
EnsurePermission(manifestElement, "android.permission.INTERNET");
|
||||
EnsurePermission(manifestElement, "android.permission.ACCESS_NETWORK_STATE");
|
||||
EnsurePermission(manifestElement, "android.permission.READ_PHONE_STATE");
|
||||
EnsurePermission(manifestElement, "android.permission.QUERY_ALL_PACKAGES");
|
||||
EnsurePermission(manifestElement, "android.permission.REQUEST_INSTALL_PACKAGES");
|
||||
EnsurePermission(manifestElement, "android.permission.BLUETOOTH");
|
||||
EnsurePermission(manifestElement, "android.permission.BLUETOOTH_CONNECT");
|
||||
EnsurePermission(manifestElement, "android.permission.ACCESS_FINE_LOCATION");
|
||||
EnsurePermission(manifestElement, "android.permission.ACCESS_COARSE_LOCATION");
|
||||
EnsurePermission(manifestElement, "android.permission.POST_NOTIFICATIONS");
|
||||
EnsureWechatQueries(manifestElement);
|
||||
|
||||
var applicationElement = manifestElement.Element("application");
|
||||
if (applicationElement == null)
|
||||
{
|
||||
applicationElement = new XElement("application");
|
||||
manifestElement.Add(applicationElement);
|
||||
}
|
||||
|
||||
SetUnityActivitySingleTop(applicationElement);
|
||||
|
||||
if (includeWechatActivity)
|
||||
{
|
||||
EnsureWechatEntryActivity(applicationElement);
|
||||
}
|
||||
|
||||
if (includeTapadProvider)
|
||||
{
|
||||
EnsureTapadFileProvider(applicationElement);
|
||||
SetOrAddAttribute(applicationElement, AndroidNamespace + "allowBackup", "false");
|
||||
MergeToolsReplaceAttribute(applicationElement, "android:allowBackup");
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnsurePermission(XElement manifestElement, string permissionName)
|
||||
{
|
||||
var exists = manifestElement.Elements("uses-permission")
|
||||
.Any(element => element.Attribute(AndroidNamespace + "name")?.Value == permissionName);
|
||||
if (exists)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var permission = new XElement("uses-permission");
|
||||
permission.Add(new XAttribute(AndroidNamespace + "name", permissionName));
|
||||
if (permissionName == "android.permission.BLUETOOTH_CONNECT" ||
|
||||
permissionName == "android.permission.POST_NOTIFICATIONS")
|
||||
{
|
||||
permission.Add(new XAttribute(ToolsNamespace + "targetApi", permissionName.EndsWith("CONNECT") ? "s" : "33"));
|
||||
}
|
||||
|
||||
manifestElement.Add(permission);
|
||||
}
|
||||
|
||||
private static void EnsureWechatQueries(XElement manifestElement)
|
||||
{
|
||||
var queries = manifestElement.Elements("queries").FirstOrDefault();
|
||||
if (queries == null)
|
||||
{
|
||||
queries = new XElement("queries");
|
||||
manifestElement.Add(queries);
|
||||
}
|
||||
|
||||
var exists = queries.Elements("package")
|
||||
.Any(element => element.Attribute(AndroidNamespace + "name")?.Value == "com.tencent.mm");
|
||||
if (!exists)
|
||||
{
|
||||
var packageElement = new XElement("package");
|
||||
packageElement.Add(new XAttribute(AndroidNamespace + "name", "com.tencent.mm"));
|
||||
queries.Add(packageElement);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnsureWechatEntryActivity(XElement applicationElement)
|
||||
{
|
||||
RemoveElementsByAndroidName(applicationElement, "activity", ".wxapi.WXEntryActivity");
|
||||
|
||||
var activity = new XElement("activity");
|
||||
activity.Add(new XAttribute(AndroidNamespace + "name", ".wxapi.WXEntryActivity"));
|
||||
activity.Add(new XAttribute(AndroidNamespace + "label", "@string/app_name"));
|
||||
activity.Add(new XAttribute(AndroidNamespace + "theme", "@android:style/Theme.Translucent.NoTitleBar"));
|
||||
activity.Add(new XAttribute(AndroidNamespace + "exported", "true"));
|
||||
activity.Add(new XAttribute(AndroidNamespace + "taskAffinity", Application.identifier));
|
||||
activity.Add(new XAttribute(AndroidNamespace + "launchMode", "singleTop"));
|
||||
applicationElement.Add(activity);
|
||||
}
|
||||
|
||||
private static void EnsureTapadFileProvider(XElement applicationElement)
|
||||
{
|
||||
RemoveElementsByAndroidName(applicationElement, "provider", "com.tapsdk.tapad.internal.TapADFileProvider");
|
||||
|
||||
var provider = new XElement("provider");
|
||||
provider.Add(new XAttribute(AndroidNamespace + "name", "com.tapsdk.tapad.internal.TapADFileProvider"));
|
||||
provider.Add(new XAttribute(AndroidNamespace + "authorities", "${applicationId}.com.tds.ad.fileprovider"));
|
||||
provider.Add(new XAttribute(AndroidNamespace + "exported", "false"));
|
||||
provider.Add(new XAttribute(AndroidNamespace + "grantUriPermissions", "true"));
|
||||
provider.Add(new XAttribute(ToolsNamespace + "replace", "android:authorities"));
|
||||
|
||||
var metadata = new XElement("meta-data");
|
||||
metadata.Add(new XAttribute(AndroidNamespace + "name", "android.support.FILE_PROVIDER_PATHS"));
|
||||
metadata.Add(new XAttribute(AndroidNamespace + "resource", "@xml/tapad_ad_file_path"));
|
||||
provider.Add(metadata);
|
||||
|
||||
applicationElement.Add(provider);
|
||||
}
|
||||
|
||||
private static void SetUnityActivitySingleTop(XElement applicationElement)
|
||||
{
|
||||
foreach (var activity in applicationElement.Elements("activity"))
|
||||
{
|
||||
var name = activity.Attribute(AndroidNamespace + "name")?.Value;
|
||||
if (name == "com.unity3d.player.UnityPlayerActivity")
|
||||
{
|
||||
SetOrAddAttribute(activity, AndroidNamespace + "launchMode", "singleTop");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void RemoveElementsByAndroidName(XElement parent, string localName, string androidName)
|
||||
{
|
||||
parent.Elements(localName)
|
||||
.Where(element => element.Attribute(AndroidNamespace + "name")?.Value == androidName)
|
||||
.ToList()
|
||||
.ForEach(element => element.Remove());
|
||||
}
|
||||
|
||||
private static void ProcessGradleProperties(string path)
|
||||
{
|
||||
var root = Directory.GetParent(path)?.FullName;
|
||||
if (string.IsNullOrEmpty(root))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var gradlePropertiesPath = Path.Combine(root, "gradle.properties");
|
||||
var lines = File.Exists(gradlePropertiesPath)
|
||||
? File.ReadAllLines(gradlePropertiesPath).ToList()
|
||||
: new List<string>();
|
||||
|
||||
UpsertProperty(lines, "android.useAndroidX", "true");
|
||||
UpsertProperty(lines, "android.enableJetifier", "true");
|
||||
|
||||
File.WriteAllText(gradlePropertiesPath, string.Join("\n", lines) + "\n");
|
||||
}
|
||||
|
||||
private static void UpsertProperty(List<string> lines, string key, string value)
|
||||
{
|
||||
var prefix = key + "=";
|
||||
var index = lines.FindIndex(line => line.TrimStart().StartsWith(prefix));
|
||||
if (index >= 0)
|
||||
{
|
||||
lines[index] = prefix + value;
|
||||
return;
|
||||
}
|
||||
|
||||
lines.Add(prefix + value);
|
||||
}
|
||||
|
||||
private static void SetOrAddAttribute(XElement element, XName attributeName, string value)
|
||||
{
|
||||
var attribute = element.Attribute(attributeName);
|
||||
if (attribute == null)
|
||||
{
|
||||
element.Add(new XAttribute(attributeName, value));
|
||||
return;
|
||||
}
|
||||
|
||||
attribute.SetValue(value);
|
||||
}
|
||||
|
||||
private static void MergeToolsReplaceAttribute(XElement element, params string[] replaceValues)
|
||||
{
|
||||
var replaceAttributeName = ToolsNamespace + "replace";
|
||||
var mergedValues = new List<string>();
|
||||
var currentValue = element.Attribute(replaceAttributeName)?.Value;
|
||||
if (!string.IsNullOrWhiteSpace(currentValue))
|
||||
{
|
||||
mergedValues.AddRange(currentValue.Split(',')
|
||||
.Select(value => value.Trim())
|
||||
.Where(value => !string.IsNullOrWhiteSpace(value)));
|
||||
}
|
||||
|
||||
foreach (var replaceValue in replaceValues)
|
||||
{
|
||||
if (!mergedValues.Contains(replaceValue))
|
||||
{
|
||||
mergedValues.Add(replaceValue);
|
||||
}
|
||||
}
|
||||
|
||||
element.SetAttributeValue(replaceAttributeName, string.Join(",", mergedValues));
|
||||
}
|
||||
|
||||
private static void EnsureNamespace(XElement element, string prefix, string namespaceName)
|
||||
{
|
||||
var namespaceAttributeName = XNamespace.Xmlns + prefix;
|
||||
if (element.Attribute(namespaceAttributeName) == null)
|
||||
{
|
||||
element.Add(new XAttribute(namespaceAttributeName, namespaceName));
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetEditorAssetPath(string fileName)
|
||||
{
|
||||
var guids = AssetDatabase.FindAssets(Path.GetFileNameWithoutExtension(fileName));
|
||||
foreach (var guid in guids)
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (Path.GetFileName(path) == fileName)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user