com.gmail.srivi.sundaram.locgenie.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.gmail.srivi.sundaram.locgenie.MainActivity.java

Source

/******************************************************************************* 
  LocGenie  An open source Android application that suggests users places of their preferred activity within their 
  preferred distance in Map View along with their address.
     
  Copyright (C) 2014 Srividya Sundaram
     
  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/.
     
  Following is the link for the repository: https://github.com/Srividya2212/LocationFinder
     
  Please, see the file license in this distribution for license terms. Link is
  https://github.com/Srividya2212/LocationFinder/blob/master/LICENSE.md
     
  References:
  https://developers.google.com/maps/documentation/android/start#getting_the_google_maps_android_api_v2
  https://developers.google.com/maps/documentation/android/
  https://developers.google.com/places/documentation/
  https://developers.google.com/places/documentation/search
  http://stackoverflow.com/questions/9605913/how-to-parse-json-in-android
     
 Author - Srividya Sundaram
 email: srividya@pdx.edu
    
******************************************************************************************/

package com.gmail.srivi.sundaram.locgenie;

import com.gmail.srivi.sundaram.locgenie.R;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
//import com.google.android.gms.maps.model.MarkerOptions;
import android.content.Intent;
import android.content.IntentSender;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.drawable.AnimationDrawable;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Locale;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.os.AsyncTask;

/**
 * This the app's main Activity. It provides buttons for requesting the various
 * features of the app, displays the current location, the current address, and
 * the status of the location client and updating services. hi
 * {@link #getLocation} gets the current location using the Location Services
 * getLastLocation() function. {@link #getAddress} calls geocoding to get a
 * street address for the current location. {@link #startUpdates} sends a
 * request to Location Services to send periodic location updates to the
 * Activity. {@link #stopUpdates} cancels previous periodic update requests.
 * 
 * The update interval is hard-coded to be 5 seconds.
 */
public class MainActivity extends FragmentActivity implements LocationListener,
        GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener {

    // private int userIcon;
    public final static String EXTRA_MESSAGE = "com.android.location.suggestion.MESSAGE";
    public final static String RADIUS = "com.android.location.suggestion.RADIUS";
    public final static String ACTIVITY = "com.android.location.suggestion.ACTIVITY";
    // A request to connect to Location Services
    private LocationRequest mLocationRequest;

    private LocationClient mLocationClient;

    // Handles to UI widgets
    private TextView mLatLng;
    private TextView mAddress;
    private ProgressBar mActivityIndicator;
    private TextView mConnectionState;
    private TextView mConnectionStatus;

    // Handle to SharedPreferences for this app
    SharedPreferences mPrefs;

    // Handle to a SharedPreferences editor
    SharedPreferences.Editor mEditor;

    boolean mUpdatesRequested = false;
    AnimationDrawable frameAnimation;
    ImageView view;

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

        mLocationRequest = LocationRequest.create();
        mLocationRequest.setInterval(LocationUtils.UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setFastestInterval(LocationUtils.FAST_INTERVAL_CEILING_IN_MILLISECONDS);
        mUpdatesRequested = false;
        mPrefs = getSharedPreferences(LocationUtils.SHARED_PREFERENCES, Context.MODE_PRIVATE);
        mEditor = mPrefs.edit();
        mLocationClient = new LocationClient(this, this, this);
    }

    /*   @Override
       public void onWindowFocusChanged(boolean hasFocus) {
           super.onWindowFocusChanged(hasFocus);
     if (hasFocus) {
          // Starting the animation when in Focus
          frameAnimation.start();
          } else {
          frameAnimation.stop();
     }
       }*/

    /*
     * Called when the Activity is no longer visible at all. Stop updates and
     * disconnect.
     */
    @Override
    public void onStop() {

        if (mLocationClient.isConnected()) {
            stopPeriodicUpdates();
        }

        mLocationClient.disconnect();

        super.onStop();
    }

    /*
     * Called when the Activity is going into the background. Parts of the UI
     * may be visible, but the Activity is inactive.
     */
    @Override
    public void onPause() {
        Log.d(" -->", "In onPause");

        // Save the current setting for updates
        mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED, mUpdatesRequested);
        mEditor.commit();

        super.onPause();
    }

    /*
     * Called when the Activity is restarted, even before it becomes visible.
     */
    @Override
    public void onStart() {
        Log.d("2", "In onStart");
        // Toast.makeText(this, "Inside Onstart()", Toast.LENGTH_SHORT).show();
        super.onStart();

        /*
         * Connect the client. Don't re-start any requests here; instead, wait
         * for onResume()
         */
        mLocationClient.connect();

    }

    /*
     * Called when the system detects that this Activity is now visible.
     */
    @Override
    public void onResume() {
        super.onResume();

        // If the app already has a setting for getting location updates, get it
        if (mPrefs.contains(LocationUtils.KEY_UPDATES_REQUESTED)) {
            mUpdatesRequested = mPrefs.getBoolean(LocationUtils.KEY_UPDATES_REQUESTED, false);

            // Otherwise, turn off location updates until requested
        } else {
            mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED, false);
            mEditor.commit();
        }

    }

    /*
     * Handle results returned to this Activity by other Activities started with
     * startActivityForResult(). In particular, the method onConnectionFailed()
     * in LocationUpdateRemover and LocationUpdateRequester may call
     * startResolutionForResult() to start an Activity that handles Google Play
     * services problems. The result of this call returns here, to
     * onActivityResult.
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {

        // Choose what to do based on the request code
        switch (requestCode) {

        // If the request code matches the code sent in onConnectionFailed
        case LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST:

            switch (resultCode) {
            // If Google Play services resolved the problem
            case Activity.RESULT_OK:

                // Log the result
                Log.d(LocationUtils.APPTAG, getString(R.string.resolved));

                // Display the result
                // mConnectionState.setText(R.string.connected);
                // mConnectionStatus.setText(R.string.resolved);
                break;

            // If any other result was returned by Google Play services
            default:
                // Log the result
                Log.d(LocationUtils.APPTAG, getString(R.string.no_resolution));

                // Display the result
                // mConnectionState.setText(R.string.disconnected);
                // mConnectionStatus.setText(R.string.no_resolution);

                break;
            }

            // If any other request code was received
        default:
            // Report that this Activity received an unknown requestCode
            Log.d(LocationUtils.APPTAG, getString(R.string.unknown_activity_request_code, requestCode));

            break;
        }
    }

    /**
     * Verify that Google Play services is available before making a request.
     * 
     * @return true if Google Play services is available, otherwise false
     */
    private boolean servicesConnected() {

        // Check that Google Play services is available
        int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);

        // If Google Play services is available
        if (ConnectionResult.SUCCESS == resultCode) {
            // In debug mode, log the status
            Log.d(LocationUtils.APPTAG, getString(R.string.play_services_available));

            // Continue
            return true;
            // Google Play services was not available for some reason
        } else {
            // Display an error dialog
            Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode, this, 0);
            if (dialog != null) {
                ErrorDialogFragment errorFragment = new ErrorDialogFragment();
                errorFragment.setDialog(dialog);
                errorFragment.show(getSupportFragmentManager(), LocationUtils.APPTAG);
            }
            return false;
        }
    }

    /**
     * Invoked by the "Get Location" button.
     * 
     * Calls getLastLocation() to get the current location
     * 
     * @param v
     *            The view object associated with this method, in this case a
     *            Button.
     */
    public void getLocation(View v) {

        // If Google Play Services is available
        if (servicesConnected()) {
            Log.d(" ", "In getLocation method");

            // Toast.makeText(this, "Inside method getLocation()",
            // Toast.LENGTH_SHORT)
            // .show();

            // Get the current location
            Location currentLocation = mLocationClient.getLastLocation();

            // Display the current location in the UI
            mLatLng.setText(LocationUtils.getLatLng(this, currentLocation));
            // Toast.makeText(this, LocationUtils.getLatLng(this,
            // currentLocation), Toast.LENGTH_SHORT).show();

        }
    }

    // Invoked by Suggestions button

    public void getSuggestion(View v) {

        if (servicesConnected()) {
            Log.d(" ", "In getSuggestions_new");
            EditText radius = (EditText) findViewById(R.id.editText1);
            String radiusCheck = radius.getText().toString();
            // Getting the Selected Activity
            RadioGroup rg = (RadioGroup) findViewById(R.id.radioGroup1);
            RadioButton selected = (RadioButton) findViewById(rg.getCheckedRadioButtonId());
            String activity = (String) selected.getText();
            if (radiusCheck.isEmpty()) {
                Toast.makeText(this, "Please Enter Radius", Toast.LENGTH_SHORT).show();
            } else {
                float miles = Float.valueOf(radius.getText().toString());
                float meters = (float) (miles * 1609.344);
                String radiusInMeters = Float.toString(meters);
                Location currentLocation = mLocationClient.getLastLocation();
                Intent intent = new Intent(getBaseContext(), DisplayPlacesActivity.class);
                intent.putExtra(EXTRA_MESSAGE, currentLocation);
                intent.putExtra(RADIUS, radiusInMeters);
                intent.putExtra(ACTIVITY, activity);
                startActivity(intent);
            }

        }
    }

    /**
     * Invoked by the "Get Address" button. Get the address of the current
     * location, using reverse geocoding. This only works if a geocoding service
     * is available.
     * 
     * @param v
     *            The view object associated with this method, in this case a
     *            Button.
     */
    // For Eclipse with ADT, suppress warnings about Geocoder.isPresent()
    @SuppressLint("NewApi")
    public void getAddress(View v) {

        // In Gingerbread and later, use Geocoder.isPresent() to see if a
        // geocoder is available.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD && !Geocoder.isPresent()) {
            // No geocoder is present. Issue an error message
            Toast.makeText(this, R.string.no_geocoder_available, Toast.LENGTH_LONG).show();
            return;
        }

        if (servicesConnected()) {

            // Get the current location
            Location currentLocation = mLocationClient.getLastLocation();

            // Turn the indefinite activity indicator on
            // mActivityIndicator.setVisibility(View.VISIBLE);

            // Start the background task
            (new MainActivity.GetAddressTask(this)).execute(currentLocation);
        }
    }

    /**
     * Invoked by the "Start Updates" button Sends a request to start location
     * updates
     * 
     * @param v
     *            The view object associated with this method, in this case a
     *            Button.
     */
    public void startUpdates(View v) {
        mUpdatesRequested = true;

        if (servicesConnected()) {
            startPeriodicUpdates();
        }
    }

    /**
     * Invoked by the "Stop Updates" button Sends a request to remove location
     * updates request them.
     * 
     * @param v
     *            The view object associated with this method, in this case a
     *            Button.
     */
    public void stopUpdates(View v) {
        mUpdatesRequested = false;

        if (servicesConnected()) {
            stopPeriodicUpdates();
        }
    }

    /*
     * Called by Location Services when the request to connect the client
     * finishes successfully. At this point, you can request the current
     * location or start periodic updates
     */
    @Override
    public void onConnected(Bundle bundle) {
        Log.d(" ", "In onConnected");
        // mConnectionStatus.setText(R.string.connected);
        // Toast.makeText(this, "Inside Onconnected()",
        // Toast.LENGTH_SHORT).show();
        if (mUpdatesRequested) {
            startPeriodicUpdates();
        }
    }

    /*
     * Called by Location Services if the connection to the location client
     * drops because of an error.
     */
    @Override
    public void onDisconnected() {
        // mConnectionStatus.setText(R.string.disconnected);
    }

    /*
     * Called by Location Services if the attempt to Location Services fails.
     */
    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {

        /*
         * Google Play services can resolve some errors it detects. If the error
         * has a resolution, try sending an Intent to start a Google Play
         * services activity that can resolve error.
         */
        if (connectionResult.hasResolution()) {
            try {

                // Start an Activity that tries to resolve the error
                connectionResult.startResolutionForResult(this,
                        LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST);

                /*
                 * Thrown if Google Play services canceled the original
                 * PendingIntent
                 */

            } catch (IntentSender.SendIntentException e) {

                // Log the error
                e.printStackTrace();
            }
        } else {

            // If no resolution is available, display a dialog to the user with
            // the error.
            showErrorDialog(connectionResult.getErrorCode());
        }
    }

    /**
     * Report location updates to the UI.
     * 
     * @param location
     *            The updated location.
     */
    @Override
    public void onLocationChanged(Location location) {

        // Report to the UI that the location was updated
        // mConnectionStatus.setText(R.string.location_updated);

        // In the UI, set the latitude and longitude to the value received
        mLatLng.setText(LocationUtils.getLatLng(this, location));
    }

    /**
     * In response to a request to start updates, send a request to Location
     * Services
     */
    private void startPeriodicUpdates() {

        mLocationClient.requestLocationUpdates(mLocationRequest, this);
        // mConnectionState.setText(R.string.location_requested);
    }

    /**
     * In response to a request to stop updates, send a request to Location
     * Services
     */
    private void stopPeriodicUpdates() {
        mLocationClient.removeLocationUpdates(this);
        // mConnectionState.setText(R.string.location_updates_stopped);
    }

    /**
     * An AsyncTask that calls getFromLocation() in the background. The class
     * uses the following generic types: Location - A
     * {@link android.location.Location} object containing the current location,
     * passed as the input parameter to doInBackground() Void - indicates that
     * progress units are not used by this subclass String - An address passed
     * to onPostExecute()
     */
    protected class GetAddressTask extends AsyncTask<Location, Void, String> {

        // Store the context passed to the AsyncTask when the system
        // instantiates it.
        Context localContext;

        // Constructor called by the system to instantiate the task
        public GetAddressTask(Context context) {

            // Required by the semantics of AsyncTask
            super();

            // Set a Context for the background task
            localContext = context;
        }

        /**
         * Get a geocoding service instance, pass latitude and longitude to it,
         * format the returned address, and return the address to the UI thread.
         */
        @Override
        protected String doInBackground(Location... params) {
            /*
             * Get a new geocoding service instance, set for localized
             * addresses. This example uses android.location.Geocoder, but other
             * geocoders that conform to address standards can also be used.
             */
            Geocoder geocoder = new Geocoder(localContext, Locale.getDefault());

            // Get the current location from the input parameter list
            Location location = params[0];

            // Create a list to contain the result address
            List<Address> addresses = null;

            // Try to get an address for the current location. Catch IO or
            // network problems.
            try {

                /*
                 * Call the synchronous getFromLocation() method with the
                 * latitude and longitude of the current location. Return at
                 * most 1 address.
                 */
                addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);

                // Catch network or other I/O problems.
            } catch (IOException exception1) {

                // Log an error and return an error message
                Log.e(LocationUtils.APPTAG, getString(R.string.IO_Exception_getFromLocation));

                // print the stack trace
                exception1.printStackTrace();

                // Return an error message
                return (getString(R.string.IO_Exception_getFromLocation));

                // Catch incorrect latitude or longitude values
            } catch (IllegalArgumentException exception2) {

                // Construct a message containing the invalid arguments
                String errorString = getString(R.string.illegal_argument_exception, location.getLatitude(),
                        location.getLongitude());
                // Log the error and print the stack trace
                Log.e(LocationUtils.APPTAG, errorString);
                exception2.printStackTrace();

                //
                return errorString;
            }
            // If the reverse geocode returned an address
            if (addresses != null && addresses.size() > 0) {

                // Get the first address
                Address address = addresses.get(0);

                // Format the first line of address
                String addressText = getString(R.string.address_output_string,

                        // If there's a street address, add it
                        address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "",

                        // Locality is usually a city
                        address.getLocality(),

                        // The country of the address
                        address.getCountryName());

                // Return the text
                return addressText;

                // If there aren't any addresses, post a message
            } else {
                return getString(R.string.no_address_found);
            }
        }

        /**
         * A method that's called once doInBackground() completes. Set the text
         * of the UI element that displays the address. This method runs on the
         * UI thread.
         */
        @Override
        protected void onPostExecute(String address) {

            // Turn off the progress bar
            // mActivityIndicator.setVisibility(View.GONE);

            // Set the address in the UI
            // mAddress.setText(address);
        }
    }

    /**
     * Show a dialog returned by Google Play services for the connection error
     * code
     * 
     * @param errorCode
     *            An error code returned from onConnectionFailed
     */
    private void showErrorDialog(int errorCode) {

        // Get the error dialog from Google Play services
        Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(errorCode, this,
                LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST);

        // If Google Play services can provide an error dialog
        if (errorDialog != null) {

            // Create a new DialogFragment in which to show the error dialog
            ErrorDialogFragment errorFragment = new ErrorDialogFragment();

            // Set the dialog in the DialogFragment
            errorFragment.setDialog(errorDialog);

            // Show the error dialog in the DialogFragment
            errorFragment.show(getSupportFragmentManager(), LocationUtils.APPTAG);
        }
    }

    /**
     * Define a DialogFragment to display the error dialog generated in
     * showErrorDialog.
     */
    public static class ErrorDialogFragment extends DialogFragment {

        // Global field to contain the error dialog
        private Dialog mDialog;

        /**
         * Default constructor. Sets the dialog field to null
         */
        public ErrorDialogFragment() {
            super();
            mDialog = null;
        }

        /**
         * Set the dialog to display
         * 
         * @param dialog
         *            An error dialog
         */
        public void setDialog(Dialog dialog) {
            mDialog = dialog;
        }

        /*
         * This method must return a Dialog to the DialogFragment.
         */
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            return mDialog;
        }
    }
}