org.ecmdroid.activity.EEPROMActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.ecmdroid.activity.EEPROMActivity.java

Source

/*
 EcmDroid - Android Diagnostic Tool for Buell Motorcycles
 Copyright (C) 2012 by Michel Marti
    
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 3
 of the License, or (at your option) any later version.
    
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
    
 You should have received a copy of the GNU General Public License
 along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
package org.ecmdroid.activity;

import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.Arrays;

import org.ecmdroid.Constants;
import org.ecmdroid.ECM;
import org.ecmdroid.EEPROM;
import org.ecmdroid.EEPROMAdapter;
import org.ecmdroid.R;
import org.ecmdroid.Utils;
import org.ecmdroid.Variable;
import org.ecmdroid.fragments.CellEditorDialogFragment;
import org.ecmdroid.fragments.CellEditorDialogFragment.CellEditorDialogListener;
import org.ecmdroid.task.BurnTask;
import org.ecmdroid.task.FetchTask;
import org.ecmdroid.task.SaveTask;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnDismissListener;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.FragmentActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.GridView;
import android.widget.TextView;
import android.widget.Toast;

public class EEPROMActivity extends FragmentActivity implements CellEditorDialogListener {

    public static final String ACTION_BURN = "BURN";

    private static final int COLS = 5;
    @SuppressWarnings("unused")
    private static final String TAG = "EEPROM";

    private ECM ecm = ECM.getInstance(this);
    private TextView offsetHex, offsetDec;
    private TextView byteValHex, byteValDec;
    private TextView hiShortHex, hiShortDec;
    private TextView loShortHex, loShortDec;
    private TextView cellInfo;
    private EEPROMAdapter adapter;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater mi = getMenuInflater();
        mi.inflate(R.menu.eeprom_menu, menu);
        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        SharedPreferences pm = PreferenceManager.getDefaultSharedPreferences(this);
        menu.findItem(R.id.fetch).setEnabled(ecm.isConnected());
        menu.findItem(R.id.burn)
                .setEnabled(ecm.isConnected() && pm.getBoolean(Constants.PREFS_ENABLE_BURN, Boolean.FALSE));
        menu.findItem(R.id.save).setEnabled(ecm.isEepromRead());
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.fetch:
            new FetchTask(this) {
                @Override
                protected void onPostExecute(Exception result) {
                    super.onPostExecute(result);
                    GridView gridview = (GridView) findViewById(R.id.eepromGrid);
                    adapter = new EEPROMAdapter(EEPROMActivity.this, ecm.getEEPROM(), COLS);
                    gridview.setAdapter(adapter);
                }
            }.start();
            break;
        case R.id.burn:
            new BurnTask(this).start();
            break;
        case R.id.save:
            new SaveTask(this, ecm.getEEPROM()).start();
            break;
        case R.id.load:
            final StringBuilder result = new StringBuilder();
            Dialog dlg = createLoadDialog(result);
            dlg.setOnDismissListener(new OnDismissListener() {
                public void onDismiss(DialogInterface dialog) {
                    if (result.length() > 0) {
                        if (ecm.isEepromRead() && ecm.getEEPROM().isTouched()) {
                            AlertDialog.Builder builder = new AlertDialog.Builder(EEPROMActivity.this);
                            builder.setTitle(R.string.load_eeprom).setMessage(R.string.overwrite_changes)
                                    .setCancelable(true).setNegativeButton(android.R.string.cancel, null)
                                    .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                                        public void onClick(DialogInterface dialog, int id) {
                                            loadEEPROM(new File(result.toString()));
                                        }
                                    }).show();
                        } else {
                            loadEEPROM(new File(result.toString()));
                        }
                    }
                }
            });
            dlg.show();
            break;
        }
        return true;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.eeprom);
        offsetHex = (TextView) findViewById(R.id.offsetHex);
        offsetDec = (TextView) findViewById(R.id.offsetDec);
        byteValHex = (TextView) findViewById(R.id.byteValHex);
        byteValDec = (TextView) findViewById(R.id.byteValDec);
        hiShortHex = (TextView) findViewById(R.id.hiShortHex);
        hiShortDec = (TextView) findViewById(R.id.hiShortDec);
        loShortHex = (TextView) findViewById(R.id.loShortHex);
        loShortDec = (TextView) findViewById(R.id.loShortDec);
        cellInfo = (TextView) findViewById(R.id.cellInfo);

        GridView gridview = (GridView) findViewById(R.id.eepromGrid);
        adapter = new EEPROMAdapter(this, ecm.getEEPROM(), COLS);
        gridview.setAdapter(adapter);
        // TODO: Chose a nice drawable for currently selected cell
        //gridview.setSelector(android.R.drawable.edit_text);

        gridview.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View v, int pos, long id) {
                if (pos % COLS != 0) {
                    int offset = pos - (pos / COLS + 1);
                    showCellInfo(offset);
                }
            }
        });

        gridview.setOnItemLongClickListener(new OnItemLongClickListener() {
            public boolean onItemLongClick(AdapterView<?> parent, View view, int pos, long id) {
                if (pos % COLS != 0) {
                    int offset = pos - (pos / COLS + 1);
                    showCellInfo(offset);
                    byte value = ecm.getEEPROM().getBytes()[offset];
                    CellEditorDialogFragment editor = CellEditorDialogFragment.newInstance(offset, value);
                    editor.show(getSupportFragmentManager(), "EEPROMActivity");
                }
                return false;
            }
        });

        if (ACTION_BURN.equals(getIntent().getAction())) {
            SharedPreferences pm = PreferenceManager.getDefaultSharedPreferences(this);
            if (pm.getBoolean(Constants.PREFS_ENABLE_BURN, false)) {
                new BurnTask(this).start();
            } else {
                Toast.makeText(EEPROMActivity.this, R.string.eeprom_burning_disabled_by_configuration,
                        Toast.LENGTH_LONG).show();
            }
        }
    }

    public void onCellValueChanged(int offset, byte value) {
        byte oldValue = ecm.getEEPROM().getBytes()[offset];
        if (oldValue != value) {
            ecm.getEEPROM().getBytes()[offset] = value;
            ecm.getEEPROM().touch(offset, 1);
            GridView gridview = (GridView) findViewById(R.id.eepromGrid);
            gridview.invalidateViews();
            showCellInfo(offset);
        }
    }

    private Dialog createLoadDialog(final StringBuilder result) {
        Builder builder = new Builder(this);
        if (Utils.isExternalStorageAvailable()) {
            final File dir = getApplicationContext().getExternalFilesDir(getString(R.string.eeprom_dir));
            final String[] files = dir.list(new FilenameFilter() {
                public boolean accept(File dir, String filename) {
                    return filename.endsWith(Constants.XPR_FILE_SUFFIX)
                            || filename.endsWith(Constants.EPR_FILE_SUFFIX);
                }
            });
            if (files.length > 0) {
                Arrays.sort(files);
                builder.setItems(files, new OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        String selected = files[which];
                        if (result != null) {
                            result.setLength(0);
                            result.append(new File(dir, selected).getPath());
                        }
                    }
                });
            } else {
                builder.setMessage(R.string.no_eeprom_dumps_present);
            }
        } else {
            builder.setMessage(R.string.no_ext_storage);
        }
        builder.setIcon(R.drawable.ic_menu_open);
        builder.setTitle(R.string.load_eeprom);
        return builder.create();
    }

    private void loadEEPROM(final File file) {
        int len = (int) file.length();
        final String[] ids;
        try {
            // Determine ECM type
            ids = EEPROM.size2id(this, len);
        } catch (IOException e) {
            Toast.makeText(EEPROMActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
            return;
        }
        if (ids.length > 1) {
            Builder builder = new Builder(this);
            builder.setItems(ids, new OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    String selected = ids[which];
                    loadEEPROM(selected, file);
                }
            });
            builder.setTitle(R.string.select_ecm_type).create().show();
        } else if (ids.length == 1) {
            loadEEPROM(ids[0], file);
        }
    }

    private void loadEEPROM(String id, File file) {
        try {
            FileInputStream in = new FileInputStream(file);
            EEPROM eeprom = EEPROM.load(this, ecm.getId(), id, in);
            if (ecm.isConnected() && !eeprom.getId().equals(ecm.getId())) {
                throw new IOException(getString(R.string.incompatible_version_disconnect_first, id));
            }
            ecm.setEEPROM(eeprom);
            Toast.makeText(EEPROMActivity.this, R.string.eeprom_loaded_sucessfully, Toast.LENGTH_LONG).show();
            GridView gridview = (GridView) findViewById(R.id.eepromGrid);
            adapter = new EEPROMAdapter(EEPROMActivity.this, ecm.getEEPROM(), COLS);
            gridview.setAdapter(adapter);
        } catch (IOException e) {
            Toast.makeText(EEPROMActivity.this,
                    getString(R.string.unable_to_load_eeprom) + " " + e.getLocalizedMessage(), Toast.LENGTH_LONG)
                    .show();
        }
    }

    private void showCellInfo(int offset) {
        Variable var = ecm.getEEPROMValueNearOffset(offset);
        if ((var.getOffset() + var.getSize() - 1) < offset) {
            // Unknown area
            var = null;
        }

        cellInfo.setText(var == null ? "" : var.getLabel() != null ? var.getLabel() : var.getName());
        cellInfo.setEnabled(var != null && var.getOffset() == offset);
        byte[] bytes = ecm.getEEPROM().getBytes();
        int val = bytes[offset] & 0xFF;
        offsetHex.setText(Utils.toHex(offset, 3));
        offsetDec.setText(Integer.toString(offset));
        byteValHex.setText(Utils.toHex(val, 2));
        byteValDec.setText(Integer.toString(val));
        if (offset == 0) {
            hiShortHex.setText("");
            hiShortDec.setText("");
        } else {
            int hival = val << 8 | (bytes[offset - 1] & 0xff);
            hiShortHex.setText(Utils.toHex(hival, 4));
            hiShortDec.setText(Integer.toString(hival));
        }

        if (offset + 1 >= bytes.length) {
            loShortHex.setText("");
            loShortDec.setText("");
        } else {
            int loval = (bytes[offset + 1] & 0xff) << 8 | val;
            loShortHex.setText(Utils.toHex(loval, 4));
            loShortDec.setText(Integer.toString(loval));
        }
    }
}