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":{