unity打包时自动配置AndroidManifest.xml和xcode工程

unity version:2017.4.3f1

unity 打包时,根据配置,自动配置android的AndroidManifest.xml和xcode工程设置和它的Info.plist
一、直接上配置代码 :

/***************************************************
 * 文件名:GlobalVar.cs
 * 描  述:自定义打包处理器
 * 时  间:2018-06-27
 * 作  者:AnyuanLzh
 * 修  改:
 *****************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.Build;
#if UNITY_IOS
using UnityEditor.iOS.Xcode;
#endif
using System.IO;
using LitJson;
using System.Xml;

public class MyCustomBuildProcessor : IPreprocessBuild, IPostprocessBuild
{
    public int callbackOrder
    {
        get { return 0; }
    }

    // build 开始时
    public void OnPreprocessBuild(BuildTarget target, string path)
    {
        //throw new System.NotImplementedException();
        if (target == BuildTarget.Android)
        {
            OnPreprocessBuild_android(target, path);
        }
    }

    // build 完成时
    public void OnPostprocessBuild(BuildTarget target, string path)
    {
        if (target == BuildTarget.iOS)
        {
            OnPostprocessBuild_ios(target, path);
        }
    }

    /// <summary>
    /// 在生成android apk前,将一些配置写入AndroidManifest.xml
    /// </summary>
    /// <param name="buildTarget"></param>
    /// <param name="path"></param>
    public static void OnPreprocessBuild_android(BuildTarget buildTarget, string path)
    {
        //Debug.Log ("path: " + path);
        if (buildTarget != BuildTarget.Android)
        {
            return;
        }
        // 添加 app_icon
        string originPath = Application.dataPath + "/NonHotDiff/textures/icon/app_icon.png";
        string targetPath = Application.dataPath + "/Plugins/Android/drawable/app_icon.png";
        if(File.Exists(originPath)==false)
        {
            Debug.LogError("缺少必要文件:"+originPath);
            return;
        }
        string targetDir = Path.GetDirectoryName(targetPath);
        if(Directory.Exists(targetDir)==false)
        {
            Directory.CreateDirectory(targetDir);
        }
        if (File.Exists(targetPath))
        {
            File.Delete(targetPath);
        }
        File.Copy(originPath, targetPath, true);


        // 读取配置,一定要保证配置的正确性
        string configPath = Application.dataPath + "/NonHotDiff/Resources/config/app_config.json";
        if (File.Exists(configPath) == false)
        {
            Debug.LogError("缺少必要文件:"+ configPath);
            return;
        }
        string configContent = File.ReadAllText(configPath);
        JsonData jd = JsonMapper.ToObject(configContent);

        // 读取xml
        string xmlPath = Application.dataPath + "/Plugins/Android/AndroidManifest.xml";
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(xmlPath);

        // 包名
        XmlNode node = xmlDoc.SelectSingleNode("/manifest");
        node.Attributes["package"].Value = jd["basic"]["app_package_name"].ToString();

        // scheme
        node = FindNode(xmlDoc, "/manifest/application/activity/intent-filter/data", "android:name", "appscheme");
        node.Attributes["android:scheme"].Value = jd["android"]["android_manifest"]["url_schemes_name"].ToString();
        // 百度-paraches
        node = FindNode(xmlDoc, "/manifest/application/activity/intent-filter/data", "android:scheme", "paraches");
        node.Attributes["android:host"].Value = jd["android"]["android_manifest"]["baidu_paraches"].ToString();
        // 百度-API_KEY
        node = FindNode(xmlDoc, "/manifest/application/meta-data", "android:name", "com.baidu.lbsapi.API_KEY");
        node.Attributes["android:value"].Value = jd["android"]["android_manifest"]["baidu_app_key"].ToString();
        // 云娃-YvImSdkAppId
        node = FindNode(xmlDoc, "/manifest/application/meta-data", "android:name", "YvImSdkAppId");
        node.Attributes["android:value"].Value = jd["android"]["android_manifest"]["yunwa_app_id"].ToString();
        // bugly appid
        node = FindNode(xmlDoc, "/manifest/application/meta-data", "android:name", "BUGLY_APPID");
        node.Attributes["android:value"].Value = jd["android"]["android_manifest"]["bugly_app_id"].ToString();

        // 自定义
        string xpath = "/manifest/application/meta-data";
        string key = "android:name";
        string value = "android:value";
        node = FindNode(xmlDoc, xpath, key, "wx_app_id");
        node.Attributes[value].Value = jd["android"]["android_manifest"]["wx_app_id"].ToString();
        node = FindNode(xmlDoc, xpath, key, "wx_app_secret");
        node.Attributes[value].Value = jd["android"]["android_manifest"]["wx_app_secret"].ToString();
        node = FindNode(xmlDoc, xpath, key, "xianliao_app_id");
        node.Attributes[value].Value = jd["android"]["android_manifest"]["xianliao_app_id"].ToString();
        node = FindNode(xmlDoc, xpath, key, "yunwa_app_id");
        node.Attributes[value].Value = jd["android"]["android_manifest"]["yunwa_app_id"].ToString();
        node = FindNode(xmlDoc, xpath, key, "baidu_app_key");
        node.Attributes[value].Value = jd["android"]["android_manifest"]["baidu_app_key"].ToString();
        node = FindNode(xmlDoc, xpath, key, "bugly_app_id");
        node.Attributes[value].Value = jd["android"]["android_manifest"]["bugly_app_id"].ToString();
        node = FindNode(xmlDoc, xpath, key, "url_schemes_name");
        node.Attributes[value].Value = jd["android"]["android_manifest"]["url_schemes_name"].ToString();

        // 保存
        xmlDoc.Save(xmlPath);
        AssetDatabase.Refresh();

    }

    /// <summary>
    /// 在生成xcode工程后,自动将一些ios配置写入xcode工程
    /// </summary>
    /// <param name="buildTarget"></param>
    /// <param name="path"></param>
    public static void OnPostprocessBuild_ios(BuildTarget buildTarget, string path)
    {
#if UNITY_IOS
        //Debug.Log ("path: " + path);
        if (buildTarget != BuildTarget.iOS)
        {
            return;
        }

        // 读取配置,一定要保证配置的正确性
        string configPath = Application.dataPath + "/NonHotDiff/Resources/config/app_config.json";
        string configContent = File.ReadAllText(configPath);
        JsonData jd = JsonMapper.ToObject(configContent);

#region 修改工程
        string projPath = PBXProject.GetPBXProjectPath (path);
        //Debug.Log ("projPath: " + projPath);
        PBXProject proj = new PBXProject ();
        string fileText = File.ReadAllText(projPath);
        proj.ReadFromString (fileText);
        //Debug.Log ("fileText: " + fileText);

        string targetName = PBXProject.GetUnityTargetName ();//Unity-iPhone
        string targetGuid = proj.TargetGuidByName (targetName);
        //Debug.Log ("targetName: " + targetName);
        //Debug.Log ("targetGuid: " + targetGuid);

        // BuildPropertys
        JsonData jd_SetBuildPropertys = jd["ios"]["xcode_project"]["set_build_property"];
        foreach(string key in jd_SetBuildPropertys.Keys)
        {
            if (key.StartsWith("--")) continue;
            proj.SetBuildProperty(targetGuid, key, jd_SetBuildPropertys[key].ToString());
        }
        JsonData jd_AddBuildPropertys = jd["ios"]["xcode_project"]["add_build_property"];
        foreach (string key in jd_AddBuildPropertys.Keys)
        {
            if (key.StartsWith("--")) continue;
            proj.AddBuildProperty(targetGuid, key, jd_AddBuildPropertys[key].ToString());
        }

        // Framework
        string fileguid = proj.FindFileGuidByProjectPath("libiconv.2.dylib");
        proj.RemoveFile(fileguid);
        JsonData jd_frameworks = jd["ios"]["xcode_project"]["add_framework"];
        foreach (string key in jd_frameworks.Keys)
        {
            if (key.StartsWith("--")) continue;
            proj.AddFrameworkToProject(targetGuid, key, (bool)jd_frameworks[key]);
        }

        // save changed
        File.WriteAllText (projPath, proj.WriteToString ());
#endregion


#region 修改plist
        string plistPath = Path.Combine(path, "Info.plist");
        Debug.Log ("plistPath: " + plistPath);
        PlistDocument plist = new PlistDocument();
        string plistFileText = File.ReadAllText(plistPath);
        plist.ReadFromString(plistFileText);
        PlistElementDict rootDict = plist.root;

        JsonData jd_plist = jd["ios"]["xcode_plist"];
        foreach (string key in jd_plist.Keys)
        {
            if (key.StartsWith("--")) continue;
            if (key == "CFBundleURLTypes")
            {
                PlistElementArray array = rootDict.CreateArray(key);
                PlistElementDict dict = array.AddDict();

                JsonData jd_temp = jd_plist[key];
                foreach (string k in jd_temp.Keys)
                {
                    if (k.StartsWith("--")) continue;
                    if(jd_temp[k].IsArray)
                    {
                        PlistElementArray array_temp = dict.CreateArray(k);
                        int count = jd_temp[k].Count;
                        for(int i=0; i<count; i++)
                        {
                            array_temp.AddString(jd_temp[k][i].ToString());
                        }
                    }
                    else
                    {
                        dict.SetString(k, jd_temp[k].ToString());
                    }

                }
            }
            else if (key == "LSApplicationQueriesSchemes")
            {
                JsonData jd_temp = jd_plist[key];
                if(jd_temp.IsArray == false)
                {
                    Debug.LogError("LSApplicationQueriesSchemes项配置出错,它应该是一个数组行式");
                }
                PlistElementArray array_temp = rootDict.CreateArray(key);
                int count = jd_temp.Count;
                for (int i = 0; i < count; i++)
                {
                    array_temp.AddString(jd_temp[i].ToString());
                }
            }
            else
            {
                rootDict.SetString(key, jd_plist[key].ToString());
            }
        }

        // 保存修改
        File.WriteAllText(plistPath, plist.WriteToString());

#endregion
#endif
    }

    static XmlNode FindNode(XmlDocument xmlDoc, string xpath, string attributeName, string attributeValue)
    {
        XmlNodeList nodes = xmlDoc.SelectNodes(xpath);
        //Debug.Log(nodes.Count);
        for (int i = 0; i < nodes.Count; i++)
        {
            XmlNode node = nodes.Item(i);
            string _attributeValue = node.Attributes[attributeName].Value;
            if (_attributeValue == attributeValue)
            {
                return node;
            }
        }
        return null;
    }

}

二、对应的配置文件模板

{
    "summary": {
        "date": "2018-06-15",
        "author": "anyuanlzh",
        "description": "这是一个app的基本设定的配置, 其中所有key和它的层次不能变动,切记!还有以'--'开头的key表示注释。"
    },


    "basic": {
        "app_name": "xx App",
        "app_package_name": "com.xx.xxx"
    },

    "global_val": {
        "standord_screen_width": 1280,
        "standord_screen_height": 720,
        "is_res_mode_debug": false,
        "is_open_luaide_debug": false,
        "is_open_lua_file_encrypt": false,
        "is_open_lua_socket": false,
        "is_open_res_update": false,
        "res_server_url": "http://xxx.xxx.xxx.xxx/xx_dir"
    },


    "android": {
        "android_manifest": {

            "-- custom": "自定义类",
            "wx_app_id": "wx_app_id_value",
            "wx_app_secret": "wx_app_secret_value",
            "xianliao_app_id": "xianliao_app_id_value",
            "yunwa_app_id": "yunwa_app_id_value",
            "baidu_app_key": "baidu_app_key_value",
            "bugly_app_id": "c6697c1768",
            "url_schemes_name": "url_schemes_name",

            "-- non custom": "非自定义",
            "baidu_paraches": "baidu_paraches"
        }
    },

    "ios": {

        "xcode_plist": {

            "-- custom": "自定义类",
            "wx_app_id": "wx_app_id_value",
            "wx_app_secret": "wx_app_secret_value",
            "xianliao_app_id": "xianliao_app_id_value",
            "yunwa_app_id": "yunwa_app_id_value",
            "baidu_app_key": "baidu_app_key_value",
            "bugly_app_id": "bugly_app_id_value",
            "url_schemes_name": "url_schemes_name",



            "-- not custom": "非自定义类",
            "NSCameraUsageDescription": "App需要您的同意,才能访问相机",
            "NSLocationWhenInUseUsageDescription": "App需要您的同意,才能在访问位置",
            "NSMicrophoneUsageDescription": "App需要您的同意,才能访问麦克风",

            "CFBundleURLTypes": {
                "CFBundleTypeRole": "Editor",
                "CFBundleURLName": "xxxxx",
                "CFBundleURLSchemes": [
                    "xxxxx",
                    "xxxx",
                    "xxxxxx"
                ]
            },
            "LSApplicationQueriesSchemes": [
                "wechat",
                "weixin",
                "xianliao"
            ]
        },

        "xcode_project": {
            "set_build_property": {
                "CFBundleDevelopmentRegion": "zh_CN",
                "ENABLE_BITCODE": "NO",
                "GCC_ENABLE_OBJC_EXCEPTIONS": "YES",
                "DEBUG_INFORMATION_FORMAT": "dwarf"
            },

            "add_build_property": {
                "OTHER_LDFLAGS": "-ObjC"
            },

            "add_framework": {
                "libz.tbd": false,
                "libz.1.tbd": false,
                "libc++.tbd": false,
                "libiconv.2.tbd": false,
                "libsqlite3.0.tbd": false,
                "libstdc++.6.0.9.tbd": false,

                "CFNetwork.framework": false,
                "CoreLocation.framework": false,
                "CoreTelephony.framework": false,
                "JavaScriptCore.framework": false,
                "ImageIO.framework": false,
                "MobileCoreServices.framework": false,
                "SafariServices.framework": false,
                "Security.framework": false,
                "StoreKit.framework": false,
                "SystemConfiguration.framework": false
            }
        }

    }
}

注:配置中对就的值都是假的

三、当然对应的平台代码下,可以做好相当的数据读取工作。这里就不上代码了。

猜你喜欢

转载自blog.csdn.net/AnYuanLzh/article/details/80931062