179 lines
7.3 KiB
C#
179 lines
7.3 KiB
C#
|
|
|
||
|
|
|
||
|
|
#if UNITY_ANDROID
|
||
|
|
|
||
|
|
namespace Guru.Notification
|
||
|
|
{
|
||
|
|
using System;
|
||
|
|
using System.IO;
|
||
|
|
using UnityEditor.Android;
|
||
|
|
using System.Xml;
|
||
|
|
|
||
|
|
public class PostCustomActivity: IPostGenerateGradleAndroidProject
|
||
|
|
{
|
||
|
|
private const int POST_ORDER = 10;
|
||
|
|
private const string K_PREMISSION_POST_NOTIFICATIONS = "android.permission.POST_NOTIFICATIONS";
|
||
|
|
private const string K_CUSTOM_NOTIFICATION_ACTIVITY = "custom_notification_android_activity";
|
||
|
|
private const string V_DEFAULT_GURU_ACTIVITY = "com.google.firebase.messaging.MessageForwardingService";
|
||
|
|
const string K_ANDROID_NAMESPACE_URI = "http://schemas.android.com/apk/res/android";
|
||
|
|
|
||
|
|
public int callbackOrder => POST_ORDER;
|
||
|
|
|
||
|
|
public void OnPostGenerateGradleAndroidProject(string path)
|
||
|
|
{
|
||
|
|
SetupAndroidManifest(path);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 设置 Android Manifest
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="projectPath"></param>
|
||
|
|
/// <exception cref="FileNotFoundException"></exception>
|
||
|
|
private void SetupAndroidManifest(string projectPath)
|
||
|
|
{
|
||
|
|
var manifestPath = $"{projectPath}/src/main/AndroidManifest.xml";
|
||
|
|
if (!File.Exists(manifestPath))
|
||
|
|
throw new FileNotFoundException($"'{manifestPath}' doesn't exist.");
|
||
|
|
|
||
|
|
XmlDocument manifestDoc = new XmlDocument();
|
||
|
|
manifestDoc.Load(manifestPath);
|
||
|
|
|
||
|
|
InjectAndroidManifest(manifestPath, manifestDoc);
|
||
|
|
|
||
|
|
manifestDoc.Save(manifestPath);
|
||
|
|
}
|
||
|
|
|
||
|
|
internal static void InjectAndroidManifest(string manifestPath, XmlDocument manifestDoc)
|
||
|
|
{
|
||
|
|
string mainActivity = GetLauncherActivity(manifestDoc);
|
||
|
|
|
||
|
|
AppendAndroidMetadataField(manifestPath, manifestDoc, K_CUSTOM_NOTIFICATION_ACTIVITY, mainActivity);
|
||
|
|
AppendAndroidPermissionField(manifestPath, manifestDoc, K_PREMISSION_POST_NOTIFICATIONS);
|
||
|
|
|
||
|
|
UnityEngine.Debug.Log($"<color=#88ff00>Add custom notification activity: {mainActivity} success!!</color>");
|
||
|
|
}
|
||
|
|
|
||
|
|
internal static void AppendAndroidPermissionField(string manifestPath, XmlDocument xmlDoc, string name, string maxSdk = null)
|
||
|
|
{
|
||
|
|
AppendAndroidPermissionField(manifestPath, xmlDoc, "uses-permission", name, maxSdk);
|
||
|
|
}
|
||
|
|
|
||
|
|
internal static void AppendAndroidPermissionField(string manifestPath, XmlDocument xmlDoc, string tagName, string name, string maxSdk)
|
||
|
|
{
|
||
|
|
var manifestNode = xmlDoc.SelectSingleNode("manifest");
|
||
|
|
if (manifestNode == null)
|
||
|
|
throw new ArgumentException(string.Format("Missing 'manifest' node in '{0}'.", manifestPath));
|
||
|
|
|
||
|
|
XmlElement metaDataNode = null;
|
||
|
|
foreach (XmlNode node in manifestNode.ChildNodes)
|
||
|
|
{
|
||
|
|
if (!(node is XmlElement) || node.Name != tagName)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
var element = (XmlElement)node;
|
||
|
|
var elementName = element.GetAttribute("name", K_ANDROID_NAMESPACE_URI);
|
||
|
|
if (elementName == name)
|
||
|
|
{
|
||
|
|
if (maxSdk == null)
|
||
|
|
return;
|
||
|
|
var maxSdkAttr = element.GetAttribute("maxSdkVersion", K_ANDROID_NAMESPACE_URI);
|
||
|
|
if (!string.IsNullOrEmpty(maxSdkAttr))
|
||
|
|
return;
|
||
|
|
metaDataNode = element;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (metaDataNode == null)
|
||
|
|
{
|
||
|
|
metaDataNode = xmlDoc.CreateElement(tagName);
|
||
|
|
metaDataNode.SetAttribute("name", K_ANDROID_NAMESPACE_URI, name);
|
||
|
|
}
|
||
|
|
if (maxSdk != null)
|
||
|
|
metaDataNode.SetAttribute("maxSdkVersion", K_ANDROID_NAMESPACE_URI, maxSdk);
|
||
|
|
|
||
|
|
manifestNode.AppendChild(metaDataNode);
|
||
|
|
}
|
||
|
|
|
||
|
|
internal static void AppendAndroidMetadataField(string manifestPath, XmlDocument xmlDoc, string name, string value)
|
||
|
|
{
|
||
|
|
var applicationNode = xmlDoc.SelectSingleNode("manifest/application");
|
||
|
|
if (applicationNode == null)
|
||
|
|
throw new ArgumentException(string.Format("Missing 'application' node in '{0}'.", manifestPath));
|
||
|
|
|
||
|
|
var nodes = xmlDoc.SelectNodes("manifest/application/meta-data");
|
||
|
|
if (nodes != null)
|
||
|
|
{
|
||
|
|
// Check if there is a 'meta-data' with the same name.
|
||
|
|
foreach (XmlNode node in nodes)
|
||
|
|
{
|
||
|
|
var element = node as XmlElement;
|
||
|
|
if (element == null)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
var elementName = element.GetAttribute("name", K_ANDROID_NAMESPACE_URI);
|
||
|
|
if (elementName == name)
|
||
|
|
{
|
||
|
|
element.SetAttribute("value", K_ANDROID_NAMESPACE_URI, value);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
XmlElement metaDataNode = xmlDoc.CreateElement("meta-data");
|
||
|
|
metaDataNode.SetAttribute("name", K_ANDROID_NAMESPACE_URI, name);
|
||
|
|
metaDataNode.SetAttribute("value", K_ANDROID_NAMESPACE_URI, value);
|
||
|
|
|
||
|
|
applicationNode.AppendChild(metaDataNode);
|
||
|
|
}
|
||
|
|
|
||
|
|
internal static string GetLauncherActivity(XmlDocument xmlDoc)
|
||
|
|
{
|
||
|
|
var applicationNode = xmlDoc.SelectSingleNode("manifest/application");
|
||
|
|
if (applicationNode == null)
|
||
|
|
throw new ArgumentException($"Missing 'application' node in doc.");
|
||
|
|
|
||
|
|
var nodes = xmlDoc.SelectNodes("manifest/application/activity");
|
||
|
|
if (nodes != null)
|
||
|
|
{
|
||
|
|
foreach (XmlNode node in nodes)
|
||
|
|
{
|
||
|
|
var activityNode = node as XmlElement;
|
||
|
|
if (activityNode == null)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
if (activityNode.HasChildNodes)
|
||
|
|
{
|
||
|
|
var intentFilterNode = activityNode.SelectSingleNode("intent-filter");
|
||
|
|
|
||
|
|
if(intentFilterNode == null || !intentFilterNode.HasChildNodes)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
foreach (XmlElement childNode in intentFilterNode)
|
||
|
|
{
|
||
|
|
if(childNode == null) continue;
|
||
|
|
|
||
|
|
// 判断 action/category 二者取其一
|
||
|
|
if (childNode.Name == "action" && childNode.InnerXml.Contains("android.intent.action.MAIN"))
|
||
|
|
{
|
||
|
|
var activityName = activityNode.GetAttribute("name", K_ANDROID_NAMESPACE_URI);
|
||
|
|
return activityName;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (childNode.Name == "category" && childNode.InnerXml.Contains("android.intent.category.LAUNCHER"))
|
||
|
|
{
|
||
|
|
var activityName = activityNode.GetAttribute("name", K_ANDROID_NAMESPACE_URI);
|
||
|
|
return activityName;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return V_DEFAULT_GURU_ACTIVITY;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|