Scrittura Android Registra su file di testo


128

Sto cercando di scrivere registri nel file Log.txt personalizzato su file Android utilizzando questo codice mio, ma questo metodo crea file ma non contiene nulla. Fondamentalmente voglio leggere i contenuti precedenti del file e quindi aggiungere i miei dati con il contenuto esistente.

Il codice è il seguente:

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();
            }
        }

Risposte:


247

Spero che questo possa aiutare ...

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
Non dimenticare di aggiungere l'autorizzazione per writing_external_storage in Manifest!
virusss8,

5
Avevo bisogno di aggiungere buf.flush (); beforebuf.close (); ma la funzione tjis era esattamente ciò di cui avevo bisogno. grazie
Csabi,

1
da dove dovrei chiamare questa funzione in modo che scriva tutti i file di accesso dell'applicazione ???
uniruddh,

10
Consiglierei di ristrutturare il codice in modo che buf.close()si trovi all'interno di un finallyblocco.
William Price,

2
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />era quello che intendeva @ virusss8, ovviamente.
Bengt,

29

Per coloro che non conoscono la registrazione Java in generale e la registrazione Android

  1. Log4j è un'implementazione di registrazione java generica ed è ora un progetto della base software Apache. Non è specifico di Android e quindi ha alcune incompatibilità con Android.
  2. SL4J non è un'implementazione di registrazione, è un livello di astrazione. Aiuta a evitare situazioni come ogni dipendenza da una libreria di terze parti da un progetto, cercando di utilizzare la propria implementazione di registrazione come Log4j. Fonte .

Di seguito sono riportate alcune opzioni per accedere a txt in Android

  1. Utilizzare logcat -fcome in questa risposta per accedere al file. Da Android 4.2, l'autorizzazione READ_LOGS non ha alcun impatto e ogni applicazione (a meno che il telefono non sia rootato) potrebbe solo leggere i propri registri. Lo svantaggio qui è che il buffer logcat è circolare e ha un limite di dimensioni. Potresti non avere registri precedenti.
  2. Usa microlog4android (scritto per dispositivi mobili come Android) come nella risposta precedente . Potrebbe esserci un modo, ma non riesco a capire come usare microlog4Android per accedere alla memoria interna dell'applicazione. L'unica opzione per il percorso dei registri era l'archiviazione esterna come sdcard e quindi non potevo usarla.
  3. Usa Log4j con android-logging-log4j . Cosa fa android-logging-log4j? Rende Log4j più facile da usare in Android offrendo due funzioni.

    • opzione per inviare registri a logcat oltre al file di registrazione
    • un modo semplice per impostare le opzioni di configurazione di Log4j come percorso del file, dimensione massima del file, numero di backup ecc. fornendo la classe LogConfigurator.

    Semplice esempio di seguito. Si noti che l' loggeroggetto nell'esempio seguente è un oggetto Log4j restituito e non una classe android-logging-log4j. Quindi android-logging-log4j viene utilizzato solo per configurare Log4j.

  4. Ancora per provare LogBack . LogBack è sviluppato dalla stessa persona che ha creato le librerie Log4J 1.xe SL4J. Tuttavia, non è correlato a Log4j 2.x.

Passaggi per l'utilizzo di Log4j in Android.

  1. Aggiungi sia log4j-1.2.x.jar che android-logging-log4j-1.0.3.jar nella cartella libs.

  2. Aggiungi autorizzazioni solo se si utilizza l'archiviazione esterna
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

  3. Scrivi Log4jclasse di aiuto

    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. Nella classe di attività

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

Fonte di esempio . Notare che log4j 2.x (funzionalità migliorate) riscritte da zero non è confrontabile con log4j 1.x. Quindi devi usare il vaso log4j 1.2.x con il vaso android-logging-log4j. Sono stato in grado di accedere al file interno dell'applicazione e successivamente inviare il file tramite e-mailsetReadable(true, false)


24

microlog4android funziona per me, ma la documentazione è piuttosto scadente. Tutto quello che devono aggiungere è un tutorial di avvio rapido .

Ecco un breve tutorial che ho trovato.

  1. Aggiungi la seguente variabile statica nella tua attività principale:

    private static final Logger logger = LoggerFactory.getLogger();
  2. Aggiungi quanto segue al tuo onCreate()metodo:

    PropertyConfigurator.getConfigurator(this).configure();
  3. Creare un file denominato microlog.propertiese memorizzarlo nella assetsdirectory

  4. Modifica il microlog.propertiesfile come segue:

    microlog.level=DEBUG
    microlog.appender=LogCatAppender;FileAppender
    microlog.formatter=PatternFormatter
    microlog.formatter.PatternFormatter.pattern=%c [%P] %m %T
  5. Aggiungi istruzioni di registrazione in questo modo:

    logger.debug("M4A");

Per ogni classe si crea un oggetto logger come specificato in 1)

6.Puoi essere aggiunto il seguente permesso:

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

Ecco la fonte per il tutorial


4
FileAppender creerà un file "microlog.txt" sulla tua sdcard (il percorso completo nel mio caso è "/sdcard/microlog.txt).
Ruslan Yanchyshyn,

2
Questo breve tutorial dovrebbe far parte della documentazione ufficiale di Microlog4Android.
Johan Karlsson,

Errore: Android Dex: [progetto] com.android.dex.DexException: più file dex definiscono Lcom / google / code / microlog4android / Level; ?

10

Avvertenza: potrei fraintenderti totalmente, ma se tutto ciò che vuoi è un file di registro, perché sudare?

Mettilo in un file bat (cambia il percorso nella directory degli strumenti e yourappname è ovviamente il nome della tua app):

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"

Quindi nel tuo codice fai qualcosa di simile a questo:

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

Per creare il registro, collegare il cavo USB ed eseguire il file bat.

Saluti


Non dimenticare di importare android.util.Log.
Spidey,

Restituisce "errore: più di un dispositivo ed emulatore - in attesa del dispositivo -" e niente di più. Hai qualcosa di sbagliato?
eros,

20
Come funziona se non sei vicino a un PC mentre esegui l'applicazione?
DDSports

@DDSports no. Ma non capiva l'essenza della domanda
Ewoks,

@DDSports è possibile utilizzare adb tramite wifi.
Daniel F,

8

Usa la libreria slf4android .
È una semplice implementazione di slf4j api utilizzando Android java.util.logging. *.

Caratteristiche:

  • accedendo al file fuori dalla scatola
  • accedendo a qualsiasi altra destinazione entro LoggerConfiguration.configuration().addHandlerToLogger
  • scuoti il ​​dispositivo per inviare i registri con screenshot via e-mail
  • veramente piccolo, ci sono voluti solo ~ 55kB

slf4android è gestito principalmente da @miensol .

Maggiori informazioni su slf4android sul nostro blog:


7

Dovresti dare un'occhiata a microlog4android. Hanno una soluzione pronta per accedere a un file.

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


12
Sembra una buona biblioteca, ma la documentazione è terribile. Semplicemente non riuscivo a capire come farlo funzionare e ho finito per mettere insieme qualcosa da solo.
Paul Lammertsma,

@PaulLammertsma: penso che sarebbe bello che tu abbia contribuito a Microlog4Android. Cordiali saluti: ha la stessa API di Log4j. Mi dispiace per la cattiva documentazione.
Johan Karlsson,

@Paul Lammertsma In che modo QUALCOSA potrebbe essere buono se la sua documentazione è così grave che non puoi usarla? Se non riesci a farlo funzionare è una schifezza.
L'incredibile

7

Potrebbe essere tardi, ma spero che questo possa essere d'aiuto .. Prova questo

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();
            }
        }

qui bfwritter.newlinescrive il testo nel file. E aggiungi l'autorizzazione

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

nel tuo file manifest a colpo sicuro.


6

Ho risolto questo problema con il seguente pezzo di codice in modo da riga di comando:

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

Dove l'opzione "time" aggiunge i dettagli del campo metadati per data, ora di invocazione, priorità / tag e PID del processo che emette il messaggio.

Quindi nel tuo codice fai qualcosa di simile a questo (usando android.util.Log):

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

4
Funziona bene quando adbè collegato, ma non funziona quando il dispositivo è in modalità autonoma. Non lo userei in produzione, ma è una soluzione semplice in modalità debug.
Julien Kronegg,

2

In generale, è necessario disporre di un handle di file prima di aprire il flusso. Hai un handle di fileOutputStream prima di createNewFile () nel blocco else. Lo stream non crea il file se non esiste.

Non proprio specifico per Android, ma questo è molto IO per questo scopo. Cosa succede se si eseguono molte operazioni di "scrittura" una dopo l'altra? Leggerai l'intero contenuto e scriverai l'intero contenuto, prendendo tempo e, soprattutto, la durata della batteria.

Suggerisco di usare java.io.RandomAccessFile, seek () 'fino alla fine, quindi writeChars () da aggiungere. Sarà un codice molto più pulito e probabilmente molto più veloce.


2

Ho creato una classe semplice e leggera (circa 260 LoC) che estende l'implementazione standard di android.util.Log con registrazione basata su file:
ogni messaggio di registro viene registrato tramite android.util.Log e anche scritto in un file di testo sul dispositivo.

Puoi trovarlo su github:
https://github.com/volkerv/FileLog


1
non ti serve che ci assicuriamo che le operazioni sui file non vengano eseguite sul thread dell'interfaccia utente. Nel caso in cui abbiamo una grande quantità di registrazione dei file?
Jayshil Dave,

2

Dopo un lungo periodo di indagini ho scoperto che:

  • android.util.Log per impostazione predefinita java.util.logging.Logger
  • LogCat utilizza loggercon il nome "", per ottenerne l'istanzaLogManager.getLogManager().getLogger("")
  • I dispositivi Android aggiungono loggerall'istanza LogCat com.android.internal.logging.AndroidHandlerdelle app di debug post-esecuzione
  • Ma!!! com.android.internal.logging.AndroidHandlerstampa i messaggi su logcat solo con livelli superiori java.util.logging.Level.INFOa ( Level.INFO, Level.WARNING, Level.SEVERE, Level.OFF)

Quindi, per scrivere i registri su file, è semplice rootLogger "" aggiungere un 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
        }
    }
}

Per stampare tutti i logger sulla tua app usa:

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()
    }

Ciao. Qual è il vantaggio di utilizzare questo "" logger. Non vedo alcuna differenza con un logger personalizzato. Oppure mi sfugge qualcosa ?
Abins Shaji,

1

Questa variante è molto più breve

provare {
    percorso file finale = nuovo file (
            Environment.getExternalStorageDirectory (), "DBO_logs5");
    if (! path.exists ()) {
        path.mkdir ();
    }
    Runtime.getRuntime (). Exec (
            "logcat -d -f" + percorso + File.separator
                    + "dbo_logcat"
                    + ".txt");
} catch (IOException e) {
    e.printStackTrace ();
}

1

Puoi usare la biblioteca che ho scritto. È molto facile da usare:

Aggiungi questa dipendenza al tuo file gradle:

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

Inizializza la libreria nella 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
    }

Ecco come si utilizza la libreria:

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

E questo è come recuperare i registri:

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();
            }
        }
    });

Ecco il link alla pagina di github con maggiori informazioni: https://github.com/danylovolokh/AndroidLogger

Spero che sia d'aiuto.


1

Molte delle versioni precedenti su log4j non funzionano ora (05/2019). Ma puoi usare Hyperlog - posso confermare che funziona.

  1. Aggiungi questa linea alle dipendenze e sincronizza il progetto

    implementation 'com.hypertrack:hyperlog:0.0.10'
  2. Creare una nuova classe di applicazione (creare una nuova classe Java ed estendere l'applicazione). Quindi nel metodo onCreate aggiungi queste righe:

    HyperLog.initialize(this);
    HyperLog.setLogLevel(Log.VERBOSE);
    
    HyperLog.getDeviceLogsInFile(this);
  3. Modificare il file manifest per definire il file dell'applicazione.

    <application
        android:name=".AppClass"
        .....
  4. Diversi modi per accedere:

    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. Trova i tuoi file di registro. Navigare verso

    RootFolder/android/data/"appPackageName/LogFiles/

Ho provato questa libreria, nel file generato con HyperLog.getDeviceLogsInFile (questo); è presente solo l'ultimo registro generato
mad_greasemonkey,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.