Esempio n. 1
0
    /// <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;
            }
        }
    }
Esempio n. 2
0
 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成功!");
    }
Esempio n. 4
0
    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());
        }
Esempio n. 6
0
        /// <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));
     }
 }
Esempio n. 8
0
 //设置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
        }