org.akvo.caddisfly.sensor.colorimetry.liquid.CalibrateListActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.akvo.caddisfly.sensor.colorimetry.liquid.CalibrateListActivity.java

Source

/*
 * Copyright (C) Stichting Akvo (Akvo Foundation)
 *
 * This file is part of Akvo Caddisfly.
 *
 * Akvo Caddisfly 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.
 *
 * Akvo Caddisfly 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 Akvo Caddisfly. If not, see <http://www.gnu.org/licenses/>.
 */

package org.akvo.caddisfly.sensor.colorimetry.liquid;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.ContextCompat;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import org.akvo.caddisfly.R;
import org.akvo.caddisfly.app.CaddisflyApp;
import org.akvo.caddisfly.helper.FileHelper;
import org.akvo.caddisfly.helper.SwatchHelper;
import org.akvo.caddisfly.model.Swatch;
import org.akvo.caddisfly.model.TestInfo;
import org.akvo.caddisfly.preference.AppPreferences;
import org.akvo.caddisfly.ui.BaseActivity;
import org.akvo.caddisfly.util.AlertUtil;
import org.akvo.caddisfly.util.ApiUtil;
import org.akvo.caddisfly.util.FileUtil;
import org.akvo.caddisfly.util.PreferencesUtil;

import java.io.File;
import java.text.DateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

/**
 * An activity representing a list of Calibrate items.
 * <p/>
 * This activity also implements the required
 * {@link CalibrateListFragment.Callbacks} interface
 * to listen for item selections.
 */
public class CalibrateListActivity extends BaseActivity
        implements CalibrateListFragment.Callbacks, SaveCalibrationDialogFragment.CalibrationDetailsSavedListener {

    private static final int REQUEST_CALIBRATE = 100;
    private static final int FREEZE_BUTTON_DELAY_MILLIS = 500;
    private FloatingActionButton fabEditCalibration;
    private TextView textSubtitle;
    private TextView textSubtitle1;
    private TextView textSubtitle2;
    private int mPosition;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        if (AppPreferences.isDiagnosticMode()) {
            getMenuInflater().inflate(R.menu.menu_calibrate_dev, menu);
        }
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
        case R.id.actionSwatches:
            final Intent intent = new Intent(this, DiagnosticSwatchActivity.class);
            startActivity(intent);
            return true;
        case R.id.menuLoad:
            Handler.Callback callback = new Handler.Callback() {
                public boolean handleMessage(Message msg) {
                    CalibrateListFragment fragment = (CalibrateListFragment) getSupportFragmentManager()
                            .findFragmentById(R.id.fragmentCalibrateList);
                    fragment.setAdapter();
                    loadDetails();
                    return true;
                }
            };
            loadCalibration(this, callback);
            return true;
        case R.id.menuSave:
            showEditCalibrationDetailsDialog(false);
            return true;
        case android.R.id.home:
            onBackPressed();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_calibrate_list);

        textSubtitle = (TextView) findViewById(R.id.textSubtitle);
        textSubtitle1 = (TextView) findViewById(R.id.textSubtitle1);
        textSubtitle2 = (TextView) findViewById(R.id.textSubtitle2);

        ((TextView) findViewById(R.id.textTitle)).setText(CaddisflyApp.getApp().getCurrentTestInfo().getName());

        fabEditCalibration = (FloatingActionButton) findViewById(R.id.fabEditCalibration);

        if (AppPreferences.isDiagnosticMode()) {
            fabEditCalibration
                    .setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor(this, R.color.cyan)));
        }

        fabEditCalibration.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showEditCalibrationDetailsDialog(true);
            }
        });

        loadDetails();
    }

    private void showEditCalibrationDetailsDialog(boolean isEdit) {
        final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        SaveCalibrationDialogFragment saveCalibrationDialogFragment = SaveCalibrationDialogFragment
                .newInstance(isEdit);
        saveCalibrationDialogFragment.show(ft, "saveCalibrationDialog");
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        setTitle(R.string.calibrate);
    }

    @Override
    protected void onResume() {
        super.onResume();
        fabEditCalibration.setEnabled(true);
    }

    private void loadDetails() {

        TestInfo testInfo = CaddisflyApp.getApp().getCurrentTestInfo();

        testInfo.setCalibrationDate(PreferencesUtil.getLong(this, testInfo.getId(), R.string.calibrationDateKey));

        if (testInfo.getCalibrationDate() >= 0) {
            textSubtitle1.setText(
                    DateFormat.getDateInstance(DateFormat.MEDIUM).format(new Date(testInfo.getCalibrationDate())));
        }

        testInfo.setExpiryDate(PreferencesUtil.getLong(this, testInfo.getId(), R.string.calibrationExpiryDateKey));

        if (testInfo.getExpiryDate() >= 0) {
            textSubtitle2.setText(String.format("%s: %s", getString(R.string.expires),
                    DateFormat.getDateInstance(DateFormat.MEDIUM).format(new Date(testInfo.getExpiryDate()))));
        }

        testInfo.setBatchNumber(PreferencesUtil.getString(this, testInfo.getId(), R.string.batchNumberKey, ""));

        textSubtitle.setText(testInfo.getBatchNumber());

        CalibrateListFragment calibrateListFragment = (CalibrateListFragment) getSupportFragmentManager()
                .findFragmentById(R.id.fragmentCalibrateList);

        if (calibrateListFragment != null) {
            calibrateListFragment.refresh();
        }
    }

    /**
     * Callback method from {@link CalibrateListFragment.Callbacks}
     * indicating that the item with the given ID was selected.
     */
    @Override
    public void onItemSelected(int id) {

        TestInfo currentTestInfo = CaddisflyApp.getApp().getCurrentTestInfo();

        fabEditCalibration.setEnabled(false);
        (new Handler()).postDelayed(new Runnable() {
            public void run() {
                fabEditCalibration.setEnabled(true);
            }
        }, FREEZE_BUTTON_DELAY_MILLIS);

        //Show edit calibration details dialog if required
        Long expiryDate = PreferencesUtil.getLong(this, currentTestInfo.getId(), R.string.calibrationExpiryDateKey);
        if (expiryDate < Calendar.getInstance().getTimeInMillis()) {
            showEditCalibrationDetailsDialog(true);
            return;
        }

        mPosition = id;
        Swatch swatch = currentTestInfo.getSwatch(mPosition);

        if (AppPreferences.useExternalCamera() || !ApiUtil.isCameraInUse(this, null)) {
            final Intent intent = new Intent(getIntent());
            intent.setClass(getBaseContext(), ColorimetryLiquidActivity.class);
            intent.putExtra("isCalibration", true);
            intent.putExtra("swatchValue", swatch.getValue());
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
            startActivityForResult(intent, REQUEST_CALIBRATE);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @NonNull Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
        case REQUEST_CALIBRATE:

            Swatch swatch = CaddisflyApp.getApp().getCurrentTestInfo().getSwatch(mPosition);

            long calibratedDate = PreferencesUtil.getLong(this, CaddisflyApp.getApp().getCurrentTestInfo().getId(),
                    R.string.calibrationDateKey);

            if (resultCode == Activity.RESULT_OK) {
                saveCalibratedData(swatch, data.getIntExtra("color", 0));

                //Save date if this is the first swatch calibrated
                if (calibratedDate < 0 || SwatchHelper
                        .getCalibratedSwatchCount(CaddisflyApp.getApp().getCurrentTestInfo().getSwatches()) == 1) {
                    PreferencesUtil.setLong(this, CaddisflyApp.getApp().getCurrentTestInfo().getId(),
                            R.string.calibrationDateKey, Calendar.getInstance().getTimeInMillis());
                    loadDetails();
                }

                ((CalibrateListFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentCalibrateList))
                        .setAdapter();
            }

            break;
        default:
            break;
        }
    }

    /**
     * Save a single calibrated color
     *
     * @param swatch      The swatch object
     * @param resultColor The color value
     */
    private void saveCalibratedData(@NonNull Swatch swatch, final int resultColor) {
        String colorKey = String.format(Locale.US, "%s-%.2f", CaddisflyApp.getApp().getCurrentTestInfo().getId(),
                swatch.getValue());

        if (resultColor == 0) {
            PreferencesUtil.removeKey(getApplicationContext(), colorKey);
        } else {
            swatch.setColor(resultColor);
            PreferencesUtil.setInt(getApplicationContext(), colorKey, resultColor);
        }

        String testCode = CaddisflyApp.getApp().getCurrentTestInfo().getId();

        //Save a backup of the calibration details
        final String calibrationDetails = SwatchHelper.generateCalibrationFile(this, testCode,
                PreferencesUtil.getString(this, testCode, R.string.batchNumberKey, ""),
                PreferencesUtil.getLong(this, testCode, R.string.calibrationDateKey),
                PreferencesUtil.getLong(this, testCode, R.string.calibrationExpiryDateKey),
                PreferencesUtil.getString(this, testCode, R.string.ledRgbKey, "255 255 255"),
                !PreferencesUtil.getBoolean(this, R.string.noBackdropDetectionKey, false));

        final File path = FileHelper.getFilesDir(FileHelper.FileType.CALIBRATION, testCode);

        FileUtil.saveToFile(path, "_AutoBackup", calibrationDetails);

        Toast.makeText(this, R.string.calibrated, Toast.LENGTH_LONG).show();
    }

    /**
     * Load the calibrated swatches from the calibration text file
     *
     * @param callback callback to be initiated once the loading is complete
     */
    private void loadCalibration(@NonNull final Context context, @NonNull final Handler.Callback callback) {
        try {
            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setTitle(R.string.loadCalibration);

            final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(context, R.layout.row_text);

            final File path = FileHelper.getFilesDir(FileHelper.FileType.CALIBRATION,
                    CaddisflyApp.getApp().getCurrentTestInfo().getId());

            File[] listFilesTemp = null;
            if (path.exists() && path.isDirectory()) {
                listFilesTemp = path.listFiles();
            }

            final File[] listFiles = listFilesTemp;
            if (listFiles != null && listFiles.length > 0) {
                Arrays.sort(listFiles);

                for (File listFile : listFiles) {
                    arrayAdapter.add(listFile.getName());
                }

                builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(@NonNull DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                });

                builder.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        String fileName = listFiles[which].getName();
                        try {
                            final List<Swatch> swatchList = SwatchHelper.loadCalibrationFromFile(getBaseContext(),
                                    fileName);

                            (new AsyncTask<Void, Void, Void>() {
                                @Nullable
                                @Override
                                protected Void doInBackground(Void... params) {
                                    SwatchHelper.saveCalibratedSwatches(context, swatchList);
                                    return null;
                                }

                                @Override
                                protected void onPostExecute(Void result) {
                                    super.onPostExecute(result);
                                    callback.handleMessage(null);
                                }
                            }).execute();

                        } catch (Exception ex) {
                            AlertUtil.showError(context, R.string.error, getString(R.string.errorLoadingFile), null,
                                    R.string.ok, new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(@NonNull DialogInterface dialog, int which) {
                                            dialog.dismiss();
                                        }
                                    }, null, null);
                        }
                    }

                });

                final AlertDialog alertDialog = builder.create();
                alertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
                    @Override
                    public void onShow(DialogInterface dialogInterface) {
                        final ListView listView = alertDialog.getListView();
                        listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
                            @Override
                            public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
                                final int position = i;

                                AlertUtil.askQuestion(context, R.string.delete, R.string.deleteConfirm,
                                        R.string.delete, R.string.cancel, true,
                                        new DialogInterface.OnClickListener() {
                                            @SuppressWarnings("unchecked")
                                            @Override
                                            public void onClick(DialogInterface dialogInterface, int i) {
                                                String fileName = listFiles[position].getName();
                                                FileUtil.deleteFile(path, fileName);
                                                ArrayAdapter listAdapter = (ArrayAdapter) listView.getAdapter();
                                                listAdapter.remove(listAdapter.getItem(position));
                                                alertDialog.dismiss();
                                                Toast.makeText(context, R.string.deleted, Toast.LENGTH_SHORT)
                                                        .show();
                                            }
                                        }, null);
                                return true;
                            }
                        });

                    }
                });
                alertDialog.show();
            } else {
                AlertUtil.showMessage(context, R.string.notFound, R.string.loadFilesNotAvailable);
            }
        } catch (ActivityNotFoundException ignored) {
        }

        callback.handleMessage(null);
    }

    @Override
    public void onCalibrationDetailsSaved() {
        loadDetails();
    }
}