/// <summary> /// 设置私有数据 /// </summary> /// <param name="plist"></param> /// <param name="privacySensiticeDataList"></param> private static void SetPrivacySensiticeData(PlistDocument plist, List <XcodeProjectSetting.PrivacySensiticeData> privacySensiticeDataList) { PlistElementDict rootDict = plist.root; int count = privacySensiticeDataList.Count; for (int i = 0; i < count; i++) { XcodeProjectSetting.PrivacySensiticeData data = privacySensiticeDataList[i]; switch (data.type) { case XcodeProjectSetting.NValueType.String: rootDict.SetString(data.key, data.value); break; case XcodeProjectSetting.NValueType.Int: rootDict.SetInteger(data.key, int.Parse(data.value)); break; case XcodeProjectSetting.NValueType.Bool: rootDict.SetBoolean(data.key, bool.Parse(data.value)); break; default: rootDict.SetString(data.key, data.value); break; } } }
private static void AddConfig(PlistElementDict dic, Dictionary <string, object> values) { foreach (var pair in values) { if (pair.Value is string) { dic.SetString(pair.Key, (string)pair.Value); } else if (pair.Value is int) { dic.SetInteger(pair.Key, (int)pair.Value); } else if (pair.Value is bool) { dic.SetBoolean(pair.Key, (bool)pair.Value); } else if (pair.Value is Dictionary <string, object> ) { var parent = dic.CreateDict(pair.Key); AddConfig(parent, (Dictionary <string, object>)pair.Value); } else if (pair.Value is List <object> ) { var parent = dic.CreateArray(pair.Key); AddConfig(parent, (List <object>)pair.Value); } } }
public static void ApplyDataBinding(string pbxmod, string rootpath, PBXProject proj, string target) { DataBinding dataBinding = new DataBinding(pbxmod); ApplyData(dataBinding.libs, (valueOne, valueTwo) => { proj.AddFileToBuild(target, proj.AddFile("usr/lib/" + valueOne, "Frameworks/" + valueOne, PBXSourceTree.Sdk)); }); ApplyData(dataBinding.frameworks, (valueOne, valueTwo) => { proj.AddFrameworkToProject(target, valueOne, false); }); ApplyData(dataBinding.plist, (valueOne, valueTwo) => { //修改plist string plistPath = rootpath + "/Info.plist"; PlistDocument plist = new PlistDocument(); plist.ReadFromString(File.ReadAllText(plistPath)); PlistElementDict rootDict = plist.root; if (valueTwo == "True" || valueTwo == "False") { rootDict.SetBoolean(valueOne, bool.Parse(valueTwo)); plist.WriteToFile(plistPath); return; } if (ChargeIsNumber(valueTwo)) { rootDict.SetInteger(valueOne, int.Parse(valueTwo)); plist.WriteToFile(plistPath); return; } // 语音听写需要开启的权限 rootDict.SetString(valueOne, valueTwo); //保存plist plist.WriteToFile(plistPath); }); Debug.Log("修改PLIST成功!"); ApplyData(dataBinding.bitcode, (valueOne, ValueTwo) => { proj.SetBuildProperty(target, "ENABLE_BITCODE", valueOne); }); Debug.Log("修改ENABLE_BITCODE成功!"); ApplyData(dataBinding.code_sign_identity, (valueOne, ValueTwo) => { proj.SetBuildProperty(target, "CODE_SIGN_IDENTITY", valueOne + ":" + ValueTwo); }); Debug.Log("修改CODE_SIGN_IDENTITY成功!"); ApplyData(dataBinding.provisioning_profile_specifier, (valueOne, ValueTwo) => { proj.SetBuildProperty(target, "PROVISIONING_PROFILE_SPECIFIER", valueOne); }); Debug.Log("修改PROVISIONING_PROFILE_SPECIFIER成功!"); ApplyData(dataBinding.framework_search_paths, (valueOne, ValueTwo) => { proj.SetBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", valueOne); }); Debug.Log("修改FRAMEWORK_SEARCH_PATHS成功!"); //设置框架路径时,无法实现在Xcode中依次添加各个路径,添加一个可以,添加第二个覆盖第一个 ApplyData(dataBinding.other_ldflags, (valueOne, ValueTwo) => { proj.SetBuildProperty(target, "OTHER_LDFLAGS", valueOne); }); Debug.Log("修改OTHER_LDFLAGS成功!"); }
public static void CreatePlist(TextureInfo[] texturesInfo, Rect[] rects, string plistOutPath) { var plist = new PlistDocument(); plist.Create(); PlistElementDict rootDict = plist.root; PlistElementArray plistArray = rootDict.CreateArray("texturesInfo"); for (int i = 0; i < texturesInfo.Length; i++) { PlistElementDict dict = plistArray.AddDict(); dict.SetString("name", texturesInfo[i].name); dict.SetInteger("x", (int)texturesInfo[i].x); dict.SetInteger("y", (int)texturesInfo[i].y); dict.SetInteger("width", (int)texturesInfo[i].width); dict.SetInteger("height", (int)texturesInfo[i].height); } File.WriteAllText(plistOutPath, plist.WriteToString()); AssetDatabase.Refresh(); }
private void GenerateIOSAirshipConfig() { string plistPath = Path.Combine(Application.dataPath, "Plugins/iOS/AirshipConfig.plist"); if (File.Exists(plistPath)) { File.Delete(plistPath); } PlistDocument plist = new PlistDocument(); PlistElementDict rootDict = plist.root; if (!String.IsNullOrEmpty(ProductionAppKey) && !String.IsNullOrEmpty(ProductionAppSecret)) { rootDict.SetString("productionAppKey", ProductionAppKey); rootDict.SetString("productionAppSecret", ProductionAppSecret); rootDict.SetInteger("productionLogLevel", IOSLogLevel(ProductionLogLevel)); } if (!String.IsNullOrEmpty(DevelopmentAppKey) && !String.IsNullOrEmpty(DevelopmentAppSecret)) { rootDict.SetString("developmentAppKey", DevelopmentAppKey); rootDict.SetString("developmentAppSecret", DevelopmentAppSecret); rootDict.SetInteger("developmentLogLevel", IOSLogLevel(DevelopmentLogLevel)); } rootDict.SetBoolean("inProduction", InProduction); PlistElementDict customConfig = rootDict.CreateDict("customConfig"); customConfig.SetBoolean("notificationPresentationOptionAlert", NotificationPresentationOptionAlert); customConfig.SetBoolean("notificationPresentationOptionBadge", NotificationPresentationOptionBadge); customConfig.SetBoolean("notificationPresentationOptionSound", NotificationPresentationOptionSound); File.WriteAllText(plistPath, plist.WriteToString()); }
/// <summary> /// 更新内容到PList /// </summary> /// <param name="key"></param> /// <param name="value"></param> public void Update(string key, string value, XcodeInfoPListType infoType = XcodeInfoPListType.StringInfo, bool isAdd = true) { PlistElementDict root = _plist.root; if (isAdd) { switch (infoType) { case XcodeInfoPListType.BoolInfo: bool vb = bool.Parse(value); if (root[key] != null) { root[key] = new PlistElementBoolean(vb); } else if (isAdd) { root.SetBoolean(key, vb); } break; case XcodeInfoPListType.IntInfo: int vi = int.Parse(value); if (root[key] != null) { root[key] = new PlistElementInteger(vi); } else if (isAdd) { root.SetInteger(key, vi); } break; case XcodeInfoPListType.StringInfo: if (root[key] != null) { root[key] = new PlistElementString(value); } else { root.SetString(key, value); } break; } } else { root.values.Remove(key); } }
private void SetDataForKey(object key, object value, PlistElementDict elementDict) { if (value is int) { elementDict.SetInteger(key.ToString(), Convert.ToInt32(value)); } else if (value is bool) { elementDict.SetBoolean(key.ToString(), Convert.ToBoolean(value)); } else if (value is string) { elementDict.SetString(key.ToString(), value.ToString()); } else if (value is float) { elementDict.SetReal(key.ToString(), Convert.ToSingle(value)); } }
//设置plist private static void SetPlist(PBXProject proj, PlistElementDict node, Hashtable arg) { if (arg != null) { foreach (DictionaryEntry i in arg) { string key = i.Key.ToString(); object val = i.Value; var vType = i.Value.GetType(); if (vType == typeof(string)) { node.SetString(key, (string)val); } else if (vType == typeof(bool)) { node.SetBoolean(key, (bool)val); } else if (vType == typeof(double)) { int v = int.Parse(val.ToString()); node.SetInteger(key, v); } else if (vType == typeof(ArrayList)) { var t = node.CreateArray(key); var array = val as ArrayList; SetPlist(proj, t, array); } else if (vType == typeof(Hashtable)) { var t = node.CreateDict(key); var table = val as Hashtable; SetPlist(proj, t, table); } } } }
public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject) { XmlNode root; XmlNodeList nodes; XmlDocument xmlDoc; XmlTextReader reader; TextWriter mfWriter; if (target == BuildTarget.WSAPlayer) { XmlNamespaceManager namespaceManager = new XmlNamespaceManager(new NameTable()); namespaceManager.AddNamespace("x", xNameSpaceURI); namespaceManager.AddNamespace("uap", uapNameSpaceURI); namespaceManager.AddNamespace("m3", m3NameSpaceURI); // O - Checking configuration if (EngagementConfiguration.WINDOWS_CONNECTION_STRING == null) { Debug.LogError("Missing WINDOWS_CONNECTION_STRING in EngagementConfiguration"); return; } if (EditorUserBuildSettings.wsaSDK != WSASDK.UWP && EditorUserBuildSettings.wsaSDK != WSASDK.PhoneSDK81) { Debug.LogError("Only Phone8.1 and Universal10 SDKs are supported"); return; } Boolean isWP81 = (EditorUserBuildSettings.wsaSDK == WSASDK.UniversalSDK81 || EditorUserBuildSettings.wsaSDK == WSASDK.PhoneSDK81); string PackageManifest = getWP10Directory(pathToBuiltProject) + "/Package.appxmanifest"; updateAppXManifest(PackageManifest, namespaceManager, isWP81); // 2 - Patching App.Xaml.CS string appcspath = getWP10Directory(pathToBuiltProject); appcspath += "/App.xaml.cs"; string appcsString = System.IO.File.ReadAllText(appcspath); // 2-1 - Remove former patch appcsString = removeEngagementCode(appcsString); Regex rgx2 = new Regex("OnLaunched\\(.*\\)\\s*\\{(\\s*)", RegexOptions.IgnoreCase); Match match2 = rgx2.Match(appcsString); if (!match2.Success) { Debug.LogError("could not find OnLaunched in App.xaml.cs"); } // 2-2 Add initEngagement OnLaunched string r = "OnLaunched(LaunchActivatedEventArgs args)\n"; r += "\t\t{\n"; r += "\t\t\t// BEGIN_ENGAGEMENT\n"; r += "\t\t\tMicrosoft.Azure.Engagement.Unity.EngagementAgent.initEngagement(args);\n"; r += "\t\t\t// END_ENGAGEMENT\n"; appcsString = rgx2.Replace(appcsString, r); // 2-3 Add initEngagement OnActivated rgx2 = new Regex("OnActivated\\(.*\\)\\s*\\{", RegexOptions.IgnoreCase); match2 = rgx2.Match(appcsString); if (!match2.Success) { Debug.LogError("could not find OnActivated in App.xaml.cs"); } r = "OnActivated(IActivatedEventArgs args)\n"; r += "\t\t{\n"; r += "\t\t\t// BEGIN_ENGAGEMENT\n"; r += "\t\t\tMicrosoft.Azure.Engagement.Unity.EngagementAgent.initEngagementOnActivated(args);\n"; r += "\t\t\t// END_ENGAGEMENT\n"; appcsString = rgx2.Replace(appcsString, r); System.IO.File.WriteAllText(appcspath, appcsString); Debug.Log("Patching " + appcspath); string unzipResourcesDirectoryWP10 = getWP10Directory(pathToBuiltProject); string vsProjectWP10 = PlayerSettings.productName + ".csproj"; addResourcesToProject(unzipResourcesDirectoryWP10, vsProjectWP10); // 4 Patching MainPage.Xaml string mainpagexamlPath = getWP10Directory(pathToBuiltProject); mainpagexamlPath += "/MainPage.xaml"; Debug.Log("Patching " + mainpagexamlPath); reader = new XmlTextReader(mainpagexamlPath); reader.Namespaces = false; xmlDoc = new XmlDocument(); xmlDoc.Load(reader); reader.Close(); // 4-0 - Remove webview root = xmlDoc.DocumentElement; removeEngagementComments(root); // 4-1 - Create Grid as a placeholder for the webview XmlNode grid = root.SelectSingleNode("Grid"); if (grid == null) { grid = xmlDoc.CreateNode(XmlNodeType.Element, "Grid", root.NamespaceURI); grid.Attributes.Append(xmlDoc.CreateAttribute("x", "Name", xNameSpaceURI)).Value = "engagementGrid"; foreach (XmlNode c in root.ChildNodes) { grid.AppendChild(c); } root.AppendChild(grid); } else { XmlNode attr = grid.Attributes.GetNamedItem("x:Name"); if (attr == null) { grid.Attributes.Append(xmlDoc.CreateAttribute("x", "Name", xNameSpaceURI)).Value = "engagementGrid"; } } // 4-2 Adding the webview if (EngagementConfiguration.ENABLE_REACH == true) { XmlNode webviewNode = xmlDoc.CreateNode(XmlNodeType.Element, "WebView", root.NamespaceURI); webviewNode.Attributes.Append(xmlDoc.CreateAttribute("x", "Name", xNameSpaceURI)).Value = "engagement_notification_content"; webviewNode.Attributes.Append(xmlDoc.CreateAttribute("Visibility")).Value = "Collapsed"; webviewNode.Attributes.Append(xmlDoc.CreateAttribute("Height")).Value = "80"; webviewNode.Attributes.Append(xmlDoc.CreateAttribute("HorizontalAlignment")).Value = "Stretch"; webviewNode.Attributes.Append(xmlDoc.CreateAttribute("VerticalAlignment")).Value = "Top"; appendChildWithEngagementComment(xmlDoc, grid, webviewNode); webviewNode = xmlDoc.CreateNode(XmlNodeType.Element, "WebView", root.NamespaceURI); webviewNode.Attributes.Append(xmlDoc.CreateAttribute("x", "Name", xNameSpaceURI)).Value = "engagement_announcement_content"; webviewNode.Attributes.Append(xmlDoc.CreateAttribute("Visibility")).Value = "Collapsed"; webviewNode.Attributes.Append(xmlDoc.CreateAttribute("HorizontalAlignment")).Value = "Stretch"; webviewNode.Attributes.Append(xmlDoc.CreateAttribute("VerticalAlignment")).Value = "Stretch"; grid.AppendChild(webviewNode); appendChildWithEngagementComment(xmlDoc, grid, webviewNode); } // 4-3 Write page mfWriter = new StreamWriter(mainpagexamlPath); xmlDoc.Save(mfWriter); mfWriter.Close(); } else if (target == BuildTarget.iOS) { #if ENABLE_IOS_SUPPORT string bundleId = PlayerSettings.bundleIdentifier; // 0 - Configuration Check string connectionString = EngagementConfiguration.IOS_CONNECTION_STRING; if (string.IsNullOrEmpty(connectionString)) { throw new ArgumentException("IOS_CONNECTION_STRING cannot be null when building on iOS project"); } string projectFile = PBXProject.GetPBXProjectPath(pathToBuiltProject); // 1 - Update Project PBXProject pbx = new PBXProject(); pbx.ReadFromFile(projectFile); string targetUID = pbx.TargetGuidByName(PBXProject.GetUnityTargetName() /*"Unity-iPhone"*/); string CTFramework = "CoreTelephony.framework"; Debug.Log("Adding " + CTFramework + " to XCode Project"); pbx.AddFrameworkToProject(targetUID, CTFramework, true); const string disableAll = "ENGAGEMENT_UNITY=1,ENGAGEMENT_DISABLE_IDFA=1"; const string enableIDFA = "ENGAGEMENT_UNITY=1,ENGAGEMENT_DISABLE_IDFA=1"; const string disableIDFA = "ENGAGEMENT_UNITY=1"; if (EngagementConfiguration.IOS_DISABLE_IDFA == true) { pbx.UpdateBuildProperty(targetUID, "GCC_PREPROCESSOR_DEFINITIONS", enableIDFA.Split(','), disableAll.Split(',')); } else { pbx.UpdateBuildProperty(targetUID, "GCC_PREPROCESSOR_DEFINITIONS", disableIDFA.Split(','), disableAll.Split(',')); } string[] paths = new string[] { EngagementConfiguration.IOS_REACH_ICON, "EngagementPlugin/iOS/res/close.png" }; // 3 - Add files to project foreach (string path in paths) { if (string.IsNullOrEmpty(path)) { continue; } string fullpath = Application.dataPath + "/" + path; string file = Path.GetFileName(fullpath); string fileUID = pbx.AddFile(file, file); Debug.Log("Adding " + file + " to XCode Project"); pbx.AddFileToBuild(targetUID, fileUID); string xcodePath = pathToBuiltProject + "/" + file; if (File.Exists(xcodePath) == false) { Debug.Log("Copy from " + fullpath + " to " + xcodePath); File.Copy(fullpath, xcodePath); } } pbx.WriteToFile(projectFile); // 4 - Modify .PLIST string plistPath = pathToBuiltProject + "/Info.plist"; PlistDocument plist = new PlistDocument(); plist.ReadFromString(File.ReadAllText(plistPath)); // Get root PlistElementDict rootDict = plist.root; if (EngagementConfiguration.ENABLE_REACH == true) { PlistElementArray UIBackgroundModes = rootDict.CreateArray("UIBackgroundModes"); UIBackgroundModes.AddString("remote-notification"); PlistElementArray CFBundleURLTypes = rootDict.CreateArray("CFBundleURLTypes"); PlistElementDict dict = CFBundleURLTypes.AddDict(); dict.SetString("CFBundleTypeRole", "None"); dict.SetString("CFBundleURLName", bundleId + ".redirect"); PlistElementArray schemes = dict.CreateArray("CFBundleURLSchemes"); schemes.AddString(EngagementConfiguration.ACTION_URL_SCHEME); } // Required on iOS8 string reportingDesc = EngagementConfiguration.LOCATION_REPORTING_DESCRIPTION; if (reportingDesc == null) { reportingDesc = PlayerSettings.productName + " reports your location for analytics purposes"; } if (EngagementConfiguration.LOCATION_REPORTING_MODE == LocationReportingMode.BACKGROUND) { rootDict.SetString("NSLocationAlwaysUsageDescription", reportingDesc); } else if (EngagementConfiguration.LOCATION_REPORTING_MODE == LocationReportingMode.FOREGROUND) { rootDict.SetString("NSLocationWhenInUseUsageDescription", reportingDesc); } string icon = EngagementConfiguration.IOS_REACH_ICON; PlistElementDict engagementDict = rootDict.CreateDict("Engagement"); engagementDict.SetString("IOS_CONNECTION_STRING", EngagementConfiguration.IOS_CONNECTION_STRING); engagementDict.SetString("IOS_REACH_ICON", icon); engagementDict.SetBoolean("ENABLE_NATIVE_LOG", EngagementConfiguration.ENABLE_NATIVE_LOG); engagementDict.SetBoolean("ENABLE_PLUGIN_LOG", EngagementConfiguration.ENABLE_PLUGIN_LOG); engagementDict.SetBoolean("ENABLE_REACH", EngagementConfiguration.ENABLE_REACH); engagementDict.SetInteger("LOCATION_REPORTING_MODE", Convert.ToInt32(EngagementConfiguration.LOCATION_REPORTING_MODE)); engagementDict.SetInteger("LOCATION_REPORTING_TYPE", Convert.ToInt32(EngagementConfiguration.LOCATION_REPORTING_TYPE)); // Write to file File.WriteAllText(plistPath, plist.WriteToString()); #else Debug.LogError("You need to active ENABLE_IOS_SUPPORT to build for IOS"); #endif } if (target == BuildTarget.Android) { string bundleId = PlayerSettings.bundleIdentifier; string productName = PlayerSettings.productName; int chk = generateAndroidChecksum(); // 0 - Configuration check string connectionString = EngagementConfiguration.ANDROID_CONNECTION_STRING; if (string.IsNullOrEmpty(connectionString)) { throw new ArgumentException("ANDROID_CONNECTION_STRING cannot be null when building on Android project"); } if (EngagementConfiguration.ENABLE_REACH == true) { string projectNumber = EngagementConfiguration.ANDROID_GOOGLE_PROJECT_NUMBER; if (string.IsNullOrEmpty(projectNumber)) { throw new ArgumentException("ANDROID_GOOGLE_PROJECT_NUMBER cannot be null when Reach is enabled"); } } string manifestPath = pathToBuiltProject + "/" + productName + "/AndroidManifest.xml"; string androidPath = Application.dataPath + "/Plugins/Android"; string mfFilepath = androidPath + "/AndroidManifest.xml"; XmlNamespaceManager namespaceManager = new XmlNamespaceManager(new NameTable()); namespaceManager.AddNamespace("android", EngagementPostBuild.androidNS); // Test Export vs Build if (File.Exists(manifestPath) == false) { // Check that Manifest exists if (File.Exists(mfFilepath) == false) { Debug.LogError("Missing AndroidManifest.xml in Plugins/Android : execute 'File/Engagement/Generate Android Manifest'"); return; } // Check that it contains Engagement tags xmlDoc = new XmlDocument(); xmlDoc.XmlResolver = null; // Create the reader. reader = new XmlTextReader(mfFilepath); xmlDoc.Load(reader); reader.Close(); root = xmlDoc.DocumentElement; nodes = root.SelectNodes("//*[@tag='" + tagName + "']", namespaceManager); if (nodes.Count == 0) { Debug.LogError("Android manifest in Plugins/Android does not contain Engagement extensions : execute 'File/Engagement/Generate Android Manifest'"); } // Checking the version XmlNode versionNode = root.SelectSingleNode("/manifest/application/meta-data[@android:name='engagement:unity:version']", namespaceManager); if (versionNode != null) { string ver = versionNode.Attributes["android:value"].Value; if (ver != EngagementAgent.PLUGIN_VERSION.ToString()) { versionNode = null; } } if (versionNode == null) { Debug.LogError("EngagementPlugin has been updated : you need to execute 'File/Engagement/Generate Android Manifest' to update your application Manifest first"); } // Checking the checksum XmlNode chkNode = root.SelectSingleNode("/manifest/application/meta-data[@android:name='engagement:unity:checksum']", namespaceManager); if (chkNode != null) { string mfchk = chkNode.Attributes["android:value"].Value; if (mfchk != chk.ToString()) { chkNode = null; } } if (chkNode == null) { Debug.LogError("Configuration file has changed : you need to execute 'File/Engagement/Generate Android Manifest' to update your application Manifest"); } // Manifest already processed : nothing to do return; } Directory.CreateDirectory(androidPath); xmlDoc = new XmlDocument(); xmlDoc.XmlResolver = null; reader = new XmlTextReader(manifestPath); xmlDoc.Load(reader); reader.Close(); root = xmlDoc.DocumentElement; // Delete all the former tags nodes = root.SelectNodes("//*[@tag='" + tagName + "']", namespaceManager); foreach (XmlNode node in nodes) { node.ParentNode.RemoveChild(node); } XmlNode manifestNode = root.SelectSingleNode("/manifest", namespaceManager); XmlNode applicationNode = root.SelectSingleNode("/manifest/application", namespaceManager); XmlNode activityNode = root.SelectSingleNode("/manifest/application/activity[@android:label='@string/app_name']", namespaceManager); string activity = EngagementConfiguration.ANDROID_UNITY3D_ACTIVITY; if (activity == null || activity == "") { activity = "com.unity3d.player.UnityPlayerActivity"; } // Already in the Unity Default Manifest // EngagementPostBuild.addUsesPermission(xmlDoc,manifestNode,namespaceManager,"android.permission.INTERNET"); EngagementPostBuild.addUsesPermission(xmlDoc, manifestNode, namespaceManager, "android.permission.ACCESS_NETWORK_STATE"); EngagementPostBuild.addMetaData(xmlDoc, applicationNode, namespaceManager, "engagement:log:test", XmlConvert.ToString(EngagementConfiguration.ENABLE_NATIVE_LOG)); EngagementPostBuild.addMetaData(xmlDoc, applicationNode, namespaceManager, "engagement:unity:version", EngagementAgent.PLUGIN_VERSION); EngagementPostBuild.addMetaData(xmlDoc, applicationNode, namespaceManager, "engagement:unity:checksum", chk.ToString()); XmlNode service = xmlDoc.CreateNode(XmlNodeType.Element, "service", null); service.Attributes.Append(xmlDoc.CreateAttribute("tag")).Value = tagName; service.Attributes.Append(xmlDoc.CreateAttribute("android", "exported", EngagementPostBuild.androidNS)).Value = "false"; service.Attributes.Append(xmlDoc.CreateAttribute("android", "label", EngagementPostBuild.androidNS)).Value = productName + "Service"; service.Attributes.Append(xmlDoc.CreateAttribute("android", "name", EngagementPostBuild.androidNS)).Value = "com.microsoft.azure.engagement.service.EngagementService"; service.Attributes.Append(xmlDoc.CreateAttribute("android", "process", EngagementPostBuild.androidNS)).Value = ":Engagement"; applicationNode.AppendChild(service); string targetAARPath = Application.dataPath + "/Plugins/Android/engagement_notification_icon.aar"; File.Delete(targetAARPath); File.Delete(targetAARPath + ".meta"); if (EngagementConfiguration.ENABLE_REACH == true) { EngagementPostBuild.addActivity(xmlDoc, applicationNode, namespaceManager, "EngagementWebAnnouncementActivity", "ANNOUNCEMENT", "Light", "text/html"); EngagementPostBuild.addActivity(xmlDoc, applicationNode, namespaceManager, "EngagementTextAnnouncementActivity", "ANNOUNCEMENT", "Light", "text/plain"); EngagementPostBuild.addActivity(xmlDoc, applicationNode, namespaceManager, "EngagementPollActivity", "POLL", "Light", null); EngagementPostBuild.addActivity(xmlDoc, applicationNode, namespaceManager, "EngagementLoadingActivity", "LOADING", "Dialog", null); const string reachActions = "android.intent.action.BOOT_COMPLETED," + "com.microsoft.azure.engagement.intent.action.AGENT_CREATED," + "com.microsoft.azure.engagement.intent.action.MESSAGE," + "com.microsoft.azure.engagement.reach.intent.action.ACTION_NOTIFICATION," + "com.microsoft.azure.engagement.reach.intent.action.EXIT_NOTIFICATION," + "com.microsoft.azure.engagement.reach.intent.action.DOWNLOAD_TIMEOUT"; EngagementPostBuild.addReceiver(xmlDoc, applicationNode, namespaceManager, "reach.EngagementReachReceiver", reachActions.Split(',')); const string downloadActions = "android.intent.action.DOWNLOAD_COMPLETE"; EngagementPostBuild.addReceiver(xmlDoc, applicationNode, namespaceManager, "reach.EngagementReachDownloadReceiver", downloadActions.Split(',')); // Add GCM Support if (string.IsNullOrEmpty(EngagementConfiguration.ANDROID_GOOGLE_PROJECT_NUMBER) == false) { EngagementPostBuild.addMetaData(xmlDoc, applicationNode, namespaceManager, "engagement:gcm:sender", EngagementConfiguration.ANDROID_GOOGLE_PROJECT_NUMBER + "\\n"); const string gcmActions = "com.microsoft.azure.engagement.intent.action.APPID_GOT"; EngagementPostBuild.addReceiver(xmlDoc, applicationNode, namespaceManager, "gcm.EngagementGCMEnabler", gcmActions.Split(',')); XmlNode receiver = xmlDoc.CreateNode(XmlNodeType.Element, "receiver", null); receiver.Attributes.Append(xmlDoc.CreateAttribute("tag")).Value = tagName; receiver.Attributes.Append(xmlDoc.CreateAttribute("android", "name", EngagementPostBuild.androidNS)).Value = "com.microsoft.azure.engagement.gcm.EngagementGCMReceiver"; receiver.Attributes.Append(xmlDoc.CreateAttribute("android", "permission", EngagementPostBuild.androidNS)).Value = "com.google.android.c2dm.permission.SEND"; XmlNode intentReceiver = xmlDoc.CreateNode(XmlNodeType.Element, "intent-filter", null); receiver.AppendChild(intentReceiver); intentReceiver.AppendChild(xmlDoc.CreateNode(XmlNodeType.Element, "action", null)) .Attributes.Append(xmlDoc.CreateAttribute("android", "name", EngagementPostBuild.androidNS)).Value = "com.google.android.c2dm.intent.REGISTRATION"; intentReceiver.AppendChild(xmlDoc.CreateNode(XmlNodeType.Element, "action", null)) .Attributes.Append(xmlDoc.CreateAttribute("android", "name", EngagementPostBuild.androidNS)).Value = "com.google.android.c2dm.intent.RECEIVE"; intentReceiver.AppendChild(xmlDoc.CreateNode(XmlNodeType.Element, "category", null)) .Attributes.Append(xmlDoc.CreateAttribute("android", "name", EngagementPostBuild.androidNS)).Value = bundleId; applicationNode.AppendChild(receiver); string permissionPackage = bundleId + ".permission.C2D_MESSAGE"; EngagementPostBuild.addUsesPermission(xmlDoc, manifestNode, namespaceManager, permissionPackage); XmlNode permission = xmlDoc.CreateNode(XmlNodeType.Element, "permission", null); permission.Attributes.Append(xmlDoc.CreateAttribute("tag")).Value = tagName; permission.Attributes.Append(xmlDoc.CreateAttribute("android", "name", EngagementPostBuild.androidNS)).Value = permissionPackage; permission.Attributes.Append(xmlDoc.CreateAttribute("android", "protectionLevel", EngagementPostBuild.androidNS)).Value = "signature"; manifestNode.AppendChild(permission); } const string datapushActions = "com.microsoft.azure.engagement.reach.intent.action.DATA_PUSH"; EngagementPostBuild.addReceiver(xmlDoc, applicationNode, namespaceManager, "shared.EngagementDataPushReceiver", datapushActions.Split(',')); EngagementPostBuild.addUsesPermission(xmlDoc, manifestNode, namespaceManager, "android.permission.WRITE_EXTERNAL_STORAGE"); EngagementPostBuild.addUsesPermission(xmlDoc, manifestNode, namespaceManager, "android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"); EngagementPostBuild.addUsesPermission(xmlDoc, manifestNode, namespaceManager, "android.permission.VIBRATE"); EngagementPostBuild.addUsesPermission(xmlDoc, manifestNode, namespaceManager, "com.google.android.c2dm.permission.RECEIVE"); string icon = "app_icon"; // using Application icon as default if (string.IsNullOrEmpty(EngagementConfiguration.ANDROID_REACH_ICON) == false) { // The only way to add resources to the APK is through a AAR library : let just create one with the icon icon = "engagement_notification_icon"; string srcAARPath = Application.dataPath + "/EngagementPlugin/Editor/engagement_notification_icon.zip"; string iconPath = Application.dataPath + "/" + EngagementConfiguration.ANDROID_REACH_ICON; File.Copy(srcAARPath, targetAARPath, true); ZipFile zip = ZipFile.Read(targetAARPath); zip.AddFile(iconPath).FileName = "res/drawable/" + icon + ".png"; zip.Save(); } EngagementPostBuild.addMetaData(xmlDoc, applicationNode, namespaceManager, "engagement:reach:notification:icon", icon); XmlNode catcherActivity = xmlDoc.CreateNode(XmlNodeType.Element, "activity", null); catcherActivity.Attributes.Append(xmlDoc.CreateAttribute("tag")).Value = "Engagement"; catcherActivity.Attributes.Append(xmlDoc.CreateAttribute("android", "label", EngagementPostBuild.androidNS)).Value = "@string/app_name"; catcherActivity.Attributes.Append(xmlDoc.CreateAttribute("android", "name", EngagementPostBuild.androidNS)).Value = "com.microsoft.azure.engagement.unity.IntentCatcherActivity"; XmlNode intent = xmlDoc.CreateNode(XmlNodeType.Element, "intent-filter", null); intent.Attributes.Append(xmlDoc.CreateAttribute("tag")).Value = tagName; intent.AppendChild(xmlDoc.CreateNode(XmlNodeType.Element, "action", null)) .Attributes.Append(xmlDoc.CreateAttribute("android", "name", EngagementPostBuild.androidNS)).Value = "android.intent.action.VIEW"; intent.AppendChild(xmlDoc.CreateNode(XmlNodeType.Element, "category", null)) .Attributes.Append(xmlDoc.CreateAttribute("android", "name", EngagementPostBuild.androidNS)).Value = "android.intent.category.DEFAULT"; intent.AppendChild(xmlDoc.CreateNode(XmlNodeType.Element, "category", null)) .Attributes.Append(xmlDoc.CreateAttribute("android", "name", EngagementPostBuild.androidNS)).Value = "android.intent.category.BROWSABLE"; intent.AppendChild(xmlDoc.CreateNode(XmlNodeType.Element, "data", null)) .Attributes.Append(xmlDoc.CreateAttribute("android", "scheme", EngagementPostBuild.androidNS)).Value = EngagementConfiguration.ACTION_URL_SCHEME; catcherActivity.AppendChild(intent); applicationNode.AppendChild(catcherActivity); EngagementPostBuild.addMetaData(xmlDoc, applicationNode, namespaceManager, "engagement:unity:activityname", activity); } if (EngagementConfiguration.LOCATION_REPORTING_MODE == LocationReportingMode.BACKGROUND) { string bootReceiverActions = "android.intent.action.BOOT_COMPLETED"; EngagementPostBuild.addReceiver(xmlDoc, applicationNode, namespaceManager, "EngagementLocationBootReceiver", bootReceiverActions.Split(',')); } if (EngagementConfiguration.LOCATION_REPORTING_TYPE == LocationReportingType.LAZY || EngagementConfiguration.LOCATION_REPORTING_TYPE == LocationReportingType.REALTIME) { EngagementPostBuild.addUsesPermission(xmlDoc, manifestNode, namespaceManager, "android.permission.ACCESS_COARSE_LOCATION"); } else if (EngagementConfiguration.LOCATION_REPORTING_TYPE == LocationReportingType.FINEREALTIME) { EngagementPostBuild.addUsesPermission(xmlDoc, manifestNode, namespaceManager, "android.permission.ACCESS_FINE_LOCATION"); } if (EngagementConfiguration.LOCATION_REPORTING_MODE == LocationReportingMode.BACKGROUND || EngagementConfiguration.ENABLE_REACH == true) { EngagementPostBuild.addUsesPermission(xmlDoc, manifestNode, namespaceManager, "android.permission.RECEIVE_BOOT_COMPLETED"); } // Update the manifest TextWriter textWriter = new StreamWriter(manifestPath); xmlDoc.Save(textWriter); textWriter.Close(); // revert the bundle id activityNode.Attributes.Append(xmlDoc.CreateAttribute("android", "name", EngagementPostBuild.androidNS)).Value = activity; Debug.Log("Generating :" + mfFilepath); mfWriter = new StreamWriter(mfFilepath); xmlDoc.Save(mfWriter); mfWriter.Close(); } }
protected override void OnPostProcessBuild(string playerPath) { #if UNITY_IOS string projPath = Path.Combine(playerPath, "Unity-iPhone.xcodeproj/project.pbxproj"); PBXProject proj = new PBXProject(); proj.ReadFromFile(projPath); string target = proj.TargetGuidByName("Unity-iPhone"); proj.SetBuildProperty(target, "ENABLE_BITCODE", m_EnableBitcode ? "YES" : "NO"); if (string.IsNullOrEmpty(m_AppleDeveloperTeamId)) { proj.SetBuildProperty(target, "DEVELOPMENT_TEAM", m_AppleDeveloperTeamId); } for (int i = 0; i < m_Frameworks.Length; i++) { var s = m_Frameworks[i]; proj.AddFrameworkToProject(target, s, true); } for (int i = 0; i < m_Files.Length; i++) { var s = m_Files[i]; proj.AddFileToBuild(target, proj.AddFile(Path.Combine("usr/lib/", s.Name), Path.Combine("Frameworks/", s.Name), (PBXSourceTree)s.SourceTree)); } proj.WriteToFile(projPath); string plistPath = Path.Combine(playerPath, "Info.plist"); PlistDocument plist = new PlistDocument(); plist.ReadFromFile(plistPath); PlistElementDict root = plist.root; for (int i = 0; i < m_InfoPlistEntries.Length; i++) { InfoPlistEntry entry = m_InfoPlistEntries[i]; switch (entry.Type) { case PlistEntryType.Boolean: root.SetBoolean(entry.Key, entry.BooleanValue); break; case PlistEntryType.Integer: root.SetInteger(entry.Key, entry.IntegerValue); break; case PlistEntryType.String: root.SetString(entry.Key, entry.StringValue); break; } } plist.WriteToFile(plistPath); var capabilityManager = new ProjectCapabilityManager(projPath, "Unity-iPhone/app.entitlements", "Unity-iPhone"); if (m_EnableGameCenter) { capabilityManager.AddGameCenter(); } if (m_EnableInAppPurchase) { capabilityManager.AddInAppPurchase(); } if (m_EnableKeychainSharing) { capabilityManager.AddKeychainSharing(m_KeychainAccessGroups); } if (m_EnablePushNotifications) { capabilityManager.AddPushNotifications(m_PushNotificationsDevelopment); } capabilityManager.WriteToFile(); #endif }