From 9d08938d7701272bb60ed46357326aead14ad401 Mon Sep 17 00:00:00 2001 From: huyufei Date: Sat, 30 Mar 2024 10:21:08 +0800 Subject: [PATCH] =?UTF-8?q?update:=20=E5=AE=8C=E5=96=84push=E5=9B=BE?= =?UTF-8?q?=E6=A0=87=E7=94=9F=E6=88=90=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Files/sdk_res/project.properties | 2 +- Editor/GuruManager/Helper/AndroidLibHelper.cs | 57 ++++ .../Helper/AndroidLibHelper.cs.meta | 3 + .../GuruManager/Helper/AndroidManifestMod.cs | 2 +- Editor/GuruManager/Helper/MainManifestDoc.cs | 257 ++++++++++++++++++ .../Helper/MainManifestDoc.cs.meta | 3 + Editor/GuruManager/Helper/PushIconHelper.cs | 148 ++++++++++ .../GuruManager/Helper/PushIconHelper.cs.meta | 3 + Editor/GuruManager/Manager/GuruSDKManager.cs | 61 ++++- Editor/GuruSDK.Editor.asmdef | 3 +- Runtime/Code/SDK/GuruSDK.cs | 2 +- package.json | 2 +- 12 files changed, 537 insertions(+), 6 deletions(-) create mode 100644 Editor/GuruManager/Helper/AndroidLibHelper.cs create mode 100644 Editor/GuruManager/Helper/AndroidLibHelper.cs.meta create mode 100644 Editor/GuruManager/Helper/MainManifestDoc.cs create mode 100644 Editor/GuruManager/Helper/MainManifestDoc.cs.meta create mode 100644 Editor/GuruManager/Helper/PushIconHelper.cs create mode 100644 Editor/GuruManager/Helper/PushIconHelper.cs.meta diff --git a/Editor/GuruManager/Files/sdk_res/project.properties b/Editor/GuruManager/Files/sdk_res/project.properties index 37b95ed..3e9d5b2 100644 --- a/Editor/GuruManager/Files/sdk_res/project.properties +++ b/Editor/GuruManager/Files/sdk_res/project.properties @@ -1,2 +1,2 @@ target=android-9 -android.library=true \ No newline at end of file +android.library=`true` \ No newline at end of file diff --git a/Editor/GuruManager/Helper/AndroidLibHelper.cs b/Editor/GuruManager/Helper/AndroidLibHelper.cs new file mode 100644 index 0000000..6b7acc1 --- /dev/null +++ b/Editor/GuruManager/Helper/AndroidLibHelper.cs @@ -0,0 +1,57 @@ +namespace Guru.Editor +{ + using System; + using System.IO; + using UnityEngine; + + /// + /// Create androidlib assets + /// + public class AndroidLibHelper + { + + private static readonly string PluginsRoot = "Plugins/Android"; + private static readonly string Extends = "androidlib"; + private static readonly string ProjectPropertiesName = "project.properties"; + private static readonly string ProjectPropertiesContent= "target=android-9\nandroid.library=true"; + private static readonly string AndroidManifestName = "AndroidManifest.xml"; + private static readonly string AndroidManifestContent = "\n\n"; + + + public static bool IsEmbeddedAndroidLibExists(string fileName) + { + string dir = Path.GetFullPath($"{Application.dataPath}/{PluginsRoot}/{fileName}.{Extends}"); + return Directory.Exists(dir); + } + + + public static string CreateLibRoot(string packageName, string fileName = "") + { + if (string.IsNullOrEmpty(packageName)) return ""; + + if(string.IsNullOrEmpty(fileName)) fileName = packageName; + + string dir = Path.GetFullPath($"{Application.dataPath}/{PluginsRoot}/{fileName}.{Extends}"); + if (Directory.Exists(dir)) + { + return dir; + } + Directory.CreateDirectory(dir); + + string path = ""; + string content = ""; + + //------ Create project.properties ------ + content = ProjectPropertiesContent; + path = $"{dir}/{ProjectPropertiesName}"; + File.WriteAllText(path, content); + // ------ Create AndroidManifest.xml ------ + content = AndroidManifestContent.Replace("{0}", packageName); + path = $"{dir}/{AndroidManifestName}"; + File.WriteAllText(path, content); + + return dir; + } + + } +} \ No newline at end of file diff --git a/Editor/GuruManager/Helper/AndroidLibHelper.cs.meta b/Editor/GuruManager/Helper/AndroidLibHelper.cs.meta new file mode 100644 index 0000000..cf8d68c --- /dev/null +++ b/Editor/GuruManager/Helper/AndroidLibHelper.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ee3d47ab5d544373ae6a43fdd36d96fb +timeCreated: 1711761343 \ No newline at end of file diff --git a/Editor/GuruManager/Helper/AndroidManifestMod.cs b/Editor/GuruManager/Helper/AndroidManifestMod.cs index dd6aac1..1686955 100644 --- a/Editor/GuruManager/Helper/AndroidManifestMod.cs +++ b/Editor/GuruManager/Helper/AndroidManifestMod.cs @@ -67,7 +67,7 @@ namespace Guru.Editor { if (e != null) { - if (e.HasAttribute("android:name")) + if (e.HasAttribute("name", NamespaceAndroid)) { if (e.Attributes["android:name"].Value == ValOptimizeInitialization) item1 = 1; if (e.Attributes["android:name"].Value == ValOptimizeAdLoading) item2 = 1; diff --git a/Editor/GuruManager/Helper/MainManifestDoc.cs b/Editor/GuruManager/Helper/MainManifestDoc.cs new file mode 100644 index 0000000..3a6177d --- /dev/null +++ b/Editor/GuruManager/Helper/MainManifestDoc.cs @@ -0,0 +1,257 @@ + + + +namespace Guru.Editor +{ + using System.Xml; + using System.IO; + using UnityEngine; + using System.Collections.Generic; + + + /// + /// Android 配置修改器 + /// + public class MainManifestDoc + { + private const string TargetPath = "Plugins/Android/AndroidManifest.xml"; + private const string XmlnsAndroid = "xmlns:android"; + private const string NamespaceAndroid = "http://schemas.android.com/apk/res/android"; + private const string XmlnsTools= "xmlns:tools"; + private const string NamespaceTools = "http://schemas.android.com/tools"; + + + + private XmlDocument _doc; + public XmlDocument Doc => _doc; + + private string _docPath; + private bool _isReady = false; + + private XmlElement _manifestNode; + private XmlElement _applicationNode; + private XmlNodeList _metadataList; + private XmlNodeList _permissionList; + + + #region Initiallize + + /// + /// 加载文件 + /// + /// + /// + public static MainManifestDoc Load(string docPath = "") + { + if (string.IsNullOrEmpty(docPath)) + { + docPath = Path.GetFullPath(Path.Combine(Application.dataPath, TargetPath)); + } + + if (!File.Exists(docPath)) + { + Debug.LogError($"--- File not found: {docPath}"); + return null; + } + + var mod = new MainManifestDoc(); + mod.ReadFromPath(docPath); + return mod; + } + + public static MainManifestDoc Read(string xmlStr, string docPath = "") + { + var mod = new MainManifestDoc(); + mod.ReadFromXml(xmlStr, docPath); + return mod; + } + + + /// + /// 从文件路径读取 + /// + /// + public void ReadFromPath(string docPath) + { + _isReady = false; + if (File.Exists(docPath)) + { + _docPath = docPath; + var xmlStr = File.ReadAllText(docPath); + ReadFromXml(xmlStr); + } + } + + + public void ReadFromXml(string xmlStr, string docPath = "") + { + _doc = new XmlDocument(); + _doc.LoadXml(xmlStr); + _docPath = docPath; + Init(); + } + + + /// + /// Initializes the Doc + /// + private void Init() + { + // --- Root Nodes --- + _manifestNode = _doc.SelectSingleNode("manifest") as XmlElement; + _applicationNode = _doc.SelectSingleNode("manifest/application") as XmlElement; + // --- Metadatas --- + _metadataList = _applicationNode.SelectNodes("meta-data"); + // --- Permissions --- + _permissionList = _applicationNode.SelectNodes("uses-permission"); + + AddXmlnsAndroid(); + AddXmlnsTools(); + _isReady = true; + } + + /// + /// Save Doc + /// + public void Save(string docPath = "") + { + if (_isReady) + { + if(string.IsNullOrEmpty(docPath)) docPath = _docPath; + if (!string.IsNullOrEmpty(docPath)) + { + var dir = Directory.GetParent(docPath); + if(!dir.Exists) dir.Create(); + _doc.Save(_docPath); + + } + + } + } + + #endregion + + #region Node Opreation + + + public static bool AddAttribute(XmlElement node, string key, string value) + { + if (node != null) + { + if (node.HasAttribute(key)) + { + node.Attributes[key].Value = value; + } + else + { + node.SetAttribute(key, value); + } + return true; + } + return false; + } + + + + #endregion + + + #region API + + public bool AddXmlnsAndroid() + { + return AddAttribute(_manifestNode, XmlnsAndroid, NamespaceAndroid); + } + + public bool AddXmlnsTools() + { + return AddAttribute(_manifestNode, XmlnsTools, NamespaceTools); + } + + /// + /// Add Replace Item + /// + /// + public void AddReplaceItem(string item) + { + if (_manifestNode != null) + { + List items = new List(5); + if (_manifestNode.HasAttribute("replace", NamespaceTools)) + { + var arr = _manifestNode.GetAttribute("replace",NamespaceTools).Split(','); + if(arr != null && arr.Length > 0) + { + items.AddRange(arr); + } + } + + if (!items.Contains(item)) items.Add(item); + + _manifestNode.SetAttribute("replace", NamespaceTools, string.Join(",", items)); + } + } + + + /// + /// Set metadata + /// + /// + /// + /// + /// + public void SetMetadata(string key, string value, string valueName = "value", string keyName = "name") + { + _metadataList = _applicationNode?.SelectNodes("meta-data") ?? null; + + XmlElement item = null; + if (_metadataList != null) + { + foreach (XmlElement e in _metadataList) + { + // var nm = e.GetAttribute("name", NamespaceAndroid); + if (e.GetAttribute(keyName, NamespaceAndroid) is string k && k == key) + { + item = e; + break; + } + } + } + + if (item == null) + { + item = _doc.CreateElement("meta-data"); + _applicationNode?.AppendChild(item); + } + + item.SetAttribute(keyName, NamespaceAndroid, key); + item.SetAttribute(valueName, NamespaceAndroid, value); + } + + + #endregion + + + + #region Output + + + public override string ToString() + { + if (_doc != null) return _doc.InnerXml; + return this.ToString(); + } + + + #endregion + + + + + + + + + + } +} \ No newline at end of file diff --git a/Editor/GuruManager/Helper/MainManifestDoc.cs.meta b/Editor/GuruManager/Helper/MainManifestDoc.cs.meta new file mode 100644 index 0000000..61eed76 --- /dev/null +++ b/Editor/GuruManager/Helper/MainManifestDoc.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 89a1c7f77fcf4982adbbaf6dc61bd62d +timeCreated: 1711505949 \ No newline at end of file diff --git a/Editor/GuruManager/Helper/PushIconHelper.cs b/Editor/GuruManager/Helper/PushIconHelper.cs new file mode 100644 index 0000000..4800772 --- /dev/null +++ b/Editor/GuruManager/Helper/PushIconHelper.cs @@ -0,0 +1,148 @@ + +using System.Net; +using UnityEditor; + +namespace Guru.Editor +{ + using UnityEngine; + using System.IO; + + public class PushIconHelper + { + public static readonly int targetWidth = 96; // 目标宽度 + public static readonly int targetHeight = 96; + private static readonly string LibName = "SDKRes"; + private static readonly string PackageName = "com.guru.unity.res"; + private static readonly string IconName = "ic_notification.png"; + + private static readonly string ColorContent = + "\n\n #{0}\n"; + private static readonly string ValueContent = + "\n\n {0}\n"; + private static readonly string[] iconNames = new string[] + { + "drawable-mdpi", + "drawable-hdpi", + "drawable-xhdpi", + "drawable-xxhdpi", + "drawable-xxxhdpi" + }; + + + private static string FcmChannelId = "fcm_default_channel"; + + /// + /// 设置推送图标 + /// + /// + /// + public static bool SetPushIconAssets(Texture2D source, Color color = default(Color)) + { + if (source == null) + { + Debug.LogError($"=== No Texture2D found ==="); + return false; + } + return DeployAllIcons(source, color); + } + + private static Texture2D ResizeTexture(Texture2D source, int newWidth, int newHeight) + { + MakeTextureReadable(source); + + Texture2D result = new Texture2D(newWidth, newHeight); + Color[] newColors = new Color[newWidth * newHeight]; + + for (int y = 0; y < newHeight; y++) + { + for (int x = 0; x < newWidth; x++) + { + // 应用一些缩放逻辑来获取新的颜色值 + newColors[x + y * newWidth] = source.GetPixelBilinear((float)x / newWidth * source.width, (float)y / newHeight * source.height); + } + } + + result.SetPixels(newColors); + result.Apply(); + return result; + } + + private static void MakeTextureReadable(Texture2D source) + { + if (source.isReadable) return; + + var path = AssetDatabase.GetAssetPath(source); + TextureImporter ti = (TextureImporter)AssetImporter.GetAtPath(path); + if (!ti.isReadable) + { + ti.isReadable = true; + ti.SaveAndReimport(); + } + } + + + private static string ColorToHex(Color color) + { + return string.Format("{0:X2}{1:X2}{2:X2}", (int)(color.r * 255), (int)(color.g * 255), (int)(color.b * 255)); + } + + + private static bool DeployAllIcons(Texture2D source, Color color) + { + var dir = AndroidLibHelper.CreateLibRoot(PackageName, LibName); + string path = ""; + string content = ""; + + var result = ResizeTexture(source, targetWidth, targetHeight); + byte[] bytes = result.EncodeToPNG(); + + + var resPath = $"{dir}/res"; + if (!Directory.Exists(resPath)) + { + Directory.CreateDirectory(resPath); + } + + File.WriteAllBytes($"{resPath}/{IconName}", bytes); // Base Icon; + // ----- Build all Icons ------ + foreach (var iconName in iconNames) + { + var iconPath = $"{resPath}/{iconName}"; + if (!Directory.Exists(iconPath)) + { + Directory.CreateDirectory(iconPath); + } + File.WriteAllBytes($"{iconPath}/{IconName}", bytes); + } + + var valuesPath = $"{resPath}/values"; + if (!Directory.Exists(valuesPath)) Directory.CreateDirectory(valuesPath); + + // ----- Build colors.xml ------ + path = $"{valuesPath}/colors.xml"; + content = ColorContent.Replace("{0}", ColorToHex(color)); + File.WriteAllText(path, content); + // ----- Build strings.xml ------ + path = $"{valuesPath}/strings.xml"; + content = ValueContent.Replace("{0}", FcmChannelId); + File.WriteAllText(path, content); + + // ----- Inject AndroidManifest.xml ------ + var doc = MainManifestDoc.Load(); + if (doc != null) + { + doc.SetMetadata("com.google.firebase.messaging.default_notification_icon", "@drawable/ic_notification", valueName:"resource"); + doc.SetMetadata("com.google.firebase.messaging.default_notification_color", "@color/colorAccent", valueName:"resource"); + doc.SetMetadata("com.google.firebase.messaging.default_notification_channel_id", "@string/default_notification_channel_id"); + doc.Save(); + Debug.Log(" --- Push Icon Build Success --- "); + return true; + } + + Debug.LogError("AndroidManifest.xml not found ..."); + return false; + } + + + } +} \ No newline at end of file diff --git a/Editor/GuruManager/Helper/PushIconHelper.cs.meta b/Editor/GuruManager/Helper/PushIconHelper.cs.meta new file mode 100644 index 0000000..86c1846 --- /dev/null +++ b/Editor/GuruManager/Helper/PushIconHelper.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 39d65f42b9694641b0c3509262aca1d4 +timeCreated: 1711724404 \ No newline at end of file diff --git a/Editor/GuruManager/Manager/GuruSDKManager.cs b/Editor/GuruManager/Manager/GuruSDKManager.cs index bcbd3ce..848edd6 100644 --- a/Editor/GuruManager/Manager/GuruSDKManager.cs +++ b/Editor/GuruManager/Manager/GuruSDKManager.cs @@ -394,6 +394,11 @@ namespace Guru.Editor { GUI_OnConfigEnabled(); } + + GUILayout.Space(10); + + // Push + GUI_PushIconMaker(); } @@ -460,7 +465,7 @@ namespace Guru.Editor } GUILayout.Space(4); - + } @@ -1000,6 +1005,60 @@ namespace Guru.Editor } } + #endregion + + + #region Push Icon Maker + + private bool _showSegmentPush = false; + private Texture2D _pushIconTexture; + private Color _pushIconColor = Color.white; + + private void GUI_PushIconMaker() + { + float btnH = 24; + + + _showSegmentPush = EditorGUILayout.Foldout(_showSegmentPush, "[ Push Icon ]"); + + // EditorGUILayout.LabelField("[ Push Icon ]", StyleItemTitle); + + if (_showSegmentPush) + { + EditorGUI.indentLevel++; + EditorGUILayout.BeginHorizontal("box"); + EditorGUILayout.LabelField("Icon ( 96x96 PNG )"); + _pushIconTexture = EditorGUILayout.ObjectField( _pushIconTexture, typeof(Texture2D), false) as Texture2D; + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.BeginHorizontal("box"); + EditorGUILayout.LabelField("Icon Color"); + _pushIconColor = EditorGUILayout.ColorField(_pushIconColor); + EditorGUILayout.EndHorizontal(); + + if (null != _pushIconTexture) + { + GUI_Button("CREATE PUSH ASSETS", () => + { + if (PushIconHelper.SetPushIconAssets(_pushIconTexture, _pushIconColor)) + { + EditorUtility.DisplayDialog("Set Push Icon", "Push Icon assets created success!", "OK"); + } + else + { + EditorUtility.DisplayDialog("Set Push Icon", "Push Icon assets created failed!", "Well..."); + } + }, null, GUILayout.Height(btnH)); + } + EditorGUI.indentLevel--; + } + + + } + + + + #endregion } diff --git a/Editor/GuruSDK.Editor.asmdef b/Editor/GuruSDK.Editor.asmdef index 0b68aad..c5f0b5d 100644 --- a/Editor/GuruSDK.Editor.asmdef +++ b/Editor/GuruSDK.Editor.asmdef @@ -6,7 +6,8 @@ "GuruSDK", "Guru.LitJson", "Guru.Runtime", - "MaxSdk.Scripts.IntegrationManager.Editor" + "MaxSdk.Scripts.IntegrationManager.Editor", + "Guru.Editor" ], "includePlatforms": [ "Editor" diff --git a/Runtime/Code/SDK/GuruSDK.cs b/Runtime/Code/SDK/GuruSDK.cs index 5b4f7c4..9ecf5f3 100644 --- a/Runtime/Code/SDK/GuruSDK.cs +++ b/Runtime/Code/SDK/GuruSDK.cs @@ -8,7 +8,7 @@ namespace Guru public partial class GuruSDK: MonoBehaviour { - public const string Version = "1.0.9"; + public const string Version = "1.0.10"; public const string Tag = "[Guru]"; public const string ServicesConfigKey = "guru_services"; diff --git a/package.json b/package.json index ae2b33f..8fb1097 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "com.guru.unity.sdk", "displayName": "Guru SDK", - "version": "1.0.9", + "version": "1.0.10", "description": "Guru SDK for unity project", "unity": "2020.3", "author":{