介绍

在调试真机时,经常需要查看日志,可是在真机上并不方便搜索日志,因此最好可以将日志发送到其他地方。

项目使用企业微信,因此可以将日志发送到微信群中。结合项目使用的 Unity 插件推荐:In-game Debug Console - 狂飙Unity 插件推荐:SRDebugger - 狂飙 两款插件,编写代码实现发送全部日志功能。

思路

由于是开发者工具,因此并不需要考虑卡顿之类的事情,直接使用同步 API 进行发送日志与消息。

企业微信发送文件需要先上传文件,然后再发送一条引用此文件的消息。文件有效期是 72 小时,注意及时下载。

代码

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
public class DeveloperTool
{
    public class WeChatUploadFile
    {
        // ReSharper disable IdentifierTypo
        public int errcode { get; set; }
        public string errmsg { get; set; }
        public string type { get; set; }
        public string media_id { get; set; }
        public string created_at { get; set; }
        // ReSharper restore IdentifierTypo
    }

    [Category("工具"), DisplayName("发送所有日志")]
    public void SendLogFile()
    {
        string url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&type=file";
        // ReSharper disable once StringLiteralTypo
        string time = DateTime.Now.ToString("yyyyMMdd-HHmmss");
        string fileName = $"Unity-Android-Log-{time}.log";
        string fileContent = DebugLogManager.Instance.GetAllLogs();
        string paramName = "media";
        string contentType = "multipart/form-data";
        var nvc = new NameValueCollection();

        // File.WriteAllText(fileName, fileContent);
        string mediaId = WeChatHttpUploadFile(url, fileName, fileContent, paramName, contentType, nvc);

        if (string.IsNullOrEmpty(mediaId))
        {
            Debug.LogWarning("Upload log file failed");
            return;
        }

        JObject msg = new JObject
        {
            // ReSharper disable once StringLiteralTypo
            ["msgtype"] = "file",
            ["file"] = new JObject(),
            ["file"] =
            {
                ["media_id"] = mediaId
            }
        };
        string content = JsonConvert.SerializeObject(msg);

        SendWeChat(content);
    }

    private static string WeChatHttpUploadFile(string url, string fileName, string fileContent, string paramName, string contentType,
        NameValueCollection nvc)
    {
        string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
        byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

        HttpWebRequest wr = (HttpWebRequest) WebRequest.Create(url);
        wr.ContentType = "multipart/form-data; boundary=" + boundary;
        wr.Method = "POST";
        wr.KeepAlive = true;
        wr.Credentials = System.Net.CredentialCache.DefaultCredentials;

        Stream rs = wr.GetRequestStream();

        string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
        foreach (string key in nvc.Keys)
        {
            rs.Write(boundarybytes, 0, boundarybytes.Length);
            string formitem = string.Format(formdataTemplate, key, nvc[key]);
            byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
            rs.Write(formitembytes, 0, formitembytes.Length);
        }

        rs.Write(boundarybytes, 0, boundarybytes.Length);

        string headerTemplate =
            "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
        string header = string.Format(headerTemplate, paramName, fileName, contentType);
        byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
        rs.Write(headerbytes, 0, headerbytes.Length);

        var bytes = Encoding.UTF8.GetBytes(fileContent);
        rs.Write(bytes, 0, bytes.Length);

        byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
        rs.Write(trailer, 0, trailer.Length);
        rs.Close();

        WebResponse wresp = null;
        try
        {
            wresp = wr.GetResponse();
            Stream stream2 = wresp.GetResponseStream();
            StreamReader reader2 = new StreamReader(stream2);
            string response = reader2.ReadToEnd();
            Debug.Log(string.Format("File uploaded, server response is: {0}", response));

            var weChatUploadFile = JsonConvert.DeserializeObject<WeChatUploadFile>(response);
            if (weChatUploadFile != null)
            {
                return weChatUploadFile.media_id;
            }
        }
        catch (Exception ex)
        {
            Debug.LogError("Error uploading file" + ex);
            if (wresp != null)
            {
                wresp.Close();
                wresp = null;
            }
        }
        finally
        {
            wr = null;
        }

        return string.Empty;
    }

    private static void SendWeChat(string content, int type = 0)
    {
        string url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";

        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
        req.Method = "POST";
        if (type == 1)
        {
            req.ContentType = "application/octet-stream";
        }
        else
        {
            req.ContentType = "application/json";
        }

        byte[] data = Encoding.UTF8.GetBytes(content);
        req.ContentLength = data.Length;
        using (Stream reqStream = req.GetRequestStream())
        {
            reqStream.Write(data, 0, data.Length);
            reqStream.Close();
        }

        HttpWebResponse response = (HttpWebResponse)req.GetResponse();
        using (Stream respStream = response.GetResponseStream())
        {   
            if (respStream != null)
            {
                using (StreamReader myStreamReader = new StreamReader(respStream, Encoding.UTF8))
                {
                    string result = myStreamReader.ReadToEnd();
                    Debug.Log("Send result" + result);
                }
            }
        }
    }
}

参考资料