将日志输出同时记录到文件和系统日志中

时间:2019-02-26 14:22:13

标签: android logging

我正在尝试诊断我编写的应用程序中的问题。该问题是偶发性的,仅在实际情况下会发生:在现场,远离我的PC以及当我处于其他情况时,没有足够的资源可用于立即调试。因此,我最好的选择是收集和分析日志数据。

不幸的是,当我意识到问题再次出现并开始调试时,由于我经常同时运行其他聊天应用程序,因此任何日志数据已经从Android日志中移出。增大日志缓冲区的大小无济于事(Android对此不满意,或者其他应用仍然过于健谈),因此我放弃了这条路线。

基于这个原因,我现在考虑将我的应用程序日志记录到除常规日志之外的单独的文本文件中。

现在我可以轻松地将每个通话加倍

Log.i(TAG, "something happened");

添加另一个将相同内容写入日志文件的调用-但这对我来说似乎不太好。

另一种选择是用包装器替换对Log的所有调用,该包装器将事件写入Android日志和日志文件。

问题:Android API是否为此提供了内置机制,即告诉Log同时将其数据写入默认日志和文本文件?还是我需要自己编写代码?

编辑:

假设:

  • 我知道我需要在代码中的何处生成日志输出(可能发生在任何地方,可能涉及或可能不涉及异常),以及要写入日志的内容。
  • 从设备到PC的日志数据也不是问题(单人秀,我只是将手机插入PC并传输日志文件)。

如果您知道当前的Android API没有内置机制可以实现我想要的功能,那么“不,Android不支持此功能”是一个完全可以接受的答案。在那种情况下,解决方案很明确-我将回到包装函数。我特别不是在寻找解决此问题的其他方法。

2 个答案:

答案 0 :(得分:0)

您尚未指定是否引发某些异常,但是您无法处理。 以防万一,看看这个答案: Android Handling Unhandled Exception

如果必须查看一堆变量和对象,我建议两个选择:

  • 在文件上写入日志副本。发生问题时,只需要求用户将文件发送给您即可。这是对具有自我意识的用户进行测试时的理想选择。
  • 获取有关使用情况的统计信息,就像商业软件一样。只需记录用户操作并将数据发送到服务器(为此,您将需要一个)。这是进行远程日志记录的最透明的方法。

在将日志写入文件的情况下,您可以在内部存储器(应用程序的沙箱内部)或外部存储器(在这种情况下,需要写许可权,并且必须在运行时(如果您定位到Android 6及更高版本)。

答案 1 :(得分:0)

进行更多研究后,似乎Android API没有提供执行此操作的标准方法。有两种可能的解决方法:

在源镜像输出

  • System.outSystem.err输出写入台式机系统的控制台,并写入Android上的日志。可以将这两个重定向到您选择的任何PrintStream中,这将为您提供所有Java控制台输出。您可以将PrintStream子类化以复制其输入,将其输入到默认流以及您选择的文件中。
  • 创建一个类,该类公开与android.util.Log相同的方法。在每种方法中,调用各自的android.util.Log方法,并另外将数据记录到文件中。如果您调用类Log(但使用不同的包名称,例如org.example.Log),那么您要做的就是用类的导入替换android.util.Log的导入, Log方法调用将转到您的课程。

注意事项::这只会为您提供由代码明确记录的数据(即您拥有源文件的数据)以及进入System.out或{{1 }}。它不包括JAR库的日志输出(如果您不能修改其源代码),也不包括系统生成的任何输出(例如来自默认异常处理程序的堆栈跟踪)或其他进程(其中一些可能是系统进程和报告)与您的过程有关的条件。

从命令行读取日志

This article解释了如何从Android内部读取日志。简而言之:

  • Android在设备上包括一个名为System.err的命令行实用程序,它将为您连续提供日志消息,直到停止为止。 (通过logcat进入设备并运行它来进行尝试。它具有许多命令行选项来控制其行为。不过,不确定是否在所有发行版中都存在它。)
  • 通过adb shell启动此命令,然后获取返回的进程的输入流。这将为您提供日志消息的输入流。
  • 根据该文章,您的应用需要获得Runtime.getRuntime().exec("logcat")权限才能读取日志。

我已阅读声明,但某些版本的Android(提到了4.2)不允许将此权限授予非系统应用。根据我自己的测试,没有此权限的行为有所不同:Anbox将返回完整的logcat,而LineageOS(在15.1上进行测试)将仅显示来自调用它的应用程序的日志条目(包括以前的实例,大概是与同一Linux用户关联的所有内容) )。这可能是一个限制或欢迎过滤器功能。 YMMV。

android.permission.READ_LOGS方便地具有一个命令行选项logcat,用于指定输出文件。我尝试过

-f

和logcat在应用程序运行期间一直保持记录。杀死应用程序(通过单击Anbox标题栏中的X)显然也终止了子进程。

现在,您可以在应用启动时运行此代码,也可以将该功能转换为单独的应用,该应用在启动时启动并连续收集所有应用的日志。

注意事项::如果您正在运行一些健谈的应用程序,这可能会很快填满您的存储空间(这就是为什么条目首先迅速移出logcat的原因)。建议将日志镜像配置为可配置(例如通过首选项)和/或确保定期删除旧文件。另外,如果在您的应用终止之前使Runtime.getRuntime().exec("logcat -f " + absolutePathToLogFile); 进程一直运行,您将无法通过MTP访问该文件,因为没有简便的方法来运行媒体扫描器(如果您在文件扫描过程中仍在扫描文件,写入后,它将在MTP上被截断,直到运行另一个媒体扫描为止。