Using Timber, I wrote a FileTree logger that will write Android logs to files on the disk. I buffer the logs, flushing to disk every 2 minutes, or 100 log messages, whichever comes first. The buffer prevents each log message from triggering a IO write, so as to not overload the IO resources by immediately writing every single log message.
I'm using RxJava to handle this task. A short snippet (taken from here):
logBuffer.observeOn(Schedulers.computation())
    .doOnEach((log) -> {
        processed++;
        if(processed % 100 == 0) {
            flush();
        }
    })
    .buffer(flush.mergeWith(Observable.interval(2, TimeUnit.MINUTES)))
    .subscribeOn(Schedulers.io())
    .subscribe((logs) -> {
        // Flush the logs to the file
        try {
            File logFile = new File(logDir, "app.log");
            FileWriter fw = new FileWriter(logFile, true);
            for(LogMessage msg : logs) {
                fw.append(msg.toString());
            }
            fw.flush();
            flushCompleted.onNext(logFile.length());
        } catch(Exception e) {
            Timber.e(e, "Failed to flush logs");
        }
    });        
I use the "flush" subject if I need to trigger a flush manually.
I plant the FileTree in Timber within the Application's onCreate():
public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Timber.plant(new Timber.DebugTree(), new FileTree(getApplicationContext()));
    }
}
This is also where the subscriptions for RxJava are setup. I have two questions about this:
- If the application closes for some reason, presumably the log flush won't get triggered by a timer or by receiving enough log messages. Should I simply place a manual call to flush in every 
Activity'sonDestroy()function? Is there a better way to do this? - Secondly, 
RxJavacomplains that I ignore the result of ".subscribe()", presumably because I won't ever calldispose()on it. I'm not sure exactly how to handle this case. The subscriptions have the same lifecycle as the Application itself, so I'm not sure that removing it within a particularActivity'sonDestroywould make sense. Further, my app has several entry points (the main activity, a background service, and a few others) that all make use of the logging facilities, so when to unsubscribe/dispose theRxJavasubscriptions isn't clear. My intuition is that I don't need to dispose them because they will be cleared whenever the Application is removed by the operating system. Any ideas? 
                        
BaseActivity, or useApplication'sactivity state callbacks API ( https://developer.android.com/reference/android/app/Application#registerActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks) ).I should note that for the purposes of chosing a lifecycle method to flush, no method after
onPause()is guaranteed to be called by the OS. If the operating system needs to kill your app for low-memory, it's not guaranteed thatonDestroy()will be called ( rather it will just kill your process ).To quote https://developer.android.com/reference/android/app/Activity :