Reputation: 3004
I'm Trying to Write Logs to Custom Log.txt File on Android File using this code of Mine but then this method creates file but contains nothing. Basically I want to read previous contents of the file and then append my data with the existing content.
The Code is as follows :
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();
}
}
Upvotes: 151
Views: 248960
Reputation: 1209
More short version.
public static void AppendLog( Context context, String text){
File path = context.getExternalFilesDir( "" );
File logFile = new File( path, "log.txt" );
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss_SSS | ");
String log_line = formatter.format( new java.util.Date() ) + text ;
try{
BufferedWriter buf = new BufferedWriter( new FileWriter(logFile, true));
buf.append( log_line );
buf.newLine();
buf.close();
}catch (IOException e){
}
}
There is no permission needed. Path to log file: "Android/data/PACKAGE_NAME/files"
.
Upvotes: 2
Reputation: 67
File logFile = new File(filename);
try {
Process process = Runtime.getRuntime().exec("logcat AndroidRuntime:E *:S
-f " + logFile);
}
catch ( Exception e )
{ Basic.Logger("Error Basic", "error "+e); }
try this code for Writing Error Log in File
Upvotes: -1
Reputation: 12847
After long time of investigation I found that:
android.util.Log
by default use java.util.logging.Logger
logger
with name ""
, to get instance of it use LogManager.getLogManager().getLogger("")
logger
instance of com.android.internal.logging.AndroidHandler
after run of debug appscom.android.internal.logging.AndroidHandler
prints messages to logcat only with levels more then java.util.logging.Level.INFO
such as (Level.INFO, Level.WARNING, Level.SEVERE, Level.OFF
) So to write logs to file just simple to the rootLogger
""
add 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
}
}
}
To print all loggers at your app 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()
}
Upvotes: 8
Reputation: 1771
Many of the previous versions on log4j dont work now (05/2019). But you can use Hyperlog - I can confirm it works.
Add this line to your dependencies & sync project
implementation 'com.hypertrack:hyperlog:0.0.10'
Create a new application class (create a new java class and extend Application). Then in the onCreate method add these lines:
HyperLog.initialize(this);
HyperLog.setLogLevel(Log.VERBOSE);
HyperLog.getDeviceLogsInFile(this);
Change manifest file to have application file defined.
<application
android:name=".AppClass"
.....
Different ways to log:
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);
Find your log files. Navigate to
RootFolder/android/data/"appPackageName/LogFiles/
Upvotes: 0
Reputation: 241
I solved this problem with following piece of code in command line way:
File outputFile = new File("pathToFile");
Runtime.getRuntime().exec("logcat -c");
Runtime.getRuntime().exec("logcat -v time -f " + outputFile.getAbsolutePath())
Where "time" option adds metadata field details for date, invocation time, priority/tag, and PID of the process issuing the message.
Then in your code just do something similar to this (using android.util.Log):
Log.d("yourappname", "Your message");
Upvotes: 8
Reputation: 4285
You can use the library I've written. It's very easy to use:
Add this dependency to your gradle file:
dependencies {
compile 'com.github.danylovolokh:android-logger:1.0.2'
}
Initialize the library in the Application class:
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
}
This is how you use the library:
AndroidLogger.v("TAG", "Verbose Message");
And this is how to retrieve the 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();
}
}
});
Here is the link to the github page with more information: https://github.com/danylovolokh/AndroidLogger
Hope it helps.
Upvotes: 2
Reputation: 24991
Use slf4android lib.
It's simple implementation of slf4j api using android java.util.logging.*.
Features:
LoggerConfiguration.configuration().addHandlerToLogger
slf4android is maintained mainly by @miensol.
Read more about slf4android on our blog:
Upvotes: 8
Reputation: 394
microlog4android works for me but the documentation is pretty poor. All they need to add is a this is a quick start tutorial.
Here is a quick tutorial I found.
Add the following static variable in your main Activity:
private static final Logger logger = LoggerFactory.getLogger();
Add the following to your onCreate()
method:
PropertyConfigurator.getConfigurator(this).configure();
Create a file named microlog.properties
and store it in assets
directory
Edit the microlog.properties
file as follows:
microlog.level=DEBUG
microlog.appender=LogCatAppender;FileAppender
microlog.formatter=PatternFormatter
microlog.formatter.PatternFormatter.pattern=%c [%P] %m %T
Add logging statements like this:
logger.debug("M4A");
For each class you create a logger object as specified in 1)
6.You may be add the following permission:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Here is the source for tutorial
Upvotes: 26
Reputation: 11201
For those new to Java logging in general and Android logging
Some options for logging to txt in Android are below
logcat -f
as in this answer to log to file. Note that from
Android 4.2, READ_LOGS permission doesn't have any impact and every
Application (unless phone is rooted) could only read its own logs.
The disadvantage here is logcat buffer is circular and has a size
limit. You might not get earlier logs.Use Log4j with android-logging-log4j. What does android-logging-log4j do ? It makes Log4j easier to use in Android by giving two functions.
Simple example below. Notice that logger
object in below example is a Log4j object returned and not an android-logging-log4j class. So android-logging-log4j is used only for configuring Log4j.
Steps for using Log4j in Android.
Add both log4j-1.2.x.jar and android-logging-log4j-1.0.3.jar to the libs folder.
Add permissions only if using external storage
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Write Log4j
helper class
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;
}
}
In Activity class
org.apache.log4j.Logger log= Log4jHelper.getLogger( "YourActivity" );
log.error("Error");
log.info("Info");
log.warn("Warn");
Example Source. Note that, log4j 2.x ( improved functionalities ) rewritten from scratch is not backward comptible with log4j 1.x. So you have to use log4j 1.2.x jar with android-logging-log4j jar. I was able to log to application internal file and later email the file with setReadable(true, false)
Upvotes: 34
Reputation: 1252
This variant is much shorter
try { final File path = new File( Environment.getExternalStorageDirectory(), "DBO_logs5"); if (!path.exists()) { path.mkdir(); } Runtime.getRuntime().exec( "logcat -d -f " + path + File.separator + "dbo_logcat" + ".txt"); } catch (IOException e) { e.printStackTrace(); }
Upvotes: 1
Reputation: 5563
I have created a simple, lightweight class (about 260 LoC) that extends the standard android.util.Log implementation with file based logging:
Every log message is logged via android.util.Log and also written to a text file on the device.
You can find it on github:
https://github.com/volkerv/FileLog
Upvotes: 3
Reputation: 1449
This may be late but hope this may help.. Try this....
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();
}
}
here bfwritter.newline
writes your text into the file. And add the permission
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE"/>
in your manifest file without fail.
Upvotes: 7
Reputation: 3354
Hope this can help...
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();
}
}
Upvotes: 275
Reputation: 4987
You should take a look at microlog4android. They have a solution ready to log to a file.
http://code.google.com/p/microlog4android/
Upvotes: 7
Reputation: 618
Warning: I may be totally misunderstanding you, but if all you want is a log file, why sweat?
Put this in a bat file (change the path to your tools directory, and yourappname is of course your app's name):
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"
Then in your code just do something similar to this:
Log.d("yourappname", "Your message");
To create the log, connect the USB cable and run your bat file.
Regards
Upvotes: 11
Reputation: 4744
In general, you must have a file handle before opening the stream. You have a fileOutputStream handle before createNewFile() in the else block. The stream does not create the file if it doesn't exist.
Not really android specific, but that's a lot IO for this purpose. What if you do many "write" operations one after another? You will be reading the entire contents and writing the entire contents, taking time, and more importantly, battery life.
I suggest using java.io.RandomAccessFile, seek()'ing to the end, then writeChars() to append. It will be much cleaner code and likely much faster.
Upvotes: 2