4

I am attempting to develop an app for the Samsung Gear VR (with the Samsung Galaxy S8) and as it requires me to pull out the USB cable in order to plug the phone onto the Gear VR device, this does not allow me to do USB debugging.

How do I go about exporting error and debug messages into a file I can read in order to figure out what's going wrong?

So far, research has shown that android Unity player does not save to a log file while the other platforms do, and adb is the way to go for USB debugging... Only I can't do that for Gear.

Programmer
  • 104,912
  • 16
  • 182
  • 271

2 Answers2

12

How to export android Unity error and debug logs to file?

That doesn't exist yet. You have to make one yourself.

1.Subscribe to Unity Log event:

Application.logMessageReceived += LogCallback;

2.Store them in a List. When application is about to exit, serialize to json and save it with File.WriteAllBytes.

The path to save it to is Application.persistentDataPath. See this post that shows where the path can be found on any build in Unity.

Below is an example script that reads logs and saves it when app is about to exit. Also, it has the ability to email you the log data. This requires the DataSaver class from this post. Note that the email is sent next time the app is re-opened not when it exit.

using System.Collections.Generic;
using UnityEngine;

using System.IO;
using System.Net;
using System.Net.Mail;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System;
using System.Text;

public class LogSaverAndSender : MonoBehaviour
{
    public bool enableSave = true;
    public bool enableMailing = true;

    public string yourEmail = "fromemail@gmail.com";
    public string yourEmailPassword = "password";
    public string toEmail = "toemail@gmail.com";


    [Serializable]
    public struct Logs
    {
        public string condition;
        public string stackTrace;
        public LogType type;

        public string dateTime;

        public Logs(string condition, string stackTrace, LogType type, string dateTime)
        {
            this.condition = condition;
            this.stackTrace = stackTrace;
            this.type = type;
            this.dateTime = dateTime;
        }
    }

    [Serializable]
    public class LogInfo
    {
        public List<Logs> logInfoList = new List<Logs>();
    }

    LogInfo logs = new LogInfo();

    void OnEnable()
    {
        //Email last saved log
        if (enableMailing)
        {
            mailLog();
        }

        //Subscribe to Log Event
        Application.logMessageReceived += LogCallback;
    }

    //Called when there is an exception
    void LogCallback(string condition, string stackTrace, LogType type)
    {
        //Create new Log
        Logs logInfo = new Logs(condition, stackTrace, type, DateTime.Now.ToString("yyyy-MM-ddTHH:mm:sszzz"));

        //Add it to the List
        logs.logInfoList.Add(logInfo);
    }

    void mailLog()
    {
        //Read old/last saved log
        LogInfo loadedData = DataSaver.loadData<LogInfo>("savelog");
        string date = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:sszzz");

        //Send only if there is something to actually send
        if (loadedData != null && loadedData.logInfoList != null

            && loadedData.logInfoList.Count > 0)
        {

            Debug.Log("Found log to send!");

            //Convert to json
            string messageToSend = JsonUtility.ToJson(loadedData, true);

            string attachmentPath = Path.Combine(Application.persistentDataPath, "data");
            attachmentPath = Path.Combine(attachmentPath, "savelog.txt");

            //Finally send email
            sendMail(yourEmail, yourEmailPassword, toEmail, "Log: " + date, messageToSend, attachmentPath);

            //Clear old log
            DataSaver.deleteData("savelog");
        }
    }

    void sendMail(string fromEmail, string emaiPassword, string toEmail, string eMailSubject, string eMailBody, string attachmentPath = null)
    {
        try
        {
            MailMessage mail = new MailMessage();

            mail.From = new MailAddress(fromEmail);
            mail.To.Add(toEmail);
            mail.Subject = eMailSubject;
            mail.Body = eMailBody;

            if (attachmentPath != null)
            {
                System.Net.Mail.Attachment attachment = new System.Net.Mail.Attachment(attachmentPath);
                mail.Attachments.Add(attachment);
            }

            SmtpClient smtpClient = new SmtpClient();
            smtpClient.Host = "smtp.gmail.com";
            smtpClient.Port = 587;
            smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
            smtpClient.Credentials = new System.Net.NetworkCredential(fromEmail, emaiPassword) as ICredentialsByHost;
            smtpClient.EnableSsl = true;
            ServicePointManager.ServerCertificateValidationCallback =
                delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
                { return true; };
            smtpClient.Send(mail);
        }
        catch (Exception e) { }
    }

    void OnDisable()
    {
        //Un-Subscribe from Log Event
        Application.logMessageReceived -= LogCallback;
    }

    //Save log  when focous is lost
    void OnApplicationFocus(bool hasFocus)
    {
        if (!hasFocus)
        {
            //Save
            if (enableSave)
                DataSaver.saveData(logs, "savelog");
        }
    }

    //Save log on exit
    void OnApplicationPause(bool pauseStatus)
    {
        if (pauseStatus)
        {
            //Save
            if (enableSave)
                DataSaver.saveData(logs, "savelog");
        }
    }
}
Programmer
  • 104,912
  • 16
  • 182
  • 271
-2

If you want to understand better the code please see my tutorial: android files tutorial

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;


public class UtilsMath : MonoBehaviour
{
    private string gpsFilePath;
    private void Start()
    {
      gpsFilePath = Application.persistentDataPath + "/logFilesGPSUnity.txt";

      //if you want to empty the file every time the app starts,
      // only delete and create a new one.

      // if gps file exists
      if (File.Exists(gpsFilePath))
      {
        //delete file
        try
        {
            File.Delete(gpsFilePath);
            Debug.Log("[Utils Script]: GPS File Log Deleted Successfully!");
        }
        catch (System.Exception e)
        {
            Debug.LogError("[Utils Script]: Cannot delete GPS File Log - Exception: " + e);
        }
      }
  }


/// <summary>
/// <para> Writes the string message into the logFilesGPSUnity.txt in the internal storage\android\data\com.armis.arimarn\files\</para>
/// You need to write a '\n' in the end or beginning of each message, otherwise, the message will be printed in a row.
/// </summary>
/// <param name="message">String to print in the file</param>
  public void WriteToFile(string message)
  {
    try
    {
        //create the stream writer to the specific file
        StreamWriter fileWriter = new StreamWriter(gpsFilePath, true);

        //write the string into the file
        fileWriter.Write(message);

        // close the Stream Writer
        fileWriter.Close();
    }
    catch (System.Exception e)
    {
        Debug.LogError("[Utils Script]: Cannot write in the GPS File Log - Exception: " + e);
    }
  }
}
SHR
  • 7,149
  • 9
  • 32
  • 50
Joel Carneiro
  • 1,731
  • 3
  • 13
  • 18