【问题标题】:Stream android logcat output to an sd card将 android logcat 输出流式传输到 sd 卡
【发布时间】:2011-08-07 01:38:35
【问题描述】:

我想实现以下目标,但到目前为止还没有成功

  • Android 应用程序首次启动时打开 SD 卡中的文件。
  • 将 logcat 输出流式传输到文件。
  • 当应用程序退出时,停止 logcat 流。

在我的 ApplicationClass extends Application onCreate() 方法中,我这样做了

wwLogManager.openLogFile();

这是 openLogFile() 中的代码

        private static final String LOGCAT_COMMAND = "logcat -v time -f ";
        String timestamp = Long.toString(System.currentTimeMillis());
        String logFileName = BuildConstants.LOG_LOCATION + "_" + timestamp + ".log";                    
        mLogFile = new File(Environment.getExternalStorageDirectory() + logFileName);
        mLogFile.createNewFile();
        String cmd = LOGCAT_COMMAND + mLogFile.getAbsolutePath();
        Runtime.getRuntime().exec(cmd);

我确实在 sd 卡中获得了日志文件,但这些文件中的日志输出没有我在活动中放置的 Log.i() 调用的任何痕迹。我在这里使用的 logcat 命令是否正确?谢谢!

【问题讨论】:

  • 您找到解决方案了吗?
  • 是的。我最终使用 BufferedReader 从 Runtime.getRuntime().exec(cmd) 读取输出。
  • 您能否在此处发布一个答案,以准确显示您所做的事情,为我和所有其他人的利益?
  • @JPM:请看我刚刚发布的答案...

标签: android file sd-card logcat


【解决方案1】:

如果我误解了您的目标,我深表歉意,但也许您可以使用 java.util.logging API 而不是使用 Logcat 或 Android Logging 机制。

与 Android 日志记录 API 一样,java.util.logging API 允许您轻松记录各种级别的消息,例如 FINE、FINER、WARN、SEVERE 等。

但标准的日志记录 API 也有额外的优势。例如,您可以使用FileHandler 轻松创建日志文件。事实上,FileHandler 具有内置的日志轮换机制,因此您不必(太多)担心清理日志文件。您还可以创建Loggers 的层次结构;因此,例如,如果您有两个Loggers,com.example.foocom.example.foo.bar,则更改前者的日志记录级别将还更改后者的日志记录级别。如果在不同的类中创建两个 Loggers,这甚至会起作用!此外,您可以通过指定日志记录配置文件在运行时更改日志记录行为。最后,你可以通过实现自己的Formatter来自定义日志的格式(或者直接使用SimpleFormatter来避免默认的XML格式)。

要使用标准的日志记录 API,您可以尝试以下方法:

    // Logger logger is an instance variable
    // FileHandler logHandler is an instance variable

    try {
        String logDirectory =
            Environment.getExternalStorageDirectory() + "/log_directory";

        // the %g is the number of the current log in the rotation
        String logFileName = logDirectory + "/logfile_base_name_%g.log";

        // ...
        // make sure that the log directory exists, or the next command will fail
        // 

        // create a log file at the specified location that is capped 100kB.  Keep up to 5 logs.
        logHandler = new FileHandler(logFileName, 100 * 1024, 5);
        // use a text-based format instead of the default XML-based format
        logHandler.setFormatter(new SimpleFormatter());
        // get the actual Logger
        logger = Logger.getLogger("com.example.foo");
        // Log to the file by associating the FileHandler with the log
        logger.addHandler(logHandler);
    }
    catch (IOException ioe) {
        // do something wise
    }

    // examples of using the logger
    logger.finest("This message is only logged at the finest level (lowest/most-verbose level)");
    logger.config("This is an config-level message (middle level)");
    logger.severe("This is a severe-level message (highest/least-verbose level)");

Android 的日志记录机制当然简单方便。但是,它不是很可定制,而且日志过滤必须使用标签来完成,这很容易变得笨拙。通过使用java.uitl.logging API,您可以避免处理大量标签,同时轻松地将日志文件限制在应用程序的特定部分,更好地控制日志的位置和外观,甚至在运行时自定义日志记录行为.

【讨论】:

  • 谢谢!我的目标是将 Android logcat 跟踪记录在一个文件中,这样我就可以跟踪与我的应用程序相关的事件。你知道 java.util.logging 是否会在其中包含 Android 堆栈跟踪。例如,当应用强制关闭时,是否会记录崩溃跟踪?
  • @Michael - 如果您的应用程序崩溃,那么它应该通过异常来实现。 java.util.logging 方法允许您记录异常。有关详细信息,请参阅Logger 方法。
  • 这不会减慢应用程序的速度吗?毕竟它只是一部安卓手机,而且资源有限。写入文件可能是一个代价高昂的过程。对吗?
  • @Enigma:是的,但是在需要记录长时间运行的操作的极端情况下,这个工具可能很有用。不过,我不认为我们一直都需要它。
【解决方案2】:

我在这里重新发布我的答案,以便@JPM 和其他人可以看到...代码基本上只是执行 logcat 命令,然后从输入流构建日志。

final StringBuilder log = new StringBuilder();
try {        
    ArrayList<String> commandLine = new ArrayList<String>();
    commandLine.add("logcat");
    commandLine.add("-d");
    ArrayList<String> arguments = ((params != null) && (params.length > 0)) ? params[0] : null;
    if (null != arguments){
        commandLine.addAll(arguments);
    }

    Process process = Runtime.getRuntime().exec(commandLine.toArray(new String[0]));
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));

    String line;
    while ((line = bufferedReader.readLine()) != null){ 
        log.append(line);
        log.append(LINE_SEPARATOR); 
    }
} 
catch (IOException e){
        //
} 

return log;

【讨论】:

    【解决方案3】:

    尝试按照此处所述手动设置过滤器: http://developer.android.com/guide/developing/debugging/debugging-log.html#filteringOutput

    类似:

    logcat ActivityManager:I MyApp:V *:S
    

    如果您将“MyApp”替换为您正在使用的日志标签,则应该会显示来自 ActivityManager 的所有信息(和更多)日志,以及来自您的应用的所有详细(和更多)日志。

    【讨论】:

    • 感谢过滤器的提示
    【解决方案4】:

    我知道这是对这个问题的迟到回答,但我强烈建议使用 Logback 将消息写入日志文件以及 logcat。

    1. logback-android-1.0.10-2.jarslf4j-api-1.7.5.jar 复制到您的libs 文件夹中。
    2. 右键单击两个库并从菜单中选择构建路径 -> 添加到构建路径。
    3. 在您的资产文件夹中创建一个 logback.xml 文件并输入以下内容:
    
    
      
    
      
      
        
          %msg
        
      
    
      
      
        
          WARN
        
    
        ${LOG_DIR}/log.txt
    
        
          %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
          
      
    
      
      
        
        
      
    
    1. 写日志:

      公共类 MyActivity 扩展了 Activity { public static final Logger logger = LoggerFactory.getLogger(MyActivity.class);

      protected void onCreate(Bundle b)
      {
          super(b);
          try{
              throw new Exception("Test");
          }catch(Exception e){
              logger.error("Something bad happened",e);
          }
      }
      

      }

    【讨论】:

    • 老实说,我无法正确格式化。但是点击编辑就可以看到代码了。
    猜你喜欢
    • 2011-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 2016-03-01
    • 2019-07-10
    相关资源
    最近更新 更多