自动打包多与自动上传一起使用,比如固定时间点或者SVN提交之后,自动出包,然后上传到指定内网网址或共享文件夹。
在此只记录一下关于自动打包的学习过程,只限于Windows打Android包,包含自动打包及其相关回调,编辑器自定义窗口,调用系统窗口选择路径,读取Windows桌面路径等功能。实际使用意义不大,还需要做一些功能的完善及扩展~~
感谢大佬们优秀的文章,对我帮助非常大:
unity3d在菜单栏,一键设置Player setting及自动打包并设置apk的存储位置
Unity调用系统窗口选择文件或文件路径
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using System.IO;
using System.Runtime.InteropServices;
using System;
using Microsoft.Win32;
//Assets/Editor文件夹下Test
namespace SimpleFrame.Tool
{
//确认窗口, 可用快捷键启动
public class AndroidPackageWindow : EditorWindow
{
[MenuItem("MyTools/Package/Build Android Package #&b")]
public static void Package()
{
//弹出确认窗口
EditorWindow.GetWindow(typeof(AndroidPackageWindow), false, "Build Android Package Window");
}
string showStr;
Texture2D defaultIcon;
//
string apkPath, apkName;
void OnEnable()
{
//确认信息
showStr = "\nBuild Platform : Android";
showStr += "\n\nCompany Name : " + PlayerSettings.companyName;
showStr += "\n\nProduct Name : " + PlayerSettings.productName;
showStr += "\n\nPackage Name : " + PlayerSettings.applicationIdentifier;
showStr += "\n\nBundle Version : " + PlayerSettings.bundleVersion;
showStr += "\n\nBundle Version Code : " + PlayerSettings.Android.bundleVersionCode;
//图标Iocn
Texture2D[] texture2Ds = PlayerSettings.GetIconsForTargetGroup(BuildTargetGroup.Android);
defaultIcon = texture2Ds.Length > 0 ? texture2Ds[0] : null;
//打包默认路径及默认文件名
apkPath = GetDesktopPath();
apkName = PlayerSettings.productName;
}
//获取Windows用户桌面路径
//https://blog.csdn.net/csethcrm/article/details/6163431
string GetDesktopPath()
{
RegistryKey folders = Registry.CurrentUser;
string s = @"/software/microsoft/windows/currentversion/explorer/shell folders";
s = s.Remove(0, 1) + @"/";
while (s.IndexOf(@"/") != -1)
{
folders = folders.OpenSubKey(s.Substring(0, s.IndexOf(@"/")));
s = s.Remove(0, s.IndexOf(@"/") + 1);
}
return folders.GetValue("Desktop").ToString();
}
void OnGUI()
{
GUILayout.Space(10);
GUILayout.Label("Please Make Sure");
defaultIcon = EditorGUILayout.ObjectField(defaultIcon, typeof(Texture2D), true) as Texture2D;
EditorGUILayout.TextArea(showStr);
GUILayout.Space(5);
apkPath = EditorGUILayout.TextField("Apk Path : ", apkPath);
if(!Directory.Exists(apkPath))
EditorGUILayout.TextArea("Apk Path Is Error");
apkName = EditorGUILayout.TextField("Apk Name : ", apkName);
if (string.IsNullOrEmpty(apkName))
EditorGUILayout.TextArea("Apk Name Is Empty");
//调用系统窗口,选择保存路径
if (GUILayout.Button("Select Path"))
{
OpenFileName openFileName = new OpenFileName();
openFileName.structSize = Marshal.SizeOf(openFileName);
openFileName.filter = "apk(*.apk)\0All files(*.*)";
openFileName.file = new string(new char[256]);
openFileName.maxFile = openFileName.file.Length;
openFileName.fileTitle = new string(new char[64]);
//openFileName.fileTitle = apkName;
openFileName.maxFileTitle = openFileName.fileTitle.Length;
openFileName.initialDir = apkPath.Replace('/', '\\');//默认路径
openFileName.title = "Select Path";
openFileName.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000008;
if (LocalDialog.GetSaveFileName(openFileName))
{
//截取字符串
apkName = openFileName.fileTitle.Split('.')[0];
apkPath = openFileName.file.Replace('\\', '/');
apkPath = apkPath.Split('.')[0];
apkPath = apkPath.Replace("/" + apkName, "");
Debug.Log(apkPath + " / " + apkName);
}
}
GUILayout.Space(10);
if (GUILayout.Button("Cancel"))
this.Close();
GUILayout.Space(5);
if (Directory.Exists(apkPath) && !string.IsNullOrEmpty(apkName))
{
if (GUILayout.Button("Sure"))
{
this.Close();
PackageTool.Build(apkPath, apkName);
}
}
this.Repaint();
}
void OnDisable()
{
showStr = null;
defaultIcon = null;
}
}
//https://blog.csdn.net/yzd1733638228/article/details/77989210
public class PackageTool
{
//打包操作
public static void Build(string apkPath, string apkName)
{
if (!Directory.Exists(apkPath) || string.IsNullOrEmpty(apkName))
return;
if (BuildPipeline.isBuildingPlayer)
return;
//设置打包平台、标签
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, null);
//打包场景路径
List sceneNames = new List();
foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes)
{
if (scene != null && scene.enabled)
{
sceneNames.Add(scene.path);
Debuger.Log(scene.path);
}
}
string path = apkPath + "/" + apkName + ".apk";
//开始打包
BuildPipeline.BuildPlayer(sceneNames.ToArray(), path, BuildTarget.Android, BuildOptions.None);
}
//回调 打包后操作
[PostProcessBuild(1)]
public static void AfterBuild(BuildTarget target, string pathToBuiltProject)
{
Debug.Log("Build Success " + target + " " + pathToBuiltProject);
//https://blog.csdn.net/zp288105109a/article/details/81366343
//可在此打开文件或文件夹
System.Diagnostics.Process.Start(pathToBuiltProject);
}
}
//https://blog.csdn.net/m0_37283423/article/details/78180487
//调用系统窗口
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class OpenFileName
{
//数据接收类
public int structSize = 0;
public IntPtr dlgOwner = IntPtr.Zero;
public IntPtr instance = IntPtr.Zero;
public String filter = null;
public String customFilter = null;
public int maxCustFilter = 0;
public int filterIndex = 0;
public String file = null;
public int maxFile = 0;
public String fileTitle = null;
public int maxFileTitle = 0;
public String initialDir = null;
public String title = null;
public int flags = 0;
public short fileOffset = 0;
public short fileExtension = 0;
public String defExt = null;
public IntPtr custData = IntPtr.Zero;
public IntPtr hook = IntPtr.Zero;
public String templateName = null;
public IntPtr reservedPtr = IntPtr.Zero;
public int reservedInt = 0;
public int flagsEx = 0;
}
//调用系统窗口函数
public class LocalDialog
{
//链接指定系统函数 //打开文件对话框
[DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
public static bool GetOFN([In, Out] OpenFileName ofn)
{
return GetOpenFileName(ofn);
}
//链接指定系统函数 //另存为对话框
[DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
public static extern bool GetSaveFileName([In, Out] OpenFileName ofn);
public static bool GetSFN([In, Out] OpenFileName ofn)
{
return GetSaveFileName(ofn);
}
}
}