Java tutorial
/* (C) 2012 Pragmatic Software This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/ */ package com.googlecode.networklog; import android.app.Activity; import android.app.AlertDialog; import android.app.DatePickerDialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Resources; import android.widget.Button; import android.widget.DatePicker; import android.view.View; import android.view.LayoutInflater; import android.os.Environment; import java.io.File; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.concurrent.FutureTask; import java.util.Date; import java.util.GregorianCalendar; import com.samsung.sprc.fileselector.*; import au.com.bytecode.opencsv.CSVWriter; import android.support.v4.app.DialogFragment; public class ExportDialog { public Button startDateButton; public Button endDateButton; public Button filenameButton; public AlertDialog dialog; private Context context; private SimpleDateFormat dateDisplayFormat = new SimpleDateFormat("MMMM d, y"); private SimpleDateFormat dateFilenameFormat = new SimpleDateFormat("y-MM-dd"); public Date startDate; public Date endDate; public File file; public ProgressDialog progressDialog = null; public int progress_max = 0; public int progress = 0; private boolean canceled = false; public enum DatePickerMode { START_DATE, END_DATE }; public DatePickerMode datePickerMode; public ExportDialog(final Context context) { this.context = context; Resources res = context.getResources(); LayoutInflater inflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); View view = inflater.inflate(R.layout.exportdialog, null); startDateButton = (Button) view.findViewById(R.id.exportStartDateButton); endDateButton = (Button) view.findViewById(R.id.exportEndDateButton); filenameButton = (Button) view.findViewById(R.id.exportFilenameButton); GregorianCalendar today = new GregorianCalendar(); startDate = new GregorianCalendar(today.get(Calendar.YEAR), today.get(Calendar.MONTH), 1).getTime(); endDate = today.getTime(); file = new File( Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + defaultFilename()); startDateButton.setText(dateDisplayFormat.format(startDate)); endDateButton.setText(dateDisplayFormat.format(endDate)); filenameButton.setText(file.getAbsolutePath()); startDateButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { datePickerMode = DatePickerMode.START_DATE; DatePickerDialog.OnDateSetListener listener = new DatePickerDialog.OnDateSetListener() { public void onDateSet(DatePicker view, int year, int month, int day) { startDate = new GregorianCalendar(year, month, day).getTime(); startDateButton.setText(dateDisplayFormat.format(startDate)); updateFilename(); } }; Calendar cal = Calendar.getInstance(); cal.setTime(startDate); DialogFragment newFragment = new DatePickerFragment(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), listener); newFragment.show(NetworkLog.instance.getSupportFragmentManager(), "exportDatePicker"); } }); endDateButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { datePickerMode = DatePickerMode.END_DATE; DatePickerDialog.OnDateSetListener listener = new DatePickerDialog.OnDateSetListener() { public void onDateSet(DatePicker view, int year, int month, int day) { endDate = new GregorianCalendar(year, month, day, 23, 59, 59).getTime(); endDateButton.setText(dateDisplayFormat.format(endDate)); updateFilename(); } }; Calendar cal = Calendar.getInstance(); cal.setTime(endDate); DialogFragment newFragment = new DatePickerFragment(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), listener); newFragment.show(NetworkLog.instance.getSupportFragmentManager(), "exportDatePicker"); } }); filenameButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { OnHandleFileListener saveListener = new OnHandleFileListener() { public void handleFile(final String filePath) { file = new File(filePath); filenameButton.setText(filePath); } }; new FileSelector(context, FileOperation.SAVE, saveListener, defaultFilename(), new String[] { "*.*", "*.csv" }).show(); } }); AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(res.getString(R.string.export_title)).setView(view).setCancelable(true) .setPositiveButton(res.getString(R.string.export_button), new DialogInterface.OnClickListener() { public void onClick(DialogInterface d, int id) { // see show() method for implementation -- avoids dismiss() unless validation passes } }).setNegativeButton(res.getString(R.string.cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface d, int id) { dialog.cancel(); dialog = null; } }); dialog = builder.create(); } public void restoreDatePickerListener() { DatePickerDialog.OnDateSetListener listener; DatePickerFragment dpf = (DatePickerFragment) NetworkLog.instance.getSupportFragmentManager() .findFragmentByTag("exportDatePicker"); if (dpf != null) { if (datePickerMode == DatePickerMode.START_DATE) { listener = new DatePickerDialog.OnDateSetListener() { public void onDateSet(DatePicker view, int year, int month, int day) { startDate = new GregorianCalendar(year, month, day).getTime(); startDateButton.setText(dateDisplayFormat.format(startDate)); updateFilename(); } }; } else { listener = new DatePickerDialog.OnDateSetListener() { public void onDateSet(DatePicker view, int year, int month, int day) { endDate = new GregorianCalendar(year, month, day, 23, 59, 59).getTime(); endDateButton.setText(dateDisplayFormat.format(endDate)); updateFilename(); } }; } dpf.setListener(listener); } } private String defaultFilename() { return "networklog-" + dateFilenameFormat.format(startDate) + "-" + dateFilenameFormat.format(endDate) + ".csv"; } private void updateFilename() { file = new File((file.getParent() == null ? "" : file.getParent()) + File.separator + defaultFilename()); filenameButton.setText(file.getAbsolutePath()); } public void setStartDate(Date date) { startDate = date; startDateButton.setText(dateDisplayFormat.format(startDate)); updateFilename(); } public void setEndDate(Date date) { endDate = date; endDateButton.setText(dateDisplayFormat.format(endDate)); updateFilename(); } public void setFile(File file) { this.file = file; filenameButton.setText(file.getAbsolutePath()); } public void show() { if (dialog != null) { dialog.show(); dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { dialog.dismiss(); dialog = null; exportLog(startDate, endDate, file); } }); } } public void dismiss() { if (dialog != null) { dialog.dismiss(); dialog = null; } } public FutureTask showProgressDialog(final Context context) { FutureTask futureTask = new FutureTask(new Runnable() { public void run() { progressDialog = new ProgressDialog(context); progressDialog.setIndeterminate(false); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setMax(progress_max); progressDialog.setCancelable(false); progressDialog.setTitle(""); progressDialog.setMessage(context.getResources().getString(R.string.exporting_log)); progressDialog.setButton(DialogInterface.BUTTON_NEUTRAL, context.getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { canceled = true; } }); progressDialog.show(); progressDialog.setProgress(progress); } }, null); NetworkLog.handler.post(futureTask); return futureTask; } public void exportLog(final Date startDate, final Date endDate, final File file) { MyLog.d("Exporting from " + dateFilenameFormat.format(startDate) + " to " + dateFilenameFormat.format(endDate) + " to path " + file.getAbsolutePath()); final long end_timestamp = endDate.getTime(); final LogfileLoader loader = new LogfileLoader(); try { loader.openLogfile(NetworkLog.settings.getLogFile()); } catch (FileNotFoundException fnfe) { SysUtils.showError(context, context.getResources().getString(R.string.export_error_title), "No logfile found at " + NetworkLog.settings.getLogFile()); return; } catch (Exception e) { SysUtils.showError(context, context.getResources().getString(R.string.export_error_title), "Error opening logfile: " + e.getMessage()); return; } try { final long length = loader.getLength(); if (length == 0) { SysUtils.showError(context, context.getResources().getString(R.string.export_error_title), "Logfile empty -- nothing to export"); return; } long possible_end_pos = loader.seekToTimestampPosition(endDate.getTime(), true); final long start_pos = loader.seekToTimestampPosition(startDate.getTime()); if (possible_end_pos == -1) { possible_end_pos = length; } final long end_pos = possible_end_pos; if (start_pos == -1) { SysUtils.showError(context, context.getResources().getString(R.string.export_error_title), "No entries found at " + dateDisplayFormat.format(startDate)); return; } progress_max = (int) (end_pos - start_pos); progress = 0; CSVWriter open_writer; try { open_writer = new CSVWriter(new FileWriter(file)); } catch (Exception e) { SysUtils.showError(context, context.getResources().getString(R.string.export_error_title), "Error opening export file: " + e.getMessage()); return; } final CSVWriter writer = open_writer; new Thread(new Runnable() { public void run() { try { FutureTask showDialog = showProgressDialog(context); showDialog.get(); // wait until showDialog task completes } catch (Exception e) { // ignored } LogEntry entry; ApplicationsTracker.AppEntry appEntry; long processed_so_far = 0; long progress_increment_size = (long) ((end_pos - start_pos) * 0.01); long next_progress_increment = progress_increment_size; try { String[] entries = new String[11]; entries[0] = "Timestamp"; entries[1] = "AppName"; entries[2] = "AppPackage"; entries[3] = "AppUid"; entries[4] = "In interface"; entries[5] = "Out interface"; entries[6] = "Source"; entries[7] = "Source Port"; entries[8] = "Destination"; entries[9] = "Destination Port"; entries[10] = "Length"; writer.writeNext(entries); while (!canceled) { entry = loader.readEntry(); processed_so_far = loader.getProcessedSoFar(); if (processed_so_far >= next_progress_increment) { next_progress_increment += progress_increment_size; progress = (int) processed_so_far; if (progressDialog != null) { progressDialog.setProgress(progress); } } if (entry == null) { // end of file break; } if (entry.timestamp > end_timestamp) { break; } appEntry = ApplicationsTracker.uidMap.get(entry.uidString); entries[0] = Timestamp.getTimestamp(entry.timestamp); entries[1] = appEntry == null ? "Uninstalled App" : appEntry.name; entries[2] = appEntry == null ? "Uninstalled App" : appEntry.packageName; entries[3] = entry.uidString; entries[4] = entry.in; entries[5] = entry.out; entries[6] = entry.src; entries[7] = StringPool.get(entry.spt); entries[8] = entry.dst; entries[9] = StringPool.get(entry.dpt); entries[10] = StringPool.get(entry.len); writer.writeNext(entries); } } catch (Exception e) { SysUtils.showError(context, context.getResources().getString(R.string.export_error_title), "Error exporting logfile: " + e.getMessage()); } finally { try { loader.closeLogfile(); } catch (Exception e) { // ignored } try { writer.close(); } catch (Exception e) { // ignored } NetworkLog.handler.post(new Runnable() { public void run() { if (progressDialog != null) { progressDialog.dismiss(); progressDialog = null; } } }); } } }, "ExportLogfile").start(); } catch (Exception e) { SysUtils.showError(context, context.getResources().getString(R.string.export_error_title), "Error exporting logfile: " + e.getMessage()); } } }