com.anton.gavel.GavelMain.java Source code

Java tutorial

Introduction

Here is the source code for com.anton.gavel.GavelMain.java

Source

/*
 * This file is part of Gavel for Android.
    
Gavel for Android 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.
    
Gavel for Android 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 Gavel for Android.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package com.anton.gavel;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.anton.gavel.PersonalInfoDialogFragment.PersonalInfoListener;

import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.DialogFragment;
import android.text.InputType;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.TextView;

public class GavelMain extends SherlockFragmentActivity
        implements PersonalInfoListener, OnItemSelectedListener, OnItemLongClickListener, OnClickListener {
    private static final int DIALOG_PI = 1;
    private static final int DIALOG_ABOUT = 2;
    private static final int DIALOG_SUBMISSION_ERR = 3;
    private static final int DIALOG_OTHER_COMPLAINT = 4;
    private static final int DIALOG_NO_GEOCODING = 5;
    private static final int DIALOG_INCOMPLETE_PERSONAL_INFORMATION = 6;
    private static final int DIALOG_NO_COMPLAINT = 7;
    private static final int DIALOG_NO_LOCATION = 8;
    private Spinner complaintSpinner;
    private ArrayAdapter<String> complaintsAdapter;
    private List<String> standardComplaints = null;
    private List<String> complaintSubmitValues = null;
    private PersonalInfo mPersonalInfo = null;
    private ProgressDialog progressDialog;
    private Map<String, String> complaintsMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_gavel_main);

        // set up edit text input style for complaints (multiline, capitalize sentences)
        EditText edit = (EditText) findViewById(R.id.complaint_body);
        edit.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
                | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
        // set up cities spinner
        Spinner citiesSpinner = (Spinner) findViewById(R.id.cities_spinner);
        ArrayAdapter<CharSequence> citiesAdapter = ArrayAdapter.createFromResource(this, R.array.cities,
                android.R.layout.simple_spinner_item);
        citiesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        citiesSpinner.setAdapter(citiesAdapter);

        // set up complaints map
        List<String> standardComplaints = this.getStandardComplaints();
        List<String> complaintSubmitValues = this.getComplaintSubmitValues();

        Iterator<String> standard = standardComplaints.iterator();
        Iterator<String> submit = complaintSubmitValues.iterator();
        complaintsMap = new HashMap<String, String>();
        //standard.next(); submit.next(); //skip the first item 'select a complaint'
        while (standard.hasNext() && submit.hasNext())
            complaintsMap.put(standard.next().toString(), submit.next().toString());

        // set up complaint spinner
        List<String> complaints_list = this.getStandardComplaints();
        complaintSpinner = (Spinner) findViewById(R.id.complaint_spinner);
        complaintsAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item,
                complaints_list);
        complaintsAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        complaintSpinner.setAdapter(complaintsAdapter);
        complaintSpinner.setOnItemSelectedListener(this);
        complaintSpinner.setOnItemLongClickListener(this);// this doesn't actually work yet bc not supported by API - events don't get fired

        //attach location listener to button
        findViewById(R.id.location_button).setOnClickListener(this);

        // make link in disclaimer clickable
        TextView disclaimer = (TextView) findViewById(R.id.disclaimer_textview);
        disclaimer.setMovementMethod(LinkMovementMethod.getInstance());

        // check &or load shared preferences to populate saved personal information
        mPersonalInfo = new PersonalInfo();
        SharedPreferences preferences = getPreferences(MODE_PRIVATE);
        mPersonalInfo.loadFromPreferences(preferences);

        // suppress keyboard
        this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

        // set complaint location to multiline for large layouts
        if (findViewById(R.id.layout_large_land) != null || findViewById(R.id.layout_large) != null) {
            ((EditText) findViewById(R.id.complaint_address)).setInputType(InputType.TYPE_CLASS_TEXT
                    | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
        }

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getSupportMenuInflater();
        // Inflate the menu; this adds items to the action bar if it is present.
        inflater.inflate(R.menu.activity_gavel_main, menu);
        getSupportActionBar().setDisplayShowHomeEnabled(false);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.menu_personal_info:
            this.createDialog(DIALOG_PI);
            return true;
        case R.id.menu_about:
            this.createDialog(DIALOG_ABOUT);
            return true;
        case R.id.menu_send_complaint:

            if (mPersonalInfo.isComplete()) {

                progressDialog = ProgressDialog.show(this, "Sending", "Uploading your complaint");

                //turn progress bar on

                // get location
                String location = ((EditText) findViewById(R.id.complaint_address)).getText().toString();

                if (String.valueOf(location).equals("")) {
                    createDialog(DIALOG_NO_LOCATION);
                    return true;
                }

                //get complaint
                String userComplaint = ((Spinner) findViewById(R.id.complaint_spinner)).getSelectedItem()
                        .toString();

                String complaint = complaintsMap.get(userComplaint);//retrieve submission value for complaint
                String otherComplaint = "";

                if (String.valueOf(complaint).equals("")) {
                    createDialog(DIALOG_NO_COMPLAINT);
                    return true;
                }
                //corresponds to 'select a complaint' 
                else if (complaint == null) {
                    complaint = "Other";
                    otherComplaint = userComplaint;
                } //if complaint is not in the standard complaintsMap, it is a custom complaint

                Map<String, String> myComplaintValues = new HashMap<String, String>();
                myComplaintValues.put("firstName",
                        ((EditText) findViewById(R.id.complaint_first_name)).getText().toString() + "");
                myComplaintValues.put("secondName",
                        ((EditText) findViewById(R.id.complaint_last_name)).getText().toString() + "");
                myComplaintValues.put("location",
                        ((EditText) findViewById(R.id.complaint_address)).getText().toString());
                myComplaintValues.put("city",
                        ((Spinner) findViewById(R.id.cities_spinner)).getSelectedItem().toString());
                myComplaintValues.put("complaintDetails",
                        ((EditText) findViewById(R.id.complaint_body)).getText().toString());
                myComplaintValues.put("complaint", complaint);
                myComplaintValues.put("otherComplaint", otherComplaint);

                ComplaintSubmission submission = new ComplaintSubmission(this, mPersonalInfo, myComplaintValues);
                submission.submit();

            } else {
                createDialog(DIALOG_INCOMPLETE_PERSONAL_INFORMATION);
            }

            return true;

        default:
            return true;
        }
    }

    Handler submissionHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            Bundle bundle = msg.getData();
            Boolean succeeded = bundle.getBoolean("succeeded");

            if (succeeded) {
                //refresh activity
                finish();
                startActivity(getIntent());

            } else {
                createDialog(DIALOG_SUBMISSION_ERR);
            }
        }
    }; // handles response from form submission.

    public void createDialog(int id) {
        if (progressDialog != null) {
            progressDialog.dismiss();
        }
        // handles creation of any dialogs by other actions
        switch (id) {
        case DIALOG_PI:
            //call custom dialog for collecting Personal Info
            PersonalInfoDialogFragment personalInfoDialog = new PersonalInfoDialogFragment();
            personalInfoDialog.setPersonalInfo(mPersonalInfo);
            personalInfoDialog.show(getSupportFragmentManager(), "PersonalInfoDialogFragment");
            break;
        case DIALOG_ABOUT:
            //construct a simple dialog to show text

            //get about text
            TextView aboutView = new TextView(this);
            aboutView.setText(R.string.about_text);
            aboutView.setMovementMethod(LinkMovementMethod.getInstance());//enable links
            aboutView.setPadding(50, 30, 50, 30);

            //build dialog
            AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
            alertDialog.setTitle("About")//title
                    .setView(aboutView)//insert textview from above
                    .setPositiveButton("Done", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    }).setIcon(R.drawable.ic_launcher).create() //build
                    .show(); //display
            break;

        case DIALOG_SUBMISSION_ERR:
            AlertDialog.Builder submissionErrorDialog = new AlertDialog.Builder(this);
            submissionErrorDialog.setTitle("Submission Error")//title
                    .setMessage("There was a problem submitting your complaint on the City's website.")//insert textview from above
                    .setPositiveButton("Done", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    }).setIcon(R.drawable.ic_launcher).show(); //display
            break;

        case DIALOG_OTHER_COMPLAINT:
            final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            final EditText input = new EditText(this);
            input.setInputType(InputType.TYPE_TEXT_FLAG_CAP_WORDS | InputType.TYPE_CLASS_TEXT);
            // capitalize letters + seperate words
            AlertDialog.Builder getComplaintDialog = new AlertDialog.Builder(this);
            getComplaintDialog.setTitle("Other...").setView(input)
                    .setMessage("Give a categorical title for your complaint:")
                    .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            String value = input.getText().toString();
                            // add the item to list and make it selected
                            complaintsAdapter.insert(value, 0);
                            complaintSpinner.setSelection(0);
                            complaintsAdapter.notifyDataSetChanged();
                            addToSubmitValues(value);

                            imm.toggleSoftInput(InputMethodManager.RESULT_HIDDEN, 0);//hide keyboard   
                            dialog.cancel();

                        }
                    }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            imm.toggleSoftInput(InputMethodManager.RESULT_HIDDEN, 0);//hide keyboard              
                            dialog.cancel();
                        }
                    }).create();

            input.requestFocus();
            imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);// show keyboard

            getComplaintDialog.show();//show dialog
            break;
        case DIALOG_NO_GEOCODING:
            AlertDialog.Builder noGeoCoding = new AlertDialog.Builder(this);
            noGeoCoding.setTitle("Not Available")//title
                    .setMessage(
                            "Your version of Android does not support location-based address lookup. This feature is only supported on Gingerbread and above.")//insert textview from above
                    .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    }).setIcon(R.drawable.ic_launcher).show(); //display
            break;
        case DIALOG_INCOMPLETE_PERSONAL_INFORMATION:
            AlertDialog.Builder incompleteInfo = new AlertDialog.Builder(this);
            incompleteInfo.setTitle("Incomplete")//title
                    .setMessage(
                            "Your personal information is incomplete. Select 'Edit Personal Information' from the menu and fill in all required fields")//insert textview from above
                    .setPositiveButton("Done", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    }).setIcon(R.drawable.ic_launcher).show(); //display         
            break;
        case DIALOG_NO_COMPLAINT:
            AlertDialog.Builder noComplaint = new AlertDialog.Builder(this);
            noComplaint.setTitle("No Comlaint Specified")//title
                    .setMessage("You must specify a complaint (e.g. barking dog).")//insert textview from above
                    .setPositiveButton("Done", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    }).setIcon(R.drawable.ic_launcher).show(); //display
            break;
        case DIALOG_NO_LOCATION:
            AlertDialog.Builder incompleteComplaint = new AlertDialog.Builder(this);
            incompleteComplaint.setTitle("No Location Specified")//title
                    .setMessage("You must specify a location (approximate street address) of the complaint.")//insert textview from above
                    .setPositiveButton("Done", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    }).setIcon(R.drawable.ic_launcher).show(); //display         
        }

    }

    @Override
    public void onDialogPositiveClick(DialogFragment Dialog) {
        //this method handles return of Personal Information dialog

        if (Dialog instanceof PersonalInfoDialogFragment) {
            mPersonalInfo = ((PersonalInfoDialogFragment) Dialog).getPersonalInfo();
            //Log.d("Runs", mPersonalInfo.toString());

            // save personal information to file.
            SharedPreferences preferences = getPreferences(MODE_PRIVATE);
            mPersonalInfo.saveToPreferences(preferences);
        }
    }
    /*
    @Override
    public void onDialogNegativeClick(DialogFragment Dialog) {
       // TODO Auto-generated method stub   
    } */ //method to handle 'cancel' of Personal Information Dialog

    @Override
    public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        // handles clicks on complaintSpinner Items - get/add new complaint

        EditText complaintBox = (EditText) findViewById(R.id.complaint_body);

        if (complaintSpinner.getSelectedItem().toString().equals("Other...")) {

            complaintBox.setHint(getResources().getString(R.string.hint_complaint_details));
            createDialog(DIALOG_OTHER_COMPLAINT);

        } else {
            //put custom hint in complaint details box

            //make a map of complaints (as seen in spinner) to complaints (as should be submitted to web)
            List<String> standardComplaints = this.getStandardComplaints();
            List<String> complaintSubmitValues = this.getComplaintSubmitValues();

            Iterator<String> standard = standardComplaints.iterator();
            Iterator<String> submit = complaintSubmitValues.iterator();
            Map<String, String> complaintValues = new HashMap<String, String>();
            while (standard.hasNext() && submit.hasNext())
                complaintValues.put(standard.next(), submit.next());
            complaintValues.put("Other", "Other");//just in case i use "Other" it should still map
            //String selectedItem = complaintSpinner.getSelectedItem().toString();
            String specific = complaintValues.get(complaintSpinner.getSelectedItem().toString());
            String hint = "describe your complaint"
                    + (specific == null || specific == "" ? "" : " about " + specific);

            complaintBox.setHint(hint);

        }

    }

    public List<String> getStandardComplaints() {
        if (standardComplaints == null)
            standardComplaints = new ArrayList<String>(
                    Arrays.asList(this.getResources().getStringArray(R.array.complaints)));

        return standardComplaints;
    }

    public List<String> getComplaintSubmitValues() {
        if (complaintSubmitValues == null)
            complaintSubmitValues = new ArrayList<String>(
                    Arrays.asList(this.getResources().getStringArray(R.array.complaint_submit_vals)));

        return complaintSubmitValues;
    }

    public void addToSubmitValues(String key) {
        getComplaintSubmitValues();
        complaintSubmitValues.add(0, "");

    }

    @Override
    public void onNothingSelected(AdapterView<?> arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean onItemLongClick(AdapterView<?> arg0, View arg1, final int position, long arg3) {
        //handles long-press on list item and deletes them
        //this doesn't do anything because Spinners don't support long clicks (last known Dec, 2012)
        AlertDialog.Builder deleteItem = new AlertDialog.Builder(this);
        deleteItem.setTitle("Delete").setMessage("Delete '" + complaintsAdapter.getItem(position) + "'?")
                .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        complaintsAdapter.remove(complaintsAdapter.getItem(position));
                    }
                }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                    }
                }).show();

        return false;
    }

    @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    @Override
    public void onClick(View arg0) {
        //click listener for location button

        LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_FINE);
        criteria.setPowerRequirement(Criteria.POWER_HIGH);
        //String provider = locationManager.getBestProvider(criteria, true);

        locationManager.requestSingleUpdate(criteria, new LocationListener() {
            @Override
            public void onLocationChanged(Location location) {
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD)
                    createDialog(DIALOG_NO_GEOCODING);
                else if (Geocoder.isPresent())
                    (new ReverseGeocodingTask(getBaseContext())).execute(new Location[] { location });
                // Invoking reverse geocoding in an AsyncTask. 
            }

            @Override
            public void onProviderDisabled(String provider) {
            }

            @Override
            public void onProviderEnabled(String provider) {
            }

            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {
            }

        }, null);

    }

    // AsyncTask encapsulating the reverse-geocoding API.  Since the geocoder API is blocked,
    // we do not want to invoke it from the UI thread.
    private class ReverseGeocodingTask extends AsyncTask<Location, Void, List<Address>> {
        Context mContext;

        public ReverseGeocodingTask(Context context) {
            super();
            mContext = context;
        }

        @Override
        protected List<Address> doInBackground(Location... params) {
            Geocoder geocoder = new Geocoder(mContext, Locale.getDefault());

            Location loc = params[0];
            List<Address> addresses = null;
            try {
                // Call the synchronous getFromLocation() method by passing in the lat/long values.
                addresses = geocoder.getFromLocation(loc.getLatitude(), loc.getLongitude(), 1);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (addresses != null && addresses.size() > 0) {
                //Address address = addresses.get(0);
                // Format the first line of address (if available), city, and country name.
                /*
                String addressText = String.format("%s, %s, %s",
                   address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "",
                   address.getLocality(),
                   address.getCountryName()); */
            }
            return addresses;
        }

        protected void onPostExecute(List<Address> result) {

            String address = "";
            if (result != null) {
                for (int i = 0; i <= result.get(0).getMaxAddressLineIndex(); i++) {
                    address += " " + result.get(0).getAddressLine(i);
                }
                address.trim();

            } else {
                address = "failed";
            } // if address == null, output 'failed', since dialogs don't work from here

            ((EditText) findViewById(R.id.complaint_address)).setText(address);
        }
    }
}