how to write exception in log file using android?
I want to write text file开发者_JAVA百科 in sd card when I get an exception from my application
How to implement this concept in my application?
I'd create my own logger class and use that. In fact here is basically what I do, but you could modify this so it only writes out exceptions:
public class Logger {
private static Logger instance = null;
private static final int MAX_LOGS = 10;
public enum Level { DEBUG, INFO, WARN, ERROR }
private Level level = Level.ERROR;
private String tag;
private SimpleDateFormat format = new SimpleDateFormat("MM/dd/yy hh:mm:ss z");
private File log;
private PrintWriter writer;
private String supportEmail;
public void LoggerSetup(String tag, String logFilename, Level level ) {
//close previous
if( writer != null ) {
writer.flush();
writer.close();
writer = null;
}
//open new
this.tag = tag;
this.log = createWriter( logFilename );
this.level = level;
}
public Logger(Context context) {
LoggerSetup(context.getPackageName(), "application.log", Level.INFO);
}
public static Logger getInstance(Context context) {
if(instance == null) {
instance = new Logger(context);
}
return instance;
}
public Logger() {
LoggerSetup("", "application.log", Level.INFO);
}
private File createWriter(String logFilename) {
try {
String state = Environment.getExternalStorageState();
if( state.equals(Environment.MEDIA_MOUNTED) ) {
File dir = new File( Environment.getExternalStorageDirectory(), "com.yourpackage");
if( !dir.mkdirs() ) {
Log.w( tag, "Could not create log directory: " + dir.getAbsolutePath() );
}
File log = new File(dir, logFilename);
if( log.exists() ) {
rotate( log );
}
Log.i( tag, "Opening " + log.getAbsolutePath() );
writer = new PrintWriter( new FileWriter( log ), true );
return log;
} else {
Log.w( tag, "Could not create log file because external storage state was " + state);
}
} catch( IOException ioe ) {
Log.e( tag, "Failed while opening the log file.", ioe );
}
return null;
}
private void rotate(File log) {
int index = log.getName().lastIndexOf('.');
if( index < 0 ) index = log.getName().length();
String prefix = log.getName().substring(0, index );
String extension = log.getName().substring(index);
int lastLog = MAX_LOGS - 1;
File lastLogFile = new File( log.getParentFile(), prefix + "-" + lastLog + extension );
if( lastLogFile.exists() ) lastLogFile.delete();
for( int i = lastLog; i >= 1; --i ) {
String filename = prefix + "-" + i + extension;
File l = new File( log.getParentFile(), filename );
if( l.exists() ) {
File newLog = new File( log.getParentFile(), prefix + "-" + (i+1) + extension );
l.renameTo( newLog );
}
}
log.renameTo( new File( log.getParentFile(), prefix + "-1" + extension ) );
}
public Level getLevel() {
return level;
}
public void setLevel(Level level) {
this.level = level;
}
public boolean isLoggable( Level level ) {
return level.ordinal() >= this.level.ordinal();
}
public void debug( String message, Object... parameters ) {
if( parameters.length > 0 ) {
Log.d( tag, MessageFormat.format( message, parameters ) );
} else {
Log.d( tag, message );
}
log( Level.DEBUG, message, parameters );
}
public void info( String message, Object... parameters ) {
if( parameters.length > 0 ) {
Log.i( tag, MessageFormat.format( message, parameters ) );
} else {
Log.i( tag, message );
}
log( Level.INFO, message, parameters );
}
public void warn( String message, Object... parameters ) {
if( parameters.length > 0 ) {
Log.w( tag, MessageFormat.format( message, parameters ) );
} else {
Log.w( tag, message );
}
log( Level.WARN, message, parameters );
}
public void error( String message, Object... parameters ) {
if( parameters.length > 0 ) {
Log.e( tag, MessageFormat.format( message, parameters ) );
} else {
Log.e( tag, message );
}
log( Level.ERROR, message, parameters );
}
public void error(Throwable throwable) {
String message = Log.getStackTraceString( throwable );
Log.e( tag, message, throwable );
log( Level.ERROR, message );
}
public void close() {
if( writer != null ) {
writer.flush();
writer.close();
writer = null;
}
}
private void log( Level level, String message, Object... parameters ) {
if( writer != null && isLoggable(level) ) {
Date date = new Date();
writer.print( format.format(date) );
writer.print( " " );
writer.print( level.toString() );
writer.print( " " );
writer.print( tag );
writer.print( " " );
writer.print( Thread.currentThread().getName() );
writer.print( " - " );
if( parameters.length > 0 ) {
writer.println( MessageFormat.format( message, parameters ) );
} else {
writer.println( message );
}
}
}
protected void sendEmail(Context context) throws IOException {
File[] logs = log.getParentFile().listFiles( new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(".log");
}
});
File temp = zipLogFiles(logs);
String[] mailto = { supportEmail };
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.setType("application/zip");
sendIntent.putExtra(Intent.EXTRA_EMAIL, mailto);
sendIntent.putExtra(Intent.EXTRA_SUBJECT, tag + ": Log File Attached");
sendIntent.putExtra(Intent.EXTRA_TEXT, "A user has requested you look at some logs.");
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(temp) );
sendIntent.setType("text/plain");
context.startActivity(Intent.createChooser(sendIntent, "Send Logs To Support"));
}
private File zipLogFiles(File[] logs) throws IOException {
File zipfile = File.createTempFile("brewster", ".zip");
ZipOutputStream stream = new ZipOutputStream( new FileOutputStream(zipfile) );
try {
for( File log : logs ) {
ZipEntry entry = new ZipEntry( log.getName() );
stream.putNextEntry( entry );
copy( stream, log );
stream.closeEntry();
}
stream.finish();
return zipfile;
} finally {
stream.close();
}
}
private void copy(OutputStream stream, File file) throws IOException {
InputStream istream = new FileInputStream( file );
try {
byte[] buffer = new byte[8096];
int length = 0;
while( (length = istream.read( buffer )) >= 0 ) {
stream.write( buffer, 0, length );
}
} finally {
istream.close();
}
}
}
A general way to go about this, although in practice you should use buffered streams whenever possible.
In your onCreate(Bundle savedInstanceState)
callback or anywhere else you want to do this logging:
try
{
//normal application code
}
//called whenever an Exception is thrown
catch(Exception e)
{
//stream for writing text
FileWriter writer=null;
try
{
writer = new FileWriter(this.getExternalFilesDir());
//write to the SD card
} catch(Throwable t) {}
finally
{
if(writer != null) writer.close();
}
}
Note that I omitted checking for the SD card, but you should always do this. See http://developer.android.com/guide/topics/data/data-storage.html#filesExternal
Sorry for the crappy code formatting. This little text box is nothing like Eclipse.
精彩评论