Androidによるテキストファイルへのログの書き込み


128

この鉱山のコードを使用してAndroidファイルのカスタムLog.txtファイルにログを書き込もうとしていますが、この方法ではファイルが作成されますが、何も含まれていません。基本的には、ファイルの以前の内容を読み取ってから、既存の内容にデータを追加します。

コードは次のとおりです。

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

回答:


247

これが役立つことを願っています...

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
Manifestにwriting_external_storageの権限を追加することを忘れないでください!
virusss8 2012年

5
buf.flush();を追加する必要がありました。beforebuf.close(); しかし、tjis関数はまさに私が必要としていたものでした。感謝
Csabi

1
すべてのアプリケーションのログをファイルに書き込むために、どこからこの関数を呼び出す必要がありますか?
uniruddh 2014

10
ブロックbuf.close()内にあるようにコードを再構築することをお勧めしfinallyます。
ウィリアムプライス

2
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />もちろん、@ virusss8の意味です。
Bengt

29

一般的なJavaロギングとAndroidロギングの初心者向け

  1. Log4jは一般的なJavaロギング実装であり、現在はApacheソフトウェア財団のプロジェクトです。Android固有ではないため、Androidとの非互換性があります。
  2. SL4Jはロギング実装ではなく、抽象化レイヤーです。Log4jのような独自のロギング実装を使用しようとする、プロジェクトへの各サードパーティライブラリの依存関係などの状況を回避するのに役立ちます。ソース

Androidでtxtにログを記録するためのいくつかのオプションは以下のとおりです

  1. logcat -fこの回答のように使用して、ファイルにログを記録します。Android 4.2以降、READ_LOGS権限は影響を与えず、すべてのアプリケーション(ルート権限がない場合を除く)は自身のログのみを読み取ることができました。ここでの欠点は、logcatバッファーが循環的であり、サイズ制限があることです。以前のログを取得できない場合があります。
  2. 使用microlog4android以前のように、(Androidのようなモバイルデバイス用に書かれた)の答え。方法はあるかもしれませんが、microlog4Androidを使用してアプリケーションの内部ストレージにログを記録する方法を理解できませんでした。ログパスの唯一のオプションはsdcardのような外部ストレージだったため、使用できませんでした。
  3. android-logging-log4jでLog4jを使用します。android-logging-log4jは何をしますか?2つの機能を提供することで、AndroidでLog4jを使いやすくします。

    • ログファイルに加えてログをlogcatに送信するオプション
    • LogConfiguratorクラスを提供することにより、ファイルパス、最大ファイルサイズ、バックアップ数などのLog4j構成オプションを設定する簡単な方法。

    以下の簡単な例。logger以下の例のオブジェクトは返されたLog4jオブジェクトであり、android-logging-log4jクラスではないことに注意してください。そのため、android-logging-log4jはLog4jの構成にのみ使用されます。

  4. まだLogBackを試してみてください。LogBackは、Log4J 1.xおよびSL4Jライブラリを思いついた人が開発しました。Log4j 2.xとは関係ありません。

AndroidでLog4jを使用するための手順。

  1. 両方の追加のlog4j-1.2.x.jarアンドロイド・ロギングにlog4j-1.0.3.jarを LIBSフォルダに。

  2. 外部ストレージを使用している場合にのみ権限を追加する
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

  3. Log4jヘルパークラスを書く

    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. アクティビティクラス

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

サンプルソース。ゼロから書き直されたlog4j 2.x(改善された機能)は、log4j 1.xとの下位互換性がないことに注意してください。したがって、android-logging-log4j jarでlog4j 1.2.x jarを使用する必要があります。アプリケーションの内部ファイルにログを記録し、後でファイルを電子メールで送信することができましたsetReadable(true, false)


24

microlog4androidは動作しますが、ドキュメントはかなり貧弱です。追加する必要があるのは、これがクイックスタートチュートリアルです。

これが私が見つけた簡単なチュートリアルです。

  1. メインアクティビティに次の静的変数を追加します。

    private static final Logger logger = LoggerFactory.getLogger();
  2. 以下をonCreate()メソッドに追加します。

    PropertyConfigurator.getConfigurator(this).configure();
  3. 名前のファイルを作成microlog.propertiesし、それを保存するassetsディレクトリ

  4. microlog.properties次のようにファイルを編集します。

    microlog.level=DEBUG
    microlog.appender=LogCatAppender;FileAppender
    microlog.formatter=PatternFormatter
    microlog.formatter.PatternFormatter.pattern=%c [%P] %m %T
    
  5. 次のようなロギングステートメントを追加します。

    logger.debug("M4A");

クラスごとに、1)で指定したようにロガーオブジェクトを作成します。

6.次の権限を追加する可能性があります。

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

これがチュートリアルのソースです


4
FileAppenderは、SDカードに「microlog.txt」というファイルを作成します(私の場合、フルパスは「/sdcard/microlog.txt」です)
Ruslan Yanchyshyn

2
このクイックチュートリアルは、Microlog4Android公式ドキュメントの一部である必要があります。
Johan Karlsson 2014

エラー:Android Dex:[プロジェクト] com.android.dex.DexException:複数のdexファイルがLcom / google / code / microlog4android / Levelを定義しています。?

10

警告:私はあなたを完全に誤解しているかもしれませんが、必要なのがログファイルだけなら、なぜ汗をかくのですか

これをbatファイルに入れます(ツールディレクトリへのパスを変更します。yourappnameはもちろんアプリの名前です):

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"

次に、コードで次のようなことを行います。

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

ログを作成するには、USBケーブルを接続し、batファイルを実行します。

よろしく


android.util.Logのインポートを忘れないでください。
Spidey

「エラー:複数のデバイスとエミュレータ-デバイスを待っています-」を返し、それ以上は返しません。何かおかしいですか?
エロス

20
アプリケーションの実行中にPCの近くにいない場合、これはどのように機能しますか?
DDSports 2014年

@DDSportsではありません。しかし、彼は質問の本質を理解していませんでした
Ewoks

@DDSportsは、wifi経由でadbを使用できます。
ダニエルF

8

slf4android libを使用します。
これは、android java.util.logging。*を使用したslf4j apiの単純な実装です。

特徴:

  • 箱から出してファイルにロギングする
  • 他の宛先へのロギング LoggerConfiguration.configuration().addHandlerToLogger
  • デバイスを振って、電子メールでスクリーンショット付きのログを送信します
  • 本当に小さい、それは〜55kBしかかかりません

slf4androidは主に@miensolによって管理されています

ブログでslf4androidの詳細をご覧ください。


7

microlog4androidをご覧ください。彼らはファイルにログを記録する準備ができているソリューションを持っています。

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


12
これは良いライブラリのようですが、ドキュメントはひどいものです。どうやってそれを機能させるかわからず、自分で何かを組み立てることになりました。
Paul Lammertsma、2011

@PaulLammertsma:代わりにMicrolog4Androidに寄稿していただければ幸いです。参考:APIはLog4jと同じです。悪いドキュメントについては申し訳ありません。
Johan Karlsson 2014

@Paul Lammertsmaドキュメンテーションがそれがあなたがそれを使うことができないほど悪いなら、何でも良いことがあり得ますか?あなたがそれを働かせることができないならば、それはがらくたです。
信じられない月

7

これは遅いかもしれませんが、これが役立つことを願っています。これを試してください...

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

ここでbfwritter.newlineは、テキストをファイルに書き込みます。許可を追加します

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

あなたのマニフェストファイルで必ず。


6

コマンドラインで次のコードを使用してこの問題を解決しました:

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

「時間」オプションは、メッセージを発行するプロセスの日付、呼び出し時間、優先度/タグ、およびPIDのメタデータフィールドの詳細を追加します。

次に、コードで次のようなことを行います(android.util.Logを使用)。

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

4
adbが接続されているときはうまく機能しますが、デバイスがスタンドアロンモードのときは機能しません。本番環境では使用しませんが、デバッグモードではシンプルなソリューションです。
ジュリアンクロネッグ

2

一般に、ストリームを開く前にファイルハンドルが必要です。elseブロックのcreateNewFile()の前に fileOutputStreamハンドルがあります。ファイルが存在しない場合、ストリームはファイルを作成しません。

実際にはAndroid固有ではありませんが、これはこの目的のための多くのIOです。多数の「書き込み」操作を次々に実行するとどうなるでしょうか。内容全体を読んだり内容全体を書き込んだりするのに時間がかかり、さらに重要なのはバッテリーの寿命です。

私はjava.io.RandomAccessFileを使用して最後までseek()し、次に追加するためにwriteChars()を使用することをお勧めします。はるかにクリーンなコードになり、おそらくはるかに速くなります。


2

ファイルベースのロギングで標準のandroid.util.Log実装を拡張するシンプルで軽量なクラス(約260 LoC)を作成しました。
すべてのログメッセージはandroid.util.Logを介してログに記録され、デバイスのテキストファイルにも書き込まれます。

あなたはそれをgithubで見つけることができます:https
//github.com/volkerv/FileLog


1
ファイル操作がUIスレッドで実行されないようにする必要があります。大量のファイルロギングがある場合は?
Jayshil Dave、2015

2

長い調査の結果、次のことがわかりました。

  • android.util.Log デフォルトで使用 java.util.logging.Logger
  • LogCatはloggernameとともに使用し""、それのインスタンスを取得しますLogManager.getLogManager().getLogger("")
  • Androidデバイスは、デバッグアプリの実行後のLogCat loggerインスタンスに追加されcom.android.internal.logging.AndroidHandlerます
  • だが!!!() などのcom.android.internal.logging.AndroidHandlerレベル以上のメッセージのみをlogcatに出力しますjava.util.logging.Level.INFOLevel.INFO, Level.WARNING, Level.SEVERE, Level.OFF

したがって、ログをファイルに書き込むにはrootLogger ""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
        }
    }
}

アプリですべてのロガーを印刷するには、以下を使用します。

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

こんにちは。この「」ロガーを使用する利点は何ですか。カスタムロガーとの違いはありません。または何か不足していますか?
アビンズシャジ

1

このバリアントははるかに短いです

{を試す
    最終ファイルパス=新しいファイル(
            Environment.getExternalStorageDirectory()、 "DBO_logs5");
    if(!path.exists()){
        path.mkdir();
    }
    Runtime.getRuntime()。exec(
            "logcat -d -f" +パス+ File.separator
                    + "dbo_logcat"
                    + ".txt");
}キャッチ(IOException e){
    e.printStackTrace();
}

1

私が書いたライブラリを使用できます。使い方はとても簡単です。

この依存関係をgradleファイルに追加してください:

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

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
    }

これは、ライブラリの使用方法です。

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

そして、これはログを取得する方法です:

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

詳細はこちらのgithubページへのリンクです:https : //github.com/danylovolokh/AndroidLogger

それが役に立てば幸い。


1

log4jの以前のバージョンの多くは現在機能しません(2019年5月)。しかし、Hyperlogを使用できます-動作することを確認できます。

  1. この行を依存関係に追加してプロジェクトを同期

    implementation 'com.hypertrack:hyperlog:0.0.10'
  2. 新しいアプリケーションクラスを作成します(新しいJavaクラスを作成し、Applicationを拡張します)。次に、onCreateメソッドに次の行を追加します。

    HyperLog.initialize(this);
    HyperLog.setLogLevel(Log.VERBOSE);
    
    HyperLog.getDeviceLogsInFile(this);
  3. マニフェストファイルを変更して、アプリケーションファイルを定義します。

    <application
        android:name=".AppClass"
        .....
  4. ログを記録するさまざまな方法:

    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. ログファイルを見つけます。案内する

    RootFolder/android/data/"appPackageName/LogFiles/

HyperLog.getDeviceLogsInFile(this);で生成されたファイルで、このライブラリを試しました。最後に生成されたログしかありません
mad_greasemonkey
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.