Metin Dosyasına Android Yazma Günlükleri


129

Bu Benim Kodumu Kullanarak Android Dosyasındaki Özel Log.txt Dosyasına Günlük Yazmaya Çalışıyorum, ancak bu yöntem dosya oluşturuyor ancak hiçbir şey içermiyor. Temel olarak dosyanın önceki içeriğini okumak ve ardından verilerimi mevcut içerikle eklemek istiyorum.

Kod aşağıdaki gibidir:

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

Yanıtlar:


247

Umarım bu yardımcı olabilir ...

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

83
Manifest'e write_external_storage izni eklemeyi unutmayın!
virusss8

5
Buf.flush () eklemem gerekiyordu; ) (beforebuf.close; ama tjis işlevi tam olarak ihtiyacım olan şeydi. teşekkürler
Csabi

1
Bu işlevi nereden çağırmalıyım ki tüm uygulamanın oturum açma dosyasına yazsın ???
uniruddh

10
Kodu buf.close()bir finallybloğun içinde olacak şekilde yeniden yapılandırmanızı tavsiye ederim .
William Price

2
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />elbette virusss8'in kastettiği buydu.
Bengt

29

Genel olarak Java günlük kaydı ve Android günlük kaydı konusunda yeni olanlar için

  1. Log4j , java günlük kaydı uygulamasıdır ve artık Apache yazılım temelinin bir projesidir. Android'e özgü değildir ve bu nedenle Android ile bazı uyumsuzlukları vardır.
  2. SL4J, bir loglama uygulaması değildir, bir soyutlama katmanıdır. Log4j gibi kendi günlük uygulamalarını kullanmaya çalışırken, bir projeye her bir 3. taraf kitaplık bağımlılığı gibi durumlardan kaçınmaya yardımcı olur. Kaynak .

Android'de txt'ye giriş yapmak için bazı seçenekler aşağıdadır

  1. Dosyaya giriş yapmak için logcat -fbu yanıttaki gibi kullanın . Android 4.2'den itibaren READ_LOGS izninin herhangi bir etkisi olmadığını ve her Uygulamanın (telefon köklenmedikçe) yalnızca kendi günlüklerini okuyabileceğini unutmayın. Buradaki dezavantaj, logcat arabelleğinin dairesel olması ve bir boyut sınırına sahip olmasıdır. Daha önceki günlükleri alamayabilirsiniz.
  2. Önceki cevapta olduğu gibi microlog4android'i (Android gibi mobil cihazlar için yazılmıştır) kullanın . Bir yolu olabilir, ancak uygulama dahili depolamasına giriş yapmak için microlog4Android'in nasıl kullanılacağını anlayamadım. Günlük yolu için tek seçenek sdcard gibi harici depolamaydı ve bu yüzden kullanamadım.
  3. Log4j'yi android-logging-log4j ile kullanın . Android-logging-log4j ne yapar? İki işlev vererek Log4j'nin Android'de kullanımını kolaylaştırır.

    • günlük dosyasına ek olarak günlükleri logcat'e gönderme seçeneği
    • LogConfigurator sınıfı sağlayarak dosya yolu, maksimum dosya boyutu, yedekleme sayısı vb. gibi Log4j yapılandırma seçeneklerini ayarlamanın basit bir yolu.

    Aşağıdaki basit örnek. loggerAşağıdaki örnekteki nesnenin, android-logging-log4j sınıfı değil, döndürülen bir Log4j nesnesi olduğuna dikkat edin . Dolayısıyla android-logging-log4j yalnızca Log4j'yi yapılandırmak için kullanılır.

  4. Henüz LogBack'i denemek için . LogBack, Log4J 1.x ve SL4J kitaplıkları ile gelen aynı kişi tarafından geliştirilmiştir. Yine de Log4j 2.x ile ilgili değil.

Log4j'yi Android'de kullanma adımları.

  1. Her iki ekleme log4j-1.2.x.jar ve android-günlüğü-log4j-1.0.3.jar libs klasörüne.

  2. Yalnızca harici depolama kullanılıyorsa izin ekleyin
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

  3. Log4jYardımcı sınıf yazın

    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. Etkinlik sınıfında

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

Örnek Kaynak . Sıfırdan yeniden yazılan log4j 2.x'in (geliştirilmiş işlevler) log4j 1.x ile geriye dönük olarak uyumlu olmadığını unutmayın. Bu yüzden android-logging-log4j jar ile log4j 1.2.x jar kullanmanız gerekir. Uygulama dahili dosyasına giriş yapabildim ve daha sonra dosyayı e-posta ile gönderebildimsetReadable(true, false)


24

microlog4android benim için çalışıyor ancak dokümantasyon oldukça zayıf. Eklemeleri gereken tek şey, bu hızlı bir başlangıç eğitimidir .

İşte bulduğum hızlı bir öğretici.

  1. Aşağıdaki statik değişkeni ana Etkinliğinize ekleyin:

    private static final Logger logger = LoggerFactory.getLogger();
  2. Aşağıdakileri onCreate()yönteminize ekleyin :

    PropertyConfigurator.getConfigurator(this).configure();
  3. Adında bir dosya oluşturun microlog.propertiesve assetsdizinde saklayın

  4. Düzenleme microlog.propertiesdosya olarak aşağıdaki gibidir:

    microlog.level=DEBUG
    microlog.appender=LogCatAppender;FileAppender
    microlog.formatter=PatternFormatter
    microlog.formatter.PatternFormatter.pattern=%c [%P] %m %T
    
  5. Şunun gibi günlük kaydı ifadeleri ekleyin:

    logger.debug("M4A");

Her sınıf için, 1) 'de belirtildiği gibi bir günlükçü nesnesi oluşturursunuz.

6. Aşağıdaki izni ekleyebilirsiniz:

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

İşte öğretici için kaynak


4
FileAppender, sdcard'ınızda bir "microlog.txt" dosyası oluşturacaktır (benim durumumda tam yol "/sdcard/microlog.txt).
Ruslan Yanchyshyn

2
Bu hızlı eğitim, Microlog4Android resmi belgelerinin bir parçası olmalıdır.
Johan Karlsson

Hata: Android Dex: [proje] com.android.dex.DexException: Birden çok dex dosyası Lcom / google / code / microlog4android / Level; ?

10

Uyarı: Sizi tamamen yanlış anlıyor olabilirim, ancak tek istediğiniz bir günlük dosyasıysa, neden terlediniz?

Bunu bir yarasa dosyasına koyun (araçlar dizininizin yolunu değiştirin ve uygulama adınız elbette uygulamanızın adıdır):

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"

Sonra kodunuzda şuna benzer bir şey yapın:

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

Günlük oluşturmak için USB kablosunu bağlayın ve bat dosyanızı çalıştırın.

Saygılarımızla


Android.util.Log'u içe aktarmayı unutmayın.
Spidey

"Hata: birden fazla aygıt ve emülatör - aygıt bekleniyor -" döndürür ve başka bir şey yoktur. Bir sorun mu var?
eros

20
Uygulamayı çalıştırırken bir bilgisayarın yakınında değilseniz bu nasıl çalışır?
DDSports

@DDSports değil. Ama sorunun özünü anlamadı
Ewoks

@DDSports, adb'yi wifi üzerinden kullanabilirsiniz.
Daniel F

8

Slf4android lib kullanın . Android java.util.logging kullanarak slf4j api'nin
basit bir uygulamasıdır . *.

Özellikleri:

  • kutudan çıkmak için oturum açmak
  • başka bir hedefe giriş yaparak LoggerConfiguration.configuration().addHandlerToLogger
  • e-posta yoluyla günlükleri ekran görüntüsü ile göndermek için cihazınızı sallayın
  • gerçekten küçük, yalnızca ~ 55kB görünüyor

slf4android esas olarak @miensol tarafından sağlanmaktadır .

Blogumuzda slf4android hakkında daha fazla bilgi edinin:


7

Microlog4android'e bir göz atmalısınız. Bir dosyaya giriş yapmaya hazır bir çözümleri var.

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


12
Bu iyi bir kitaplık gibi görünüyor, ancak dokümantasyon korkunç. Nasıl çalıştıracağımı bilemedim ve kendim bir şeyler kurmaya başladım.
Paul Lammertsma

@PaulLammertsma: Bunun yerine Microlog4Android'e katkıda bulunmanız güzel olurdu. Bilginize: Log4j ile aynı API'ye sahiptir. Kötü dokümantasyon için özür dilerim.
Johan Karlsson

@Paul Lammertsma Kullanamayacağınız kadar kötü dokümantasyon varsa HERHANGİ BİR ŞEY nasıl iyi olabilir? Eğer onu çalıştıramazsan bu saçmalıktır.
inanılmaz

7

Bu geç olabilir, ancak bunun yardımcı olabileceğini umuyoruz .. Bunu deneyin ....

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

burada bfwritter.newlinemetninizi dosyaya yazar. Ve izni ekle

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

manifest dosyanızda hatasız.


6

Bu sorunu aşağıdaki kod parçasını komut satırı yoluyla çözdüm:

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

"Zaman" seçeneği, mesajı veren sürecin tarih, çağrı zamanı, öncelik / etiket ve PID'si için meta veri alanı ayrıntılarını ekler.

Ardından kodunuzda buna benzer bir şey yapın (android.util.Log kullanarak):

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

4
adbBağlandığında güzel çalışır , ancak cihaz bağımsız moddayken çalışmaz. Üretimde kullanmazdım ama hata ayıklama modunda basit bir çözüm.
Julien Kronegg

2

Genel olarak, akışı açmadan önce bir dosya tanıtıcınızın olması gerekir. Else bloğunda createNewFile () 'den önce bir fileOutputStream tutamacınız var . Akış, yoksa dosyayı oluşturmaz.

Gerçekten android'e özgü değil, ancak bu amaç için çok fazla IO. Ya arka arkaya birçok "yazma" işlemi yaparsanız? Tüm içeriği okuyacak ve tüm içeriği yazacak, zaman ayıracak ve daha da önemlisi pil ömrünü alacaksınız.

Ben java.io.RandomAccessFile kullanmayı, sonuna kadar seek () 'i kullanmanızı, ardından eklemek içinChars () yazmanızı öneririm. Daha temiz bir kod olacak ve muhtemelen çok daha hızlı olacak.


2

Dosya tabanlı günlük kaydı ile standart android.util.Log uygulamasını genişleten basit, hafif bir sınıf (yaklaşık 260 LoC) oluşturdum:
Her günlük mesajı android.util.Log aracılığıyla kaydedilir ve ayrıca cihazdaki bir metin dosyasına yazılır.

Bunu github'da bulabilirsiniz:
https://github.com/volkerv/FileLog


1
UI iş parçacığında dosya işlemlerinin yapılmamasını sağlamamız gerekmiyor mu? Büyük miktarda dosya günlüğü tutmamız durumunda mı?
Jayshil Dave

2

Uzun süren araştırmalardan sonra şunu buldum:

  • android.util.Log varsayılan olarak kullanım java.util.logging.Logger
  • LogCat, kullandığı örneğini almak için loggeradla ""birlikte kullanırLogManager.getLogManager().getLogger("")
  • Android Cihazlar , hata ayıklama uygulamaları çalıştırıldıktan sonra LogCat loggerörneğine eklercom.android.internal.logging.AndroidHandler
  • Fakat!!! ( ) gibi com.android.internal.logging.AndroidHandlerdüzeylerde yalnızca logcat'e mesaj yazdırırjava.util.logging.Level.INFOLevel.INFO, Level.WARNING, Level.SEVERE, Level.OFF

Bu nedenle, günlükleri dosyaya yazmak için rootLogger "" a 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
        }
    }
}

Uygulamanızdaki tüm kaydedicileri yazdırmak için şunu kullanın:

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

Selam. Bu "" kaydediciyi kullanmanın faydası nedir? Özel bir kaydedici ile hiçbir fark görmüyorum. veya bir şey mi kaçırıyorum?
Abins Shaji

1

Bu varyant çok daha kısadır

Deneyin {
    final Dosya yolu = yeni Dosya (
            Environment.getExternalStorageDirectory (), "DBO_logs5");
    eğer (! path.exists ()) {
        path.mkdir ();
    }
    Runtime.getRuntime (). Exec (
            "logcat -d -f" + yol + Dosya ayırıcı
                    + "dbo_logcat"
                    + ".txt");
} catch (IOException e) {
    e.printStackTrace ();
}

1

Yazdığım kütüphaneyi kullanabilirsiniz. Kullanımı çok kolay:

Bu bağımlılığı gradle dosyanıza ekleyin:

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

Uygulama sınıfındaki kitaplığı başlatın:

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
    }

Kitaplığı şu şekilde kullanıyorsunuz:

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

Ve günlükler şu şekilde alınır:

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

Daha fazla bilgi içeren github sayfasına bağlantı: https://github.com/danylovolokh/AndroidLogger

Umarım yardımcı olur.


1

Log4j'deki önceki sürümlerin çoğu artık çalışmıyor (05/2019). Ancak Hyperlog'u kullanabilirsiniz - Çalıştığını onaylayabilirim.

  1. Bu satırı bağımlılıklarınıza ekleyin ve projenizi senkronize edin

    implementation 'com.hypertrack:hyperlog:0.0.10'
  2. Yeni bir uygulama sınıfı oluşturun (yeni bir java sınıfı oluşturun ve Uygulamayı genişletin). Ardından onCreate yönteminde şu satırları ekleyin:

    HyperLog.initialize(this);
    HyperLog.setLogLevel(Log.VERBOSE);
    
    HyperLog.getDeviceLogsInFile(this);
  3. Uygulama dosyası tanımlanacak şekilde manifest dosyasını değiştirin.

    <application
        android:name=".AppClass"
        .....
  4. Günlüğe kaydetmenin farklı yolları:

    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. Günlük dosyalarınızı bulun. Şu yöne rotayı ayarla

    RootFolder/android/data/"appPackageName/LogFiles/

Bu kitaplığı HyperLog.getDeviceLogsInFile ile oluşturulan dosyada denedim (this); sadece son oluşturulan günlük var
mad_greasemonkey
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.