前言
最近需要做一个在PC端的Bug上报功能,之前的Bugly是用在移动端的,其实不是很适合。
所以需要一个在PC端的Bug上报,然后在网上找到一个还不错的插件:Trello Bug Tracker
https://assetstore.unity.com/packages/tools/integration/trello-bug-tracker-pro-75613
不过网上对这个的介绍很少,所以一边学一边记录一下。
其实这类功能最关键的要实现的功能有这么几个:
1、用户反馈能上报;
2、能抓取日志;
3、自动抓取报错上报;
4、有一个给开发者的查看界面。
前面的都能在客户端实现,关键是第四个对吧。这个插件其实取了个巧,他是相当于白嫖了Trello这个网络协作插件来进行上报(其实按照他这个原理理论上也是可以接入别的看板网页之类,比如企业微信的TAPD这种)。
原理
这个插件的原理就是调用了Trello的开发者API,然后用WWW的方式来上传一个卡片(Card)到Trello的看板(Borad)。你可以理解为,这个插件白嫖了 Trello 的网站、数据存储,来实现了自己的错误上报功能。
插件的使用
原版的插件下载下来之后,他分为2个部分。一个是错误上报,还有一个部分是辅助类的,比如画图什么的。个人认为画图什么的没啥大用,可以不用管,但是上报的部分可以留着。
可以先打开它的例子程序来操作一下,点右下那个虫就可以上报了。
之后更多的是在程序方面的工作了。
初始化
当然,你需要先去Trello 的官网上注册一个账号先:https://trello.com。
之后需要将你的Key和Token取出来,用来初始化。
获取Key和Token的地址为 : https://trello.com/app-key
然后你需要在Trello上新建立一个Board来接收你的上传文件。
在网页的右上角有个 + 号,点击创建一个(看板)Board,然后记下这个看板的名字。
之后转入到代码上:
public string Key;
public string Token;
public string BoardName;
private Trello trello;
public const string ListName_Advice = "PlayerAcvice";
public const string ListName_PlayerReport = "PlayerReport";
public const string ListName_AutoReport = "AutoReport";
IEnumerator StartInit()
{
if (trello != null && trello.IsConnected())
{
Debug.Log("Trello 已经连接上!");
yield break;
}
trello = new Trello(Key, Token);
yield return trello.PopulateBoardsRoutine();
//设置当前看板;
trello.SetCurrentBoard(BoardName);
//获取当前看板下的列表;
yield return trello.PopulateListsRoutine();
/*
* 从网上拉下来的List可能与设定的有所不同。
* 设定的是需要 PlayerAdvice , PlayerReprot , AutoReport 三个。
* 分别对应的是玩家建议、玩家的错误反馈、自动的错误上报。
* 如果这三个标签没有则需要手动添加;
*/
bool isNeedReCache = false;
if (!trello.IsListCached(ListName_Advice))
{
yield return trello.UploadListRoutine(NewList(ListName_Advice));
isNeedReCache = true;
}
if (!trello.IsListCached(ListName_PlayerReport))
{
yield return trello.UploadListRoutine(NewList(ListName_PlayerReport));
isNeedReCache = true;
}
if (!trello.IsListCached(ListName_AutoReport))
{
yield return trello.UploadListRoutine(NewList(ListName_AutoReport));
isNeedReCache = true;
}
//如果修改了List,那就重新缓存一下;
if (isNeedReCache)
yield return trello.PopulateListsRoutine();
}
private TrelloList NewList(string name)
{
TrelloList list = trello.NewList();
list.name = name;
return list;
}
玩家上报
玩家上报需要建立一个新的UI面板来处理上报,这里就不用赘述了。直接跳到获取到了所需的信息之后,如何上传。
#region 用户上报部分
/// <summary>
/// 发送用户的建议;
/// </summary>
/// <param name="title"></param>
/// <param name="content"></param>
public void SendAdvice(string title, string content)
{
TrelloCard card = trello.NewCard(title, content, ListName_Advice);
StartCoroutine(SendReportRoutine(card, null));
}
/// <summary>
/// 发送用户的错误报告
/// </summary>
/// <param name="title"></param>
/// <param name="content"></param>
public void SendPlayerReport(string title, string content)
{
//与玩家建议不同的是,玩家错误报告需要上传错误日志;
TrelloCard card = trello.NewCard(title, content, ListName_PlayerReport);
StartCoroutine(SendReportRoutine(card, null, true));
}
public IEnumerator SendReportRoutine(TrelloCard card, List<Texture2D> screenshots = null, bool isLog = false)
{
// We upload the card with an async custom coroutine that will return the card ID
// Once it has been uploaded.
CustomCoroutine cC = new CustomCoroutine(this, trello.UploadCardRoutine(card));
yield return cC.coroutine;
// The uploaded card ID
string cardID = (string)cC.result;
//这里是截图上传,如果是玩家建议则不需要截图;
if (screenshots != null && screenshots.Count > 0)
{
int i = 0;
foreach (Texture2D screenshot in screenshots)
{
i++;
// We can now attach the screenshot to the card given its ID.
yield return trello.SetUpAttachmentInCardRoutine(cardID, "ScreenShot" + i + ".png", screenshot);
}
}
if (isLog)
{
#if UNITY_STANDALONE
// We make sure the log exists before trying to retrieve it.
if (System.IO.File.Exists(logPath))
{
// We make a copy of the log since the original is being used by Unity.
System.IO.File.Copy(logPath, logPathCopy, true);
// We attach the Unity log file to the card.
yield return trello.SetUpAttachmentInCardFromFileRoutine(cardID, "output_log.txt", logPathCopy);
}
#endif
}
//这里是上传自定义的玩家信息:
string userData = $"UserName : {"测试用户1"};\n" +
$"玩家等级{1}";
yield return trello.SetUpAttachmentInCardRoutine(cardID, "UserInfo.txt", userData);
}
// Platform dependent Log Path
private string logPath
{
get
{
#if UNITY_STANDALONE_WIN
var absolutePath = "%USERPROFILE%/AppData/LocalLow/" + Application.companyName + "/" + Application.productName + "/output_log.txt";
var filePath = System.Environment.ExpandEnvironmentVariables(absolutePath);
return filePath;
//Old windows log path
//return System.Diagnostics.Process.GetCurrentProcess().ProcessName + "_Data/output_log.txt";
#elif UNITY_STANDALONE_LINUX
return "~/.config/unity3d/" + Application.companyName + "/" + Application.productName + "/Player.log";
#elif UNITY_STANDALONE_OSX
return "~/Library/Logs/Unity/Player.log";
#else
return "";
#endif
}
}
// Platform dependent Log Path copy
private string logPathCopy
{
get
{
#if UNITY_STANDALONE_WIN
var absolutePath = "%USERPROFILE%/AppData/LocalLow/" + Application.companyName + "/" + Application.productName + "/output_logCopy.txt";
var filePath = System.Environment.ExpandEnvironmentVariables(absolutePath);
return filePath;
//Old windows log path
//return System.Diagnostics.Process.GetCurrentProcess().ProcessName + "_Data/output_log2.txt";
#elif UNITY_STANDALONE_LINUX
return "~/.config/unity3d/" + Application.companyName + "/" + Application.productName + "/PlayerCopy.log";
#elif UNITY_STANDALONE_OSX
return "~/Library/Logs/Unity/PlayerCopy.log";
#else
return "";
#endif
}
}
#endregion
这样就算完成了一个简易地,由玩家触发的上传机制。
接下来测试一下,我在面板里分别上传了1个建议和1个报错,然后我们转到Trello的网站上看:
可以看到已经成功上传了。后续只需要调整一些格式和内容,根据项目进行调优即可。
后记
还有一个很重要的功能就是Bug的自动上报,也就是当我们检测到控制台打印出Error或者Exception的时候,就自动抓取进行上报。这个功能我打算新开一篇来写,这一篇篇幅略长。
新的一篇在这里:https://blog.csdn.net/cyf649669121/article/details/105654015
改造后的文件:https://download.csdn.net/download/cyf649669121/12346924