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
}
}
}
}
注:配置中对就的值都是假的
三、当然对应的平台代码下,可以做好相当的数据读取工作。这里就不上代码了。