以前不是写了篇收集报错日志上传ftp服务器的文章,那时候由于某些缘由,我只有权限上传到ftp服务器上,可是在压测的时候发现不少问题,链接打不开,由于ftp有权限设置,还有链接人数上限,这就尴尬了,这就致使不少报错信息没有收到。这彻底不符合需求,所以,须要后台PHP来处理。php

PHP来处理就很是简单了,只须要上传字符串就行。性能上也优化了,皆大欢喜。代码就很简单,不说什么了。java

/// 
/// 上传错误日志
/// 
public void UploadErrorToPHP(string error)
{
if (!Main.bIsCollectLog) return;
StringBuilder sb = new StringBuilder();
sb.Append(ErrorUploadUrl + "&error=" + error);
sb.Append("&uname=" + account);
System.DateTime nowTime = System.DateTime.Now;
var filename = "Unity_" + (nowTime.ToString("HH_mm_ss"));
sb.Append("&filename=" + filename);
#if UNITY_EDITOR
string system = "PC";
#elif UNITY_ANDROID
string system = "Android";
#elif UNITY_IOS
string system = "IOS";
#endif
sb.Append("&system=" + system);
RequestHttp(sb.ToString(), requetTimeOut);
}
private string RequestHttp(string url, int Timeout = 100000)
{
string requestPath = url;
string result = "";
HttpWebRequest httpWebReq = null;
Stream stream = null;
StreamReader reader = null;
try
{
httpWebReq = (HttpWebRequest)WebRequest.Create(requestPath);
//Debug.LogError(" httpWebReq.Timeout: " + httpWebReq.Timeout);
httpWebReq.Timeout = Timeout;
httpWebReq.KeepAlive = false;
stream = httpWebReq.GetResponse().GetResponseStream();
reader = new StreamReader(stream, Encoding.UTF8);
string line = string.Empty;
while (line != null)
{
line = reader.ReadLine();
result = result + line + "\n";
}
result = Decrypt(result);
reader.Close();
stream.Close();
}
catch (Exception e)
{
Debug.Log("RequestHttp In Error. url:" + url + "--" + e.Message);
}
finally
{
if (stream != null)
stream.Close();
if (reader != null)
reader.Close();
if (httpWebReq != null)
httpWebReq.Abort();
}
return result;
}

有了报错日志,需求又增长了,想要获取崩溃日志。可是这边又不想用Bugly这些插件,会影响性能,以前测试过,有降帧。因此只好在Java层上在实现一套上传崩溃日志功能,由于如今安卓版本在测试,因此安卓功能优先,就意味下次我还得处理一套iOS的功能,尴尬了。web

以前有写过怎么获取java层的单例,这边也再也不多说一遍,仍是在以前写的安卓通用类上加了个接口。c#

开启接口服务器

/**
* 开启java层上传异常信息
*/
public void InitCatchException()
{
if(ec != null)
return;
ec = new exceptioncatch();
ec.Init();
}
/**
* 修改java层上传异常信息的帐号名
*/
public void SetAccount(String account)
{
if(ec != null)
{
ec.SetAccount(account);
}
}

捕获异常,须要注意的是要调用SystemClock.sleep(requetTimeOut)这个接口延迟一段时间关闭进程,否则还没上传数据到PHP就被关闭了。这个问题就致使我调了3,4个小时。在使用一段时间后,发现几乎没有收集到Java层的报错,以前写了个Android Demo测试,能够捕获到异常的,没有用Unity来测试,故意写个异常出来,Unity会捕获变成Unity层的错误,而后就调用了C#的上传报错日志接口。只好在网上继续搜索查找,而后找到了一个重要缘由:setUncaughtExceptionHandler只对应注册的线程起做用,对应的线程,这就尴尬了,果真不熟悉Android和Java,后果太严重了。也查找到了setDefaultUncaughtExceptionHandler则是在全部线程上都起做用。换了接口后,一个下午就收集到了Java上的报错信息。又是一个坑被我趟过。app

public class exceptioncatch implements Thread.UncaughtExceptionHandler {
private Thread.UncaughtExceptionHandler defaultThread;
private final String ErrorUploadUrl = "http://xxxxxxxxxxxxxx.php?";
private String account = "Login";
private int requetTimeOut = 5000;
public void Init()
{
Thread.setDefaultUncaughtExceptionHandler(this);//全部线程上都起做用
//Thread.currentThread().setUncaughtExceptionHandler(this);//只对应注册的线程起做用
defaultThread = Thread.getDefaultUncaughtExceptionHandler();
Log.e("ZP", "启动异常捕获");
}
public void SetAccount(String accoutStr)
{
account = accoutStr;
}
@Override
public void uncaughtException(Thread t, Throwable ex)
{
Log.e("ZP", "捕捉到了异常");
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
pw.close();
UploadErrorToPHP(sw.toString());
SystemClock.sleep(requetTimeOut);
defaultThread.uncaughtException(t, ex);
}
private void UploadErrorToPHP(String error)
{
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("(yyyy-mm-dd:HH:mm:ss)");
error = "[Java异常" + sdf.format(date) + "]" + error;
StringBuffer sb = new StringBuffer();
sb.append(ErrorUploadUrl + "error=" + error);
sb.append("&uname=" + account);
sdf = new SimpleDateFormat("HH_mm_ss");
String filename = "Java_" + sdf.format(date);
sb.append("&filename=" + filename);
sb.append("&system=Java");
RequestHttp(sb.toString());
}
private void RequestHttp(String requestUrl)
{
urlThread tempUrlThread = new urlThread();
tempUrlThread.SetRequestUrl(requestUrl);
Thread tempThread = new Thread(tempUrlThread);
tempThread.start();
}

上传到PHPide

public class urlThread implements Runnable {
private String requestUrl;
public void SetRequestUrl(String requestUrl)
{
this.requestUrl = requestUrl;
}
@Override
public void run() {
Log.e("ZP","开始上传报错:" + requestUrl);
if(requestUrl != null && !requestUrl.isEmpty()) {
try {
URL url = new URL(requestUrl);
//返回一个URLConnection对象,它表示到URL所引用的远程对象的链接
URLConnection connection = url.openConnection();
connection.connect();
InputStream is = connection.getInputStream();
Log.e("ZP","完成上传报错");
} catch (Exception e) {
e.printStackTrace();
Log.e("ZP","上传exception:" + e.toString());
}
finally {
requestUrl = null;
}
}
}
}

Java我不是很熟悉,不少我都是按照C#的逻辑来实现的,找几个相似C#的方法来实现的,好比java的url我就是照着c#的webrequest来的,总计为了实现这个功能踩了仍是蛮多的坑,记录下来防止之后继续踩坑。忽然发现本身在Unity上写功能的时间少了不少,都是在弄这种奇奇怪怪的需求。性能