Android Writing Logs no arquivo de texto


128

Estou tentando gravar logs no arquivo Log.txt personalizado no arquivo Android usando esse código meu, mas esse método cria um arquivo, mas não contém nada. Basicamente, quero ler o conteúdo anterior do arquivo e anexar meus dados ao conteúdo existente.

O código é o seguinte:

public static void write(String str) 
    {
        InputStream fileInputStream = null;
        FileOutputStream fileOutpurStream = null;
        try
        { 
            fileInputStream = new FileInputStream(file);
            fileOutpurStream = new FileOutputStream(file);
            if(file.exists())
            {
                int ch = 0;
                int current = 0;
                StringBuffer buffer = new StringBuffer();
                while((ch = fileInputStream.read()) != -1)
                {
                    buffer.append((char) ch);
                    current++;
                }
                byte data[]=new byte[(int)file.length()];
                fileInputStream.read(data);   
                fileOutpurStream.write(data);
                fileOutpurStream.write(str.getBytes(),0,str.getBytes().length);
                fileOutpurStream.flush();
            } 
            else
            {   
                file.createNewFile();
                fileOutpurStream.write(str.getBytes(),0,str.getBytes().length);
                fileOutpurStream.flush();
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                fileInputStream.close();
                fileOutpurStream.flush();
                fileOutpurStream.close();
                fileOutpurStream = null;
                fileInputStream = null;
            }
            catch (IOException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

Respostas:


247

Espero que isso possa ajudar ...

public void appendLog(String text)
{       
   File logFile = new File("sdcard/log.file");
   if (!logFile.exists())
   {
      try
      {
         logFile.createNewFile();
      } 
      catch (IOException e)
      {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }
   }
   try
   {
      //BufferedWriter for performance, true to set append to file flag
      BufferedWriter buf = new BufferedWriter(new FileWriter(logFile, true)); 
      buf.append(text);
      buf.newLine();
      buf.close();
   }
   catch (IOException e)
   {
      // TODO Auto-generated catch block
      e.printStackTrace();
   }
}

82
Não se esqueça de adicionar permissão para writing_external_storage no Manifest!
precisa saber é o seguinte

5
Eu precisava adicionar buf.flush (); beforebuf.close (); mas essa função era exatamente o que eu estava precisando. obrigado
Csabi 6/2

1
de onde devo chamar essa função para que ele escreva o arquivo de logon de todos os aplicativos ??
uniruddh

10
Eu recomendaria reestruturar o código para que buf.close()fique dentro de um finallybloco.
William Price

2
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />foi o que @ virusss8 significava, é claro.
Bengt

29

Para quem é iniciante no Java em geral e no Android

  1. O Log4j é uma implementação genérica de registro em java e agora é um projeto da fundação de software Apache. Não é específico do Android e, portanto, possui algumas incompatibilidades com o Android.
  2. O SL4J não é uma implementação de log, é uma camada de abstração. Isso ajuda a evitar situações como dependências de cada biblioteca de terceiros em um projeto, tentando usar sua própria implementação de log como o Log4j. Fonte .

Algumas opções para registrar no txt no Android estão abaixo

  1. Use logcat -fcomo neste resposta para fazer logon no arquivo. Observe que no Android 4.2, a permissão READ_LOGS não tem impacto e todos os aplicativos (a menos que o telefone esteja enraizado) só podiam ler seus próprios registros. A desvantagem aqui é que o buffer do logcat é circular e tem um limite de tamanho. Você pode não obter logs anteriores.
  2. Use microlog4android (escrito para dispositivos móveis como Android) como na resposta anterior . Poderia haver uma maneira, mas não consegui descobrir, como usar o microlog4Android para fazer logon no armazenamento interno do aplicativo. A única opção para o caminho dos logs era o armazenamento externo como sdcard e, portanto, não podia usá-lo.
  3. Use Log4j com android-logging-log4j . O que faz o android-logging-log4j? Isso torna o Log4j mais fácil de usar no Android, oferecendo duas funções.

    • opção para enviar logs para o logcat, além do arquivo de log
    • uma maneira simples de definir as opções de configuração do Log4j, como caminho do arquivo, tamanho máximo do arquivo, número de backups etc., fornecendo a classe LogConfigurator.

    Exemplo simples abaixo. Observe que o loggerobjeto no exemplo abaixo é um objeto Log4j retornado e não uma classe android-logging-log4j. Portanto, android-logging-log4j é usado apenas para configurar o Log4j.

  4. Ainda para experimentar o LogBack . O LogBack é desenvolvido pela mesma pessoa que criou as bibliotecas Log4J 1.xe SL4J. Porém, não relacionado ao Log4j 2.x.

Etapas para usar o Log4j no Android.

  1. Adicione log4j-1.2.x.jar e android-logging-log4j-1.0.3.jar à pasta libs.

  2. Adicione permissões apenas se estiver usando armazenamento externo
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

  3. Gravar Log4jclasse auxiliar

    package com.example.logger;
    
    import android.os.Environment;
    import de.mindpipe.android.logging.log4j.LogConfigurator;
    
    public class Log4jHelper {
        private final static LogConfigurator mLogConfigrator = new LogConfigurator();
    
        static {
            configureLog4j();
        }
    
        private static void configureLog4j() {
            String fileName = Environment.getExternalStorageDirectory() + "/" + "log4j.log";
            String filePattern = "%d - [%c] - %p : %m%n";
            int maxBackupSize = 10;
            long maxFileSize = 1024 * 1024;
    
            configure( fileName, filePattern, maxBackupSize, maxFileSize );
        }
    
        private static void configure( String fileName, String filePattern, int maxBackupSize, long maxFileSize ) {
            mLogConfigrator.setFileName( fileName );
            mLogConfigrator.setMaxFileSize( maxFileSize );
            mLogConfigrator.setFilePattern(filePattern);
            mLogConfigrator.setMaxBackupSize(maxBackupSize);
            mLogConfigrator.setUseLogCatAppender(true);
            mLogConfigrator.configure();
    
        }
    
        public static org.apache.log4j.Logger getLogger( String name ) {
            org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger( name );
            return logger;
        }
    }
  4. Na classe Activity

    org.apache.log4j.Logger log= Log4jHelper.getLogger( "YourActivity" );
    log.error("Error");
    log.info("Info");
    log.warn("Warn");

Fonte de exemplo . Observe que o log4j 2.x (funcionalidades aprimoradas) reescrito do zero não é compatível com o log4j 1.x. Então você precisa usar o jar log4j 1.2.x com o jar android-logging-log4j. Consegui fazer logon no arquivo interno do aplicativo e, posteriormente, enviá-lo por e-mail comsetReadable(true, false)


24

microlog4android funciona para mim, mas a documentação é muito pobre. Tudo o que eles precisam adicionar é um tutorial de início rápido .

Aqui está um rápido tutorial que encontrei.

  1. Adicione a seguinte variável estática na sua Atividade principal:

    private static final Logger logger = LoggerFactory.getLogger();
  2. Adicione o seguinte ao seu onCreate()método:

    PropertyConfigurator.getConfigurator(this).configure();
  3. Crie um arquivo nomeado microlog.propertiese armazene-o no assetsdiretório

  4. Edite o microlog.propertiesarquivo da seguinte maneira:

    microlog.level=DEBUG
    microlog.appender=LogCatAppender;FileAppender
    microlog.formatter=PatternFormatter
    microlog.formatter.PatternFormatter.pattern=%c [%P] %m %T
  5. Adicione instruções de log como esta:

    logger.debug("M4A");

Para cada classe, você cria um objeto de logger, conforme especificado em 1)

6.Você pode adicionar a seguinte permissão:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Aqui está a fonte do tutorial


4
FileAppender irá criar um arquivo "microlog.txt" em seu sdcard (caminho completo no meu caso é "/sdcard/microlog.txt).
Ruslan Yanchyshyn

2
Este tutorial rápido deve fazer parte da documentação oficial do Microlog4Android.
Johan Karlsson

Erro: Android Dex: [projeto] com.android.dex.DexException: vários arquivos dex definem Lcom / google / code / microlog4android / Level; ?

10

Aviso: Posso estar entendendo totalmente mal você, mas se tudo o que você quer é um arquivo de log, por que suar?

Coloque isso em um arquivo bat (altere o caminho para o diretório de ferramentas e yourappname é, obviamente, o nome do seu aplicativo):

cd "C:\devAndroid\Software\android-sdk-windows-1.6_r1\android-sdk-windows-1.6_r1\tools"
adb logcat -v time   ActivityManager:W  yourappname:D  *:W >"C:\devAndroid\log\yourappname.log"

Então, no seu código, faça algo semelhante a este:

Log.d("yourappname", "Your message");

Para criar o log, conecte o cabo USB e execute seu arquivo bat.

Saudações


Não se esqueça de importar o android.util.Log.
Spidey 26/05

Ele retorna "erro: mais de um dispositivo e emulador - aguardando dispositivo -" e nada mais. Tem algo errado?
Eros

20
Como isso funciona se você não está perto de um PC enquanto executa o aplicativo?
DDSports

@DDSports isso não acontece. Mas ele não entendeu a essência da questão
Ewoks

@DDSports você pode usar adb por wifi.
Daniel F

8

Use slf4android lib.
É simples implementação do slf4j api usando o Android java.util.logging. *.

Recursos:

  • registrando para arquivar fora da caixa
  • registrando em qualquer outro destino LoggerConfiguration.configuration().addHandlerToLogger
  • agite seu dispositivo para enviar logs com captura de tela por e-mail
  • muito pequeno, leva apenas ~ 55kB

slf4android é mantido principalmente por @miensol .

Leia mais sobre slf4android em nosso blog:


7

Você deve dar uma olhada no microlog4android. Eles têm uma solução pronta para fazer logon em um arquivo.

http://code.google.com/p/microlog4android/


12
Parece uma boa biblioteca, mas a documentação é terrível. Eu simplesmente não conseguia descobrir como fazê-lo funcionar e acabei montando algo sozinho.
Paul Lammertsma

@PaulLammertsma: Eu acho que seria bom você ter contribuído para o Microlog4Android. FYI: possui a mesma API do Log4j. Desculpe pela documentação ruim.
Johan Karlsson

@Paul Lammertsma Como QUALQUER COISA pode ser boa se a documentação é tão ruim que você não pode usá-la? Se você não consegue fazê-lo funcionar, é uma porcaria.
A incrível Jan

7

Isso pode ser tarde, mas espero que isso ajude. Tente isso ....

public void writefile()
    {
        File externalStorageDir = Environment.getExternalStorageDirectory();
        File myFile = new File(externalStorageDir , "yourfilename.txt");

        if(myFile.exists())
        {
           try
           {

        FileOutputStream fostream = new FileOutputStream(myFile);
        OutputStreamWriter oswriter = new OutputStreamWriter(fostream); 
        BufferedWriter bwriter = new BufferedWriter(oswriter);   
        bwriter.write("Hi welcome ");
        bwriter.newLine();            
        bwriter.close(); 
        oswriter.close(); 
        fostream.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
        else
        {
            try {
                myFile.createNewFile();
            }
            catch (IOException e) 
            {
                e.printStackTrace();
            }
        }

aqui bfwritter.newlineescreve seu texto no arquivo E adicione a permissão

 <uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE"/>

no seu arquivo de manifesto sem falha.


6

Resolvi esse problema com o seguinte trecho de código na linha de comando:

File outputFile = new File("pathToFile"); 
Runtime.getRuntime().exec("logcat -c");
Runtime.getRuntime().exec("logcat -v time -f " + outputFile.getAbsolutePath())

Onde a opção "hora" adiciona detalhes do campo de metadados para data, hora da chamada, prioridade / tag e PID do processo que emite a mensagem.

Em seguida, no seu código, faça algo semelhante a este (usando android.util.Log):

Log.d("yourappname", "Your message");

4
Funciona bem quando adbestá conectado, mas não funciona quando o dispositivo está no modo autônomo. Eu não o usaria na produção, mas é uma solução simples no modo de depuração.
Julien Kronegg

2

Em geral, você deve ter um identificador de arquivo antes de abrir o fluxo. Você tem um identificador fileOutputStream antes de createNewFile () no bloco else. O fluxo não cria o arquivo se ele não existir.

Não é realmente específico para o Android, mas é muito IO para esse fim. E se você fizer muitas operações de "gravação" uma após a outra? Você estará lendo todo o conteúdo e escrevendo o conteúdo inteiro, levando tempo e, mais importante, a duração da bateria.

Sugiro usar java.io.RandomAccessFile, seek () até o final e writeChars () para acrescentar. Será um código muito mais limpo e provavelmente muito mais rápido.


2

Eu criei uma classe simples e leve (cerca de 260 LoC) que estende a implementação padrão do android.util.Log com o log baseado em arquivo:
Toda mensagem de log é registrada via android.util.Log e também é gravada em um arquivo de texto no dispositivo.

Você pode encontrá-lo no github:
https://github.com/volkerv/FileLog


1
não acha que precisamos garantir que as operações do arquivo não sejam feitas no thread da interface do usuário. Caso tenhamos uma enorme quantidade de arquivos de log?
Jayshil Dave

2

Após muito tempo de investigação, descobri que:

  • android.util.Log por uso padrão java.util.logging.Logger
  • O LogCat usa loggercom nome "", para obter uma instância dele, useLogManager.getLogManager().getLogger("")
  • Os dispositivos Android são adicionados à loggerinstância do LogCat com.android.internal.logging.AndroidHandlerapós a execução dos aplicativos de depuração
  • Mas!!! com.android.internal.logging.AndroidHandlerimprime mensagens para logcat apenas com níveis mais altos que java.util.logging.Level.INFO, como ( Level.INFO, Level.WARNING, Level.SEVERE, Level.OFF)

Então, para escrever logs em um arquivo, basta rootLogger "" adicionar um java.util.logging.FileHandler:

  class App : Application{
    override fun onCreate() {
      super.onCreate()
      Log.d(TAG, printLoggers("before setup"))

      val rootLogger = java.util.logging.LogManager.getLogManager().getLogger("")
      val dirFile = destinationFolder
      val file = File(dirFile,"logFile.txt")
      val handler = java.util.logging.FileHandler(file.absolutePath, 5* 1024 * 1024/*5Mb*/, 1, true)
      handler.formatter = AndroidLogFormatter(filePath = file.absolutePath)

      rootLogger?.addHandler(handler)

      Log.d(TAG, printLoggers("after setup"))
    }
  }

val destinationFolder: File
        get() {
            val parent = 
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absoluteFile
            val destinationFolder = File(parent, "MyApp")
            if (!destinationFolder.exists()) {
                destinationFolder.mkdirs()
                destinationFolder.mkdir()
            }
            return destinationFolder
        }
class AndroidLogFormatter(val filePath: String = "", var tagPrefix: String = "") : Formatter() {

    override fun format(record: LogRecord): String {
        val tag = record.getTag(tagPrefix)
        val date = record.getDate()
        val level = record.getLogCatLevel()
        val message = record.getLogCatMessage()
        return "$date $level$tag: $message\n"
    }
}

fun LogRecord.getTag(tagPrefix: String): String {
    val name = loggerName
    val maxLength = 30
    val tag = tagPrefix + (if (name.length > maxLength) name.substring(name.length - maxLength) else name)
    return tag
}

fun LogRecord.getDate(): String? {
    return Date(millis).formatedBy("yyyy-MM-dd HH:mm:ss.SSS")
}

fun Date?.formatedBy(dateFormat: String): String? {
    val date = this
    date ?: return null
    val writeFormat = SimpleDateFormat(dateFormat, Locale.getDefault()) //MM в HH:mm
    return writeFormat.format(date)
}

fun LogRecord.getLogCatMessage(): String {
    var message = message

    if (thrown != null) {
        message += Log.getStackTraceString(thrown)
    }
    return message
}

fun Int.getAndroidLevel(): Int {
    return when {
        this >= Level.SEVERE.intValue() -> { // SEVERE
            Log.ERROR
        }
        this >= Level.WARNING.intValue() -> { // WARNING
            Log.WARN
        }
        this >= Level.INFO.intValue() -> { // INFO
            Log.INFO
        }
        else -> {
            Log.DEBUG
        }
    }
}

fun LogRecord.getLogCatLevel(): String {
    return when (level.intValue().getAndroidLevel()) {
        Log.ERROR -> { // SEVERE
            "E/"
        }
        Log.WARN -> { // WARNING
            "W/"
        }
        Log.INFO -> { // INFO
            "I/"
        }
        Log.DEBUG -> {
            "D/"
        }
        else -> {
            "D/"
        }
    }
}

fun getLoggerLevel(level: Int): Level {
    return when (level) {
        Log.ERROR -> { // SEVERE
            Level.SEVERE
        }
        Log.WARN -> { // WARNING
            Level.WARNING
        }
        Log.INFO -> { // INFO
            Level.INFO
        }
        Log.DEBUG -> {
            Level.FINE
        }
        else -> {
            Level.FINEST
        }
    }
}

Para imprimir todos os registradores no seu aplicativo, use:

Log.e(TAG, printLoggers("before setup"))

 private fun printLoggers(caller: String, printIfEmpty: Boolean = true): String {
        val builder = StringBuilder()
        val loggerNames = LogManager.getLogManager().loggerNames
        builder.appendln("--------------------------------------------------------------")
        builder.appendln("printLoggers: $caller")
        while (loggerNames.hasMoreElements()) {
            val element = loggerNames.nextElement()
            val logger = LogManager.getLogManager().getLogger(element)
            val parentLogger: Logger? = logger.parent
            val handlers = logger.handlers
            val level = logger?.level
            if (!printIfEmpty && handlers.isEmpty()) {
                continue
            }
            val handlersNames = handlers.map {
                val handlerName = it.javaClass.simpleName
                val formatter: Formatter? = it.formatter
                val formatterName = if (formatter is AndroidLogFormatter) {
                    "${formatter.javaClass.simpleName}(${formatter.filePath})"
                } else {
                    formatter?.javaClass?.simpleName
                }
                "$handlerName($formatterName)"
            }
            builder.appendln("level: $level logger: \"$element\" handlers: $handlersNames parentLogger: ${parentLogger?.name}")
        }
        builder.appendln("--------------------------------------------------------------")
        return builder.toString()
    }

Oi. Qual é o benefício usando este "" logger. Não vejo diferença com um criador de logs personalizado. Ou eu estou esquecendo de alguma coisa ?
Abins Shaji

1

Esta variante é muito mais curta

experimentar {
    caminho final do arquivo = novo arquivo (
            Environment.getExternalStorageDirectory (), "DBO_logs5");
    if (! path.exists ()) {
        path.mkdir ();
    }
    Runtime.getRuntime (). Exec (
            "logcat -d -f" + caminho + File.separator
                    + "dbo_logcat"
                    + ".txt");
} captura (IOException e) {
    e.printStackTrace ();
}

1

Você pode usar a biblioteca que escrevi. É muito fácil de usar:

Adicione esta dependência ao seu arquivo gradle:

dependencies {
    compile 'com.github.danylovolokh:android-logger:1.0.2'
}

Inicialize a biblioteca na classe Application:

File logsDirectory = AndroidLogger.getDefaultLogFilesDirectory(this);
    int logFileMaxSizeBytes = 2 * 1024 * 1024; // 2Mb
    try {
        AndroidLogger.initialize(
                this,
                logsDirectory,
                "Log_File_Name",
                logFileMaxSizeBytes,
                false
                );
    } catch (IOException e) {
        // Some error happened - most likely there is no free space on the system
    }

É assim que você usa a biblioteca:

AndroidLogger.v("TAG", "Verbose Message");

E é assim que recuperar os logs:

AndroidLogger.processPendingLogsStopAndGetLogFiles(new AndroidLogger.GetFilesCallback() {
        @Override
        public void onFiles(File[] logFiles) {
            // get everything you need from these files
            try {
                AndroidLogger.reinitAndroidLogger();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });

Aqui está o link para a página do github com mais informações: https://github.com/danylovolokh/AndroidLogger

Espero que ajude.


1

Muitas das versões anteriores do log4j não funcionam agora (05/2019). Mas você pode usar o Hyperlog - posso confirmar que funciona.

  1. Adicione esta linha ao seu projeto de dependências e sincronização

    implementation 'com.hypertrack:hyperlog:0.0.10'
  2. Crie uma nova classe de aplicativo (crie uma nova classe java e estenda o aplicativo). Em seguida, no método onCreate, adicione estas linhas:

    HyperLog.initialize(this);
    HyperLog.setLogLevel(Log.VERBOSE);
    
    HyperLog.getDeviceLogsInFile(this);
  3. Altere o arquivo de manifesto para definir o arquivo do aplicativo.

    <application
        android:name=".AppClass"
        .....
  4. Maneiras diferentes de registrar:

    HyperLog.d(TAG,"debug");
    HyperLog.i(TAG,"information");
    HyperLog.e(TAG,"error");
    HyperLog.v(TAG,"verbose");
    HyperLog.w(TAG,"warning");
    HyperLog.a(TAG,"assert");
    HyperLog.exception(TAG,"exception",throwable);
  5. Encontre seus arquivos de log. Navegar para

    RootFolder/android/data/"appPackageName/LogFiles/

Eu tentei esta biblioteca, no arquivo gerado com HyperLog.getDeviceLogsInFile (this); apenas o último log gerado existe
mad_greasemonkey 14/11/19
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.