org.cirdles.chroni.AliquotMenuActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.cirdles.chroni.AliquotMenuActivity.java

Source

/*
 * Copyright 2016 CIRDLES.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* This activity provides the user with the aliquot file selection menu actions and setup */

package org.cirdles.chroni;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import org.w3c.dom.Document;

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

public class AliquotMenuActivity extends Activity {

    // Layout variables
    private EditText aliquotSelectedFileText; // holds the currently selected file name
    private EditText igsnText; // holds user-inputted IGSN

    // Global functionality  variables
    private static String geochronUsername, geochronPassword; // the GeoChron information on file for the user
    public static final String USER_PREFS = "My CIRDLES Settings"; // code to access stored preferences

    private static final String PREF_ALIQUOT = "Current Aliquot"; // Path of the current aliquot file
    private static final String PREF_REPORT_SETTINGS = "Current Report Settings"; // Path of the current report settings file

    // Base URLs for IGSN downloads
    public static String BASE_ALIQUOT_URI = "http://www.geochronportal.org/getxml.php?igsn=";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //Sets up activity layout
        super.onCreate(savedInstanceState);
        setTheme(android.R.style.Theme_Holo);
        setContentView(R.layout.aliquot_select);

        RelativeLayout aliquotMenuLayout = (RelativeLayout) findViewById(R.id.aliquotSelectBackground);

        //Places background image on layout after theme overriding
        aliquotMenuLayout.setBackground(getResources().getDrawable(R.drawable.background));

        Button aliquotFileSelectButton = (Button) findViewById(R.id.aliquotFileSelectButton);
        aliquotFileSelectButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // Opens file picker activity to main menu
                Intent openFilePicker = new Intent("android.intent.action.FILEPICKER");
                openFilePicker.putExtra("Default_Directory", "From_Aliquot_Directory");
                startActivityForResult(openFilePicker, 1); // Opens FilePicker and waits for it to return an Extra (SEE onActivityResult())
            }
        });

        aliquotSelectedFileText = (EditText) findViewById(R.id.aliquotFileSelectText); // Contains selected aliquot file name

        // sets the Aliquot file when one has already been selected (through "View Files" menu)
        if (getIntent().hasExtra("AliquotXMLFileName")) {
            String aliquotPath = getIntent().getStringExtra("AliquotXMLFileName");
            aliquotSelectedFileText.setText(splitReportSettingsName(aliquotPath));
        }

        Button aliquotFileSubmitButton = (Button) findViewById(R.id.aliquotFileSubmitButton);
        aliquotFileSubmitButton.setOnClickListener(new View.OnClickListener() {
            // Submits aliquot file to display activity for parsing and displaying in table
            public void onClick(View v) {

                if (aliquotSelectedFileText.getText().length() != 0) {

                    // if coming from a previously created table, change the aliquot
                    if (getIntent().hasExtra("From_Table")) {
                        if (getIntent().getStringExtra("From_Table").equals("true")) {

                            // if the Aliquot selected is valid, return to the new table
                            if (validateFile(getIntent().getStringExtra("AliquotXMLFileName"))) {
                                Toast.makeText(AliquotMenuActivity.this, "Changing Aliquot...", Toast.LENGTH_LONG)
                                        .show(); // lets user know table is opening
                                Intent returnAliquot = new Intent("android.intent.action.DISPLAY");
                                returnAliquot.putExtra("newAliquot", "true"); // tells if a new Aliquot has been chosen

                                // tells Intent that it is from a previous table that was opened via the History table
                                if (getIntent().hasExtra("fromHistory")) {
                                    returnAliquot.putExtra("fromHistory",
                                            getIntent().getStringExtra("fromHistory"));
                                    returnAliquot.putExtra("historyAliquot",
                                            getIntent().getStringExtra("AliquotXMLFileName"));

                                    if (!getIntent().getStringExtra("fromHistory").equals("true"))
                                        saveCurrentAliquot(); // saves Aliquot if Intent was NOT originally from the History table
                                }

                                else // saves Aliquot if Intent was NOT originally from the History table (and doesn't have extra)
                                    saveCurrentAliquot();

                                setResult(RESULT_OK, returnAliquot);
                                finish();

                            } else // if it is not valid, display a message
                                Toast.makeText(AliquotMenuActivity.this, "ERROR: Invalid Aliquot XML file.",
                                        Toast.LENGTH_LONG).show();

                        }

                    } else {

                        // if the Aliquot selected is valid, return to the new table
                        if (validateFile(getIntent().getStringExtra("AliquotXMLFileName"))) {
                            // Makes sure there is a file selected
                            Toast.makeText(AliquotMenuActivity.this, "Opening table...", Toast.LENGTH_LONG).show(); // lets user know table is opening
                            Intent openDisplayTable = new Intent("android.intent.action.DISPLAY"); // Opens display table
                            openDisplayTable.putExtra("fromHistory", "false"); // tells Intent that it is not from History table

                            saveCurrentAliquot();

                            startActivity(openDisplayTable); // Starts display activity

                        } else // if it is not valid, display a message
                            Toast.makeText(AliquotMenuActivity.this, "ERROR: Invalid Aliquot XML file.",
                                    Toast.LENGTH_LONG).show();

                    }

                } else
                    // Tells user to select a file for viewing
                    Toast.makeText(AliquotMenuActivity.this, "Please select an aliquot file to view.",
                            Toast.LENGTH_LONG).show(); // lets user know table is opening

            }
        });

        igsnText = (EditText) findViewById(R.id.aliquotIGSNText);
        // Checks to see if user profile information has been authenticated for private file access
        // Sets appropriate hint based on if credentials are stored or not
        retrieveCredentials();
        if (!getGeochronUsername().contentEquals("None") && !getGeochronPassword().contentEquals("None"))
            igsnText.setHint("Profile information stored. Private files enabled!");
        else
            igsnText.setHint("No profile information stored. Private files disabled.");

        Button igsnDownloadButton = (Button) findViewById(R.id.aliquotIGSNSubmitButton);
        igsnDownloadButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {

                // Hides SoftKeyboard When Download Button is Pressed
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(igsnText.getWindowToken(), 0);

                // Checks internet connection before downloading files
                ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(
                        Context.CONNECTIVITY_SERVICE);
                NetworkInfo mobileWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);

                if (mobileWifi.isConnected()) {
                    if (igsnText.getText().length() != 0) {
                        downloadAliquot();
                        igsnText.setText("");
                    }
                } else {//Handles lack of wifi connection
                    new AlertDialog.Builder(AliquotMenuActivity.this)
                            .setMessage("You are not connected to WiFi, mobile data rates may apply. "
                                    + "Do you wish to continue?")
                            // if user selects yes, continue with validation
                            .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    downloadAliquot();
                                    igsnText.setText("");
                                }
                            })
                            // if user selects no, just go back
                            .setNegativeButton("No", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    dialogInterface.dismiss();
                                }
                            }).show();
                }
            }

        });

        // displays the current Report Settings
        TextView currentReportSettingsLabel = (TextView) findViewById(R.id.aliquotCurrentReportSettingsLabel);
        currentReportSettingsLabel
                .setText("Current Report Settings:\n" + splitReportSettingsName(retrieveReportSettingsFileName()));

        // if no file permissions, asks for them
        if (ContextCompat.checkSelfPermission(this,
                android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[] { android.Manifest.permission.WRITE_EXTERNAL_STORAGE }, 1);
        }
    }

    /**
     * Accesses current report settings file
     */
    private String retrieveReportSettingsFileName() {
        SharedPreferences settings = getSharedPreferences(PREF_REPORT_SETTINGS, 0);
        return settings.getString("Current Report Settings", "Default Report Settings.xml"); // Gets current RS and if no file there, returns default as the current file
    }

    /**
     * Splits report settings file name returning a displayable version without the entire path
     */
    private String splitReportSettingsName(String fileName) {
        String[] fileNameParts = fileName.split("/");
        String name = fileNameParts[fileNameParts.length - 1];
        if (name.contains(".xml")) { // removes '.xml' from end of name
            String[] newParts = name.split(".xml");
            name = newParts[0];
        }
        return name;
    }

    /**
     * Downloads an aliquot based on the text entered into the aliquot field
     */
    public void downloadAliquot() {
        Toast.makeText(AliquotMenuActivity.this, "Downloading Aliquot...", Toast.LENGTH_SHORT).show(); // Reports that aliquot is being downloaded

        // Captures igsn from user input
        String aliquotIGSN = igsnText.getText().toString().toUpperCase().trim();

        // creates URLFileReader class to download the file
        URLFileReader downloader = new URLFileReader(AliquotMenuActivity.this, "AliquotMenu",
                makeURI(BASE_ALIQUOT_URI, aliquotIGSN), "igsn");

        downloader.startFileDownload(); // begins actual download

        // Note: Setting above is useful for download-then-open functionality
    }

    /**
     * Stores Current Aliquot
     */
    protected void saveCurrentAliquot() {
        SharedPreferences settings = getSharedPreferences(PREF_ALIQUOT, 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putString("Current Aliquot", getIntent().getStringExtra("AliquotXMLFileName")); // gets chosen file from file browser and stores
        editor.apply(); // Committing changes
    }

    @Override
    // Gets the filename that the FilePicker returns and puts it into this Intent's Extra
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == 1) {
            if (resultCode == RESULT_OK) {
                if (data.hasExtra("AliquotXMLFileName")) {
                    String result = data.getStringExtra("AliquotXMLFileName"); // Specified file name from file browser
                    getIntent().putExtra("AliquotXMLFileName", result); // put the DATA into THIS INTENT
                    String[] selectedAliquotFilePath = result.split("/"); // Splits selected file name into relevant parts
                    String fileName = selectedAliquotFilePath[selectedAliquotFilePath.length - 1]; // Creates displayable file name from split file path
                    aliquotSelectedFileText.setText(fileName); // Sets file name for displaying on aliquot file select line
                }
            }
        }
    }

    /**
     * Checks an XML file at the specified file path to see if it is a Aliquot file
     *
     * @param filePath the path to the XML file
     * @return a boolean stating whether it is valid or not
     */
    private boolean validateFile(String filePath) {
        // initializes the end result
        boolean result = false;
        String[] splitPathAtPeriod = filePath.split("\\.");

        if (splitPathAtPeriod.length > 0) { // makes sure there is something to index
            // then makes sure that the file is an XML file
            if (splitPathAtPeriod[splitPathAtPeriod.length - 1].equals("xml")) {
                try {
                    // builds the XML file to parse and checks for validity
                    File xmlFile = new File(filePath);
                    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
                    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
                    Document doc = dBuilder.parse(xmlFile);

                    // returns true if the first node is Aliquot
                    result = doc.getDocumentElement().getNodeName().equals("Aliquot");

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        // returns false if there was a different error
        return result;
    }

    /**
     * Retrieves the currently stored username and password
     * If none present, returns None
     */
    private void retrieveCredentials() {
        SharedPreferences settings = getSharedPreferences(USER_PREFS, 0);
        setGeochronUsername(settings.getString("Geochron Username", "None"));
        setGeochronPassword(settings.getString("Geochron Password", "None"));
    }

    /**
     * Creates URL from the constant GeoChron URL and IGSN
     */
    public static String makeURI(String baseURL, String IGSN) {
        String URI = baseURL + IGSN;
        if (!getGeochronUsername().contentEquals("None") && !getGeochronPassword().contentEquals("None")) {
            // Create unique URL and password if credentials stored
            URI += "&username=" + getGeochronUsername() + "&password=" + getGeochronPassword();
        }
        return URI;
    }

    public static String getGeochronUsername() {
        return geochronUsername;
    }

    public void setGeochronUsername(String geochronUser) {
        geochronUsername = geochronUser;
    }

    public static String getGeochronPassword() {
        return geochronPassword;
    }

    public void setGeochronPassword(String geochronPass) {
        geochronPassword = geochronPass;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu, menu);
        return true;
    }

    /**
     * The purpose of overriding this method is to alter/delete some of the menu items from the default
     * menu, as they are not wanted in this Activity. Doing so prevents the unnecessary stacking of
     * Activities by making the user follow the intended flow of Activities in the application.
     *
     * @param menu the menu that has been inflated in the Activity
     * @return true so that the menu is displayed
     */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // removes the History item from the menu
        MenuItem historyItem = menu.findItem(R.id.historyMenu);
        historyItem.setVisible(false);

        // removes the Edit Credentials item from the menu
        MenuItem credentialsItem = menu.findItem(R.id.editProfileMenu);
        credentialsItem.setVisible(false);

        MenuItem viewFiles = menu.findItem(R.id.viewFilesMenu);
        viewFiles.setVisible(false);

        // if coming from a Table Activity, changes Main Menu item to say "Back to Table"
        if (getIntent().hasExtra("From_Table")) {
            if (getIntent().getStringExtra("From_Table").equals("true")) {
                MenuItem backItem = menu.findItem(R.id.returnToMenu);
                backItem.setTitle("Back to Table");
            }
        }

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handles menu item selection
        switch (item.getItemId()) {
        case R.id.returnToMenu: // Takes user to main menu by finishing the Activity
            finish();
            return true;
        case R.id.viewAliquotsMenu: // Takes user to aliquot menu
            Intent openAliquotFiles = new Intent("android.intent.action.FILEPICKER");
            openAliquotFiles.putExtra("Default_Directory", "From_Aliquot_Directory");
            startActivityForResult(openAliquotFiles, 1);
            return true;
        case R.id.viewReportSettingsMenu: // Takes user to report settings menu
            Intent openReportSettingsFiles = new Intent("android.intent.action.FILEPICKER");
            openReportSettingsFiles.putExtra("Default_Directory", "Report_Settings_Directory");
            startActivity(openReportSettingsFiles);
            return true;
        case R.id.importFilesMenu: // Takes user to import files menu
            Intent importFiles = new Intent("android.intent.action.IMPORTFILES");
            startActivity(importFiles);
            return true;
        case R.id.viewRootMenu:
            Intent openRootDirectory = new Intent("android.intent.action.FILEPICKER");
            openRootDirectory.putExtra("Default_Directory", "Root_Directory");
            startActivity(openRootDirectory);
            return true;
        case R.id.aboutScreen: // Takes user to about screen
            Intent openAboutScreen = new Intent("android.intent.action.ABOUT");
            startActivity(openAboutScreen);
            return true;
        case R.id.helpMenu: // Takes user to help blog
            // Checks internet connection before downloading files
            ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(
                    Context.CONNECTIVITY_SERVICE);
            NetworkInfo mobileWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);

            if (mobileWifi.isConnected()) {
                Intent openHelpBlog = new Intent(Intent.ACTION_VIEW,
                        Uri.parse(getString(R.string.chroni_help_address)));
                startActivity(openHelpBlog);

            } else {
                new AlertDialog.Builder(this)
                        .setMessage("You are not connected to WiFi, mobile data rates may apply. "
                                + "Do you wish to continue?")
                        .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                Intent openHelpBlog = new Intent(Intent.ACTION_VIEW,
                                        Uri.parse(getString(R.string.chroni_help_address)));
                                startActivity(openHelpBlog);
                            }
                        }).setNegativeButton("No", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                dialogInterface.dismiss();
                            }
                        }).show();
            }
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }
}