by Aklan
ZeaLotSean Modify
转载请注明.
多渠道sdk自动打包工具
ApkBuilder.cs
using GameResBuild;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
public class ApkBuilder : EditorBase
{
public string localAndroidSDKPath = Application.dataPath + "/Plugins/Android";
public int columnCount = 5;
///
/// 是否打包带AssetBundle的
///
private bool m_bAssetBundleBuild = false;
[MenuItem("Build/ZeaLot's MakeApp/ApkBuilder")]
private static void DrawWindow()
{
ApkBuilder window = (ApkBuilder)EditorWindow.GetWindow(typeof(ApkBuilder));
}
private void OnGUI()
{
AddTitleLabel("BuildConfigEditor, by Aklan\r\nZeaLot Modify");
if (!OnShow)
{
return;
}
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
LeftNameLabel("单行最大显示数量");
columnCount = EditorGUILayout.IntField(columnCount, GUILayout.Width(fieldWidth / 2));
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.Space();
m_bAssetBundleBuild = EditorGUILayout.Toggle("是否打AssetBundle包", m_bAssetBundleBuild);
EditorGUILayout.Space();
EditorGUILayout.Space();
LeftNameLabel("所有渠道打包");
if (GUILayout.Button("打包所有渠道", GUILayout.Width(btnWidth)))
{
BuildAllApk();
}
EditorGUILayout.Space();
EditorGUILayout.Space();
LeftNameLabel("单个渠道打包");
int index = 0;
foreach (var iter in BuildConfigDic)
{
if (index % columnCount == 0)
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button(iter.Value.channelName, GUILayout.Width(btnWidth)))
{
Debug.Log("Start build single apk");
if (EditorUtility.DisplayDialog("确认打包", "是否执行_" + iter.Value.channelName + "_打包?", "Yes", "No"))
{
BuildSingleApk(iter.Value.channelName);
}
// ShowBuildPath();
}
if (index % columnCount == (columnCount - 1))
{
EditorGUILayout.EndHorizontal();
}
index++;
}
}
///
/// 打包完成后打开目录
///
private void ShowBuildPath()
{
System.Diagnostics.Process.Start(CommonTools.buildPath);
}
private void BuildAllApk()
{
if (EditorUtility.DisplayDialog("确认打包", "是否执行所有渠道一键打包?", "Yes", "No"))
{
Debug.Log("Start build all apk");
List buildList = BuildConfigDic.Keys.ToList();
for (int i = 0; i < buildList.Count; i++)
{
BuildSingleApk(buildList[i]);
}
// ShowBuildPath();
}
}
private void BuildSingleApk(string channelName)
{
BuildConfig _config;
BuildConfigDic.TryGetValue(channelName, out _config);
if (_config == null)
{
return;
}
SaveBuildValue(_config);
AssetsCopyDirectory(_config.androidSDKPath, localAndroidSDKPath);
// 调用我们自己的打包
// BuildToAndroid(config);
if (m_bAssetBundleBuild)
{
BuildAssetBundle.OneKeyMakApp();
}
else
{
BuildAssetBundle.BuildPlayerUnity();
}
}
private void AssetsCopyDirectory(string fromPath, string toPath)
{
Debug.LogWarning("Del_" + toPath + ":" + FileUtil.DeleteFileOrDirectory(toPath));
AssetDatabase.Refresh();
if (!Directory.Exists(fromPath))
{
return;
}
if (!Directory.Exists(toPath))
{
Directory.CreateDirectory(toPath);
}
string[] files = Directory.GetFiles(fromPath + "/");
foreach (string file in files)
{
string name = file.Substring(file.LastIndexOf("/"));
FileUtil.CopyFileOrDirectory(file, toPath + "/" + name);
}
string[] dirs = Directory.GetDirectories(fromPath + "/");
foreach (string dir in dirs)
{
string name = dir.Substring(dir.LastIndexOf("/"));
string _path = Path.Combine(name, toPath);
//UnityEngine.Debug.LogError(toPath);
//UnityEngine.Debug.LogError(name);
//UnityEngine.Debug.LogError(_path);
FileUtil.CopyFileOrDirectory(dir, toPath + "/" + name);
// FileUtil.CopyFileOrDirectory(dir, _path);
}
AssetDatabase.Refresh();
}
public void SaveBuildValue(BuildConfig _config)
{
PlayerSettings.bundleIdentifier = _config.bundleIdentifier;
PlayerSettings.bundleVersion = _config.bundleVersion;
PlayerSettings.Android.bundleVersionCode = _config.bundleVersionCode;
PlayerSettings.Android.keystoreName = _config.keystorePath;
PlayerSettings.Android.keystorePass = _config.keystorePassword;
PlayerSettings.Android.keyaliasName = _config.keyName;
PlayerSettings.Android.keyaliasPass = _config.keyPassword;
PlayerSettings.productName = _config.appName;
PlayerSettings.companyName = _config.companyName;
if (BuildAssetBundle.IsOSXEditor())
{
PlayerSettings.SetIconsForTargetGroup(BuildTargetGroup.Unknown, new Texture2D[] { Resources.Load(_config.iconPath) as Texture2D });
}
else
{
// 之前的如果sdk里面有会被sdk覆盖
//PlayerSettings.SetIconsForTargetGroup(BuildTargetGroup.Unknown, new Texture2D[] { Resources.Load(_config.iconPath) as Texture2D });
// 无效
//PlayerSettings.SetIconsForTargetGroup(BuildTargetGroup.Android, new Texture2D[] { Resources.Load(_config.iconPath) as Texture2D });
Texture2D _tex2d = Resources.Load(_config.iconPath) as Texture2D;
if (_tex2d != null)
{
PlayerSettings.SetIconsForTargetGroup(BuildTargetGroup.Android,
new Texture2D[] { _tex2d, _tex2d, _tex2d,
_tex2d, _tex2d, _tex2d });
}
else
{
UnityEngine.Debug.LogError("Texture2D is Null");
}
}
PlayerSettings.Android.useAPKExpansionFiles = _config.m_bUsePKExpansionFiles;
UnityEngine.Debug.LogWarning("SaveBuildValue");
}
}
using System;
using System.Linq;
using UnityEditor;
using UnityEngine;
///
/// sdk编辑框
///
public class BuildConfigEditor : EditorBase
{
private BuildConfig CurrentConfig;
private bool CreateNew;
private string ChannelName;
private int SelectIndex;
private Texture AppIcon = null;
// Out Look Parameters
private Vector2 scrollViewVector2 = Vector2.zero;
[MenuItem("Build/ZeaLot's MakeApp/ConfigEditor")]
private static void DrawWindow()
{
BuildConfigEditor window = (BuildConfigEditor)EditorWindow.GetWindow(typeof(BuildConfigEditor));
}
private BuildConfig AddNewConfig(string channelName)
{
BuildConfig config = new BuildConfig(channelName);
BuildConfigDic.Add(channelName, config);
return config;
}
private void Delete()
{
BuildConfigDic.Remove(CurrentConfig.channelName);
CommonTools.SaveXml(BuildConfigDic);
SelectIndex -= 1;
}
protected override void OnEnabling()
{
CreateNew = false;
SelectIndex = 0;
}
private void OnGUI()
{
string[] tempList;
AddTitleLabel("BuildConfigEditor, by Aklan\r\nZeaLot Modify");
EditorGUILayout.Space();
EditorGUILayout.Space();
if (!OnShow) return;
// 是否要新增配置
CreateNew = EditorGUILayout.BeginToggleGroup("创建新配置", CreateNew);
ChannelName = EditorGUILayout.TextField("渠道名", ChannelName, GUILayout.Width(labelWidth + fieldWidth));
if (!string.IsNullOrEmpty(ChannelName))
{
if (GUILayout.Button("Create", GUILayout.Width(btnWidth)))
{
if (!BuildConfigDic.ContainsKey(ChannelName))
{
AddNewConfig(ChannelName);
// 把index切换到新增的这个配置
tempList = BuildConfigDic.Keys.ToArray();
for (int i = 0; i < tempList.Length; i++)
{
if (tempList[i] == ChannelName)
{
SelectIndex = i;
break;
}
}
CreateNew = false;
}
}
}
EditorGUILayout.EndToggleGroup();
EditorGUILayout.Space();
EditorGUILayout.Space();
if (!CreateNew)
{
// 选择一个做显示
LeftNameLabel("选择要编辑的渠道配置", 400);
tempList = BuildConfigDic.Keys.ToArray();
SelectIndex = EditorGUILayout.Popup(SelectIndex, tempList, GUILayout.Width(fieldWidth));
if (SelectIndex < tempList.Length && SelectIndex >= 0)
{
BuildConfigDic.TryGetValue(tempList[SelectIndex], out CurrentConfig);
EditorGUILayout.Space();
EditorGUILayout.Space();
// 图标
LeftNameLabel("应用图标");
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Select Icon", GUILayout.Width(btnWidth)))
{
CurrentConfig.iconPath = EditorUtility.OpenFilePanel("Select Icon", "", "png");
if (!string.IsNullOrEmpty(CurrentConfig.iconPath))
{
string[] temp = CurrentConfig.iconPath.Split(new string[] { "Resources/" }, StringSplitOptions.None);
CurrentConfig.iconPath = temp[1];
CurrentConfig.iconPath = CurrentConfig.iconPath.Split(new string[] { ".png" }, StringSplitOptions.None)[0];
}
}
AppIcon = Resources.Load(CurrentConfig.iconPath) as Texture;
if (AppIcon != null)
EditorGUI.DrawPreviewTexture(new Rect(170, 150, AppIcon.width / 2, AppIcon.height / 2), AppIcon);
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
LeftNameLabel("打包配置相关");
CurrentConfig.m_bUsePKExpansionFiles = EditorGUILayout.Toggle("是否打分包(apk + obb)", CurrentConfig.m_bUsePKExpansionFiles);
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
LeftNameLabel("名字相关");
CurrentConfig.fileName = EditorGUILayout.TextField("电脑上显示的文件名", CurrentConfig.fileName, GUILayout.Width(labelWidth + fieldWidth));
CurrentConfig.appName = EditorGUILayout.TextField("手机上显示的游戏名", CurrentConfig.appName, GUILayout.Width(labelWidth + fieldWidth));
CurrentConfig.companyName = EditorGUILayout.TextField("公司名", CurrentConfig.companyName, GUILayout.Width(labelWidth + fieldWidth));
EditorGUILayout.Space();
LeftNameLabel("AndroidSDKPath");
LeftNameLabel(CurrentConfig.androidSDKPath, labelWidth + fieldWidth);
if (GUILayout.Button("Select SDK", GUILayout.Width(btnWidth)))
{
CurrentConfig.androidSDKPath = EditorUtility.OpenFolderPanel("Select Android File", CurrentConfig.androidSDKPath, "Android");
}
EditorGUILayout.Space();
EditorGUILayout.Space();
// 包信息设置//
EditorGUILayout.BeginHorizontal();
LeftNameLabel("Bundle Identifier");
CurrentConfig.bundleIdentifier = EditorGUILayout.TextField(CurrentConfig.bundleIdentifier, GUILayout.Width(fieldWidth));
LeftNameLabel("Bundle Version");
CurrentConfig.bundleVersion = EditorGUILayout.TextField(CurrentConfig.bundleVersion, GUILayout.Width(fieldWidth / 2));
LeftNameLabel("Version Code");
CurrentConfig.bundleVersionCode = EditorGUILayout.IntField(CurrentConfig.bundleVersionCode, GUILayout.Width(fieldWidth / 2));
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
LeftNameLabel("Keystore");
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Browse Keystore", GUILayout.Width(btnWidth * 2)))
{
CurrentConfig.keystorePath = EditorUtility.OpenFilePanel("Select Keystore", "", "keystore");
}
EditorGUILayout.LabelField(CurrentConfig.keystorePath);
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
LeftNameLabel("Keystore password", 20);
CurrentConfig.keystorePassword = EditorGUILayout.TextField(CurrentConfig.keystorePassword, GUILayout.Width(fieldWidth - 20));
EditorGUILayout.EndHorizontal();
LeftNameLabel("Key");
EditorGUILayout.BeginHorizontal();
LeftNameLabel("Name");
CurrentConfig.keyName = EditorGUILayout.TextField(CurrentConfig.keyName, GUILayout.Width(fieldWidth));
LeftNameLabel("Password");
CurrentConfig.keyPassword = EditorGUILayout.TextField(CurrentConfig.keyPassword, GUILayout.Width(fieldWidth));
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("保存配置", GUILayout.Width(btnWidth * 2)))
{
CommonTools.SaveXml(BuildConfigDic);
EditorUtility.DisplayDialog("Save Finish!", "Save Finish!", "ok");
}
EditorGUILayout.Space();
if (GUILayout.Button("删除配置", GUILayout.Width(btnWidth * 2)))
{
Delete();
}
EditorGUILayout.EndHorizontal();
}
}
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.TextArea("\n\n注意事项:\n" +
"把SDK按渠道归类,比如'C:/Users/Aklan/Desktop/SDK/MI'为小米渠道,且不要放到Assets目录下\n" +
"编辑时:\n" +
"1.新建渠道配置,或选择一个要编辑的配置\n" +
"2.选择本渠道包对应的icon\n" +
"3.设置本渠道包的相关名字\n" +
"4.选择SDK目录,比如'C:/Users/Aklan/Desktop/SDK/MI'\n" +
"5.填写包名,版本等信息\n" +
"6.选择keystore\n" +
"7.点击保存或删除\n" +
"注意:路径不能有中文\n\n");
}
}
///
/// 打包用配置信息
///
public class BuildConfig
{
///
/// 渠道名
///
public string channelName = "打包时显示的渠道名";
///
/// icon路径
///
public string iconPath = "Textures/GameIcon/";
///
/// 显示在电脑里的文件名
///
public string fileName = "文件名称";
///
/// 显示在手机上的应用名
///
public string appName = "应用名称";
///
/// 公司名
///
public string companyName = "公司名称";
///
/// 处理好的SDK文件夹路径
///
public string androidSDKPath = "点击按钮选择对应本渠道的SDK目录";
///
/// 包名
///
public string bundleIdentifier = "请填写包名";
///
/// 包版本名
///
public string bundleVersion = "请填写版本名";
///
/// 版本号
///
public int bundleVersionCode = 1;
///
/// keystore路径
///
public string keystorePath = "";
///
/// keystore密码
///
public string keystorePassword = "";
///
/// keystore别名
///
public string keyName = "";
///
/// keystore别名密码
///
public string keyPassword = "";
///
/// 分包
///
public bool m_bUsePKExpansionFiles = false;
///
/// 是否使用sdk
///
public bool m_useSdk = false;
public BuildConfig()
{
}
public BuildConfig(string channelName)
{
this.channelName = channelName;
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using UnityEngine;
public static class CommonTools
{
public static string projectPath = Application.dataPath.Split(new string[] { "Assets" }, StringSplitOptions.None)[0];
public static string buildPath = projectPath + "Builds/Android/";
public static string cfgPath = projectPath + "SDK/Config.xml";
public static void LoadXml(ref Dictionary dic)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(cfgPath);
XmlNodeList nodeList = xmlDoc.SelectSingleNode("Config").ChildNodes;
foreach (XmlNode node in nodeList)
{
if (node.Name != "Child") continue;
BuildConfig config = new BuildConfig();
config.channelName = AnalyzeXmlToString(node, "channelName");
config.iconPath = AnalyzeXmlToString(node, "iconPath");
config.m_bUsePKExpansionFiles = bool.Parse(AnalyzeXmlToString(node, "useAPKExpansionFiles"));
config.fileName = AnalyzeXmlToString(node, "fileName");
config.appName = AnalyzeXmlToString(node, "appName");
config.companyName = AnalyzeXmlToString(node, "companyName");
config.androidSDKPath = AnalyzeXmlToString(node, "androidSDKPath");
config.bundleIdentifier = AnalyzeXmlToString(node, "bundleIdentifier");
config.bundleVersion = AnalyzeXmlToString(node, "bundleVersion");
config.bundleVersionCode = AnalyzeXmlToInt(node, "bundleVersionCode");
config.keystorePath = AnalyzeXmlToString(node, "keystorePath");
config.keystorePassword = AnalyzeXmlToString(node, "keystorePassword");
config.keyName = AnalyzeXmlToString(node, "keyName");
config.keyPassword = AnalyzeXmlToString(node, "keyPassword");
dic.Add(config.channelName, config);
}
}
public static void SaveXml(Dictionary dic)
{
File.Delete(cfgPath);
XmlDocument xmlDoc = new XmlDocument();
//创建Xml声明部分,即
XmlDeclaration dec = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
xmlDoc.AppendChild(dec);
XmlNode rootNode = xmlDoc.CreateElement("Config");
xmlDoc.AppendChild(rootNode);
foreach (var iter in dic)
{
XmlNode child = xmlDoc.CreateElement("Child");
XmlAttribute attr = xmlDoc.CreateAttribute("channelName");
attr.Value = iter.Value.channelName;
child.Attributes.Append(attr);
attr = xmlDoc.CreateAttribute("iconPath");
attr.Value = iter.Value.iconPath;
child.Attributes.Append(attr);
attr = xmlDoc.CreateAttribute("useAPKExpansionFiles");
attr.Value = iter.Value.m_bUsePKExpansionFiles.ToString();
child.Attributes.Append(attr);
attr = xmlDoc.CreateAttribute("fileName");
attr.Value = iter.Value.fileName;
child.Attributes.Append(attr);
attr = xmlDoc.CreateAttribute("appName");
attr.Value = iter.Value.appName;
child.Attributes.Append(attr);
attr = xmlDoc.CreateAttribute("companyName");
attr.Value = iter.Value.companyName;
child.Attributes.Append(attr);
attr = xmlDoc.CreateAttribute("androidSDKPath");
attr.Value = iter.Value.androidSDKPath;
child.Attributes.Append(attr);
attr = xmlDoc.CreateAttribute("bundleIdentifier");
attr.Value = iter.Value.bundleIdentifier;
child.Attributes.Append(attr);
attr = xmlDoc.CreateAttribute("bundleVersion");
attr.Value = iter.Value.bundleVersion;
child.Attributes.Append(attr);
attr = xmlDoc.CreateAttribute("bundleVersionCode");
attr.Value = iter.Value.bundleVersionCode.ToString();
child.Attributes.Append(attr);
attr = xmlDoc.CreateAttribute("keystorePath");
attr.Value = iter.Value.keystorePath;
child.Attributes.Append(attr);
attr = xmlDoc.CreateAttribute("keystorePassword");
attr.Value = iter.Value.keystorePassword;
child.Attributes.Append(attr);
attr = xmlDoc.CreateAttribute("keyName");
attr.Value = iter.Value.keyName;
child.Attributes.Append(attr);
attr = xmlDoc.CreateAttribute("keyPassword");
attr.Value = iter.Value.keyPassword;
child.Attributes.Append(attr);
rootNode.AppendChild(child);
}
xmlDoc.Save(cfgPath);
}
private static int AnalyzeXmlToInt(XmlNode node, string key)
{
if (node.Attributes[key] != null)
{
string tempValue = node.Attributes[key].Value;
if (tempValue.Length > 0)
return int.Parse(tempValue);
}
return 0;
}
private static string AnalyzeXmlToString(XmlNode node, string key)
{
if (node.Attributes[key] != null)
return node.Attributes[key].Value;
return "";
}
}
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class EditorBase : EditorWindow
{
protected bool OnShow = false;
protected Dictionary BuildConfigDic = new Dictionary();
protected GUIStyle titleStyle = new GUIStyle();
protected GUIStyleState titleState = new GUIStyleState();
protected static float totalWidth = 650;
protected float btnWidth = 100;
protected float labelWidth = 100;
protected float fieldWidth = 150;
protected float border = 4;
protected virtual void OnEnabling()
{
}
protected void LeftNameLabel(string name, float offsetWidth = 0)
{
EditorGUILayout.LabelField(name, GUILayout.Width(labelWidth + offsetWidth));
}
protected void AddTitleLabel(string title)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField(new GUIContent(title), titleStyle);
EditorGUILayout.Space();
}
private void OnEnable()
{
OnShow = false;
BuildConfigDic.Clear();
titleState.textColor = Color.white;
titleStyle.normal = titleState;
titleStyle.fontStyle = FontStyle.Bold;
CommonTools.LoadXml(ref BuildConfigDic);
OnEnabling();
OnShow = true;
}
}