package net.wigle.wigleandroid; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.support.v7.app.ActionBarActivity; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; import android.widget.TextView; /** * display latest error stack, if any. * allow the stack to be emailed to us. * @author bobzilla * */ public class ErrorReportActivity extends ActionBarActivity { private static final int MENU_EXIT = 11; private static final int MENU_EMAIL = 12; private boolean fromFailure = false; private String stack; @Override public void onCreate( final Bundle savedInstanceState) { super.onCreate( savedInstanceState ); // set language MainActivity.setLocale( this ); setContentView( R.layout.error ); // get stack from file stack = getLatestStack(); // set on view TextView tv = (TextView) findViewById( R.id.errorreport ); tv.setText( stack ); Intent intent = getIntent(); boolean doEmail = intent.getBooleanExtra( MainActivity.ERROR_REPORT_DO_EMAIL, false ); if ( doEmail ) { fromFailure = true; // setup email sending setupEmail( stack ); } final String dialogMessage = intent.getStringExtra(MainActivity.ERROR_REPORT_DIALOG ); if ( dialogMessage != null ) { fromFailure = true; shutdownRestOfApp(); final Handler handler = new Handler(); final Runnable dialogTask = new Runnable() { @Override public void run() { final AlertDialog.Builder builder = new AlertDialog.Builder( ErrorReportActivity.this ); builder.setCancelable( false ); builder.setTitle( getString(R.string.fatal_title) ); String fatalDbWarn = ""; if ( dialogMessage.contains("SQL") ) { fatalDbWarn = getString(R.string.fatal_db_warn); } builder.setMessage( fatalDbWarn + "\n\n*** " + getString(R.string.fatal_pre_message) + ": ***\n" + dialogMessage + "\n\n" + getString(R.string.fatal_post_message) ); final AlertDialog ad = builder.create(); ad.setButton( DialogInterface.BUTTON_POSITIVE, "OK, Shutdown", new DialogInterface.OnClickListener() { @Override public void onClick( final DialogInterface dialog, final int which ) { try { dialog.dismiss(); } catch ( Exception ex ) { // guess it wasn't there anyways MainActivity.info( "exception dismissing alert dialog: " + ex ); } } }); try { ad.show(); } catch ( WindowManager.BadTokenException windowEx ) { MainActivity.info("window probably gone when trying to display dialog. windowEx: " + windowEx, windowEx ); } } }; handler.removeCallbacks( dialogTask ); handler.postDelayed( dialogTask, 100 ); } } private void shutdownRestOfApp() { MainActivity.info( "ErrorReportActivity: shutting down app" ); // shut down anything we can get a handle to final MainActivity mainActivity = MainActivity.getMainActivity(); if ( mainActivity != null ) { mainActivity.finish(); } if ( NetworkActivity.networkActivity != null ) { NetworkActivity.networkActivity.finish(); } if ( SpeechActivity.speechActivity != null ) { SpeechActivity.speechActivity.finish(); } } private String getLatestStack() { StringBuilder builder = new StringBuilder( "No Error Report found" ); BufferedReader reader = null; try { File fileDir = new File( MainActivity.safeFilePath( Environment.getExternalStorageDirectory() ) + "/wiglewifi/" ); if ( ! fileDir.canRead() || ! fileDir.isDirectory() ) { MainActivity.error( "file is not readable or not a directory. fileDir: " + fileDir ); } else { String[] files = fileDir.list(); if ( files == null ) { MainActivity.error( "no files in dir: " + fileDir ); } else { String latestFilename = null; for ( String filename : files ) { if ( filename.startsWith( MainActivity.ERROR_STACK_FILENAME ) ) { if ( latestFilename == null || filename.compareTo( latestFilename ) > 0 ) { latestFilename = filename; } } } MainActivity.info( "latest filename: " + latestFilename ); String filePath = MainActivity.safeFilePath( fileDir ) + "/" + latestFilename; reader = new BufferedReader( new InputStreamReader( new FileInputStream( filePath ), "UTF-8") ); String line = reader.readLine(); builder.setLength( 0 ); while ( line != null ) { builder.append( line ).append( "\n" ); line = reader.readLine(); } } } } catch ( IOException ex ) { MainActivity.error( "error reading stack file: " + ex, ex ); } finally { if (reader != null) { try { reader.close(); } catch (IOException ex) { MainActivity.error( "error closing stack file: " + ex, ex ); } } } return builder.toString(); } private void setupEmail( String stack ) { MainActivity.info( "ErrorReport onCreate" ); final Intent emailIntent = new Intent( android.content.Intent.ACTION_SEND ); emailIntent.setType( "plain/text" ); emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{"wiwiwa@wigle.net"} ); emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "WigleWifi error report" ); emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, stack ); final Intent chooserIntent = Intent.createChooser( emailIntent, "Email WigleWifi error report?" ); startActivity( chooserIntent ); } /* Creates the menu items */ @Override public boolean onCreateOptionsMenu( final Menu menu ) { if ( fromFailure ) { MenuItem item = menu.add(0, MENU_EXIT, 0, getString(R.string.menu_exit)); item.setIcon( android.R.drawable.ic_menu_close_clear_cancel ); } else { MenuItem item = menu.add(0, MENU_EXIT, 0, getString(R.string.menu_return)); item.setIcon( android.R.drawable.ic_media_previous ); } MenuItem item = menu.add(0, MENU_EMAIL, 0, getString(R.string.menu_error_report)); item.setIcon( android.R.drawable.ic_menu_send ); return true; } /* Handles item selections */ @Override public boolean onOptionsItemSelected( final MenuItem item ) { switch ( item.getItemId() ) { case MENU_EXIT: finish(); return true; case MENU_EMAIL: setupEmail( stack ); return true; } return false; } }