org.croudtrip.fragments.join.JoinSearchFragment.java Source code

Java tutorial

Introduction

Here is the source code for org.croudtrip.fragments.join.JoinSearchFragment.java

Source

/*
 * The CroudTrip! application aims at revolutionizing the car-ride-sharing market with its easy,
 * user-friendly and highly automated way of organizing shared Trips. Copyright (C) 2015  Nazeeh Ammari,
 *  Philipp Eichhorn, Ricarda Hohn, Vanessa Lange, Alexander Popp, Frederik Simon, Michael Weber
 * This program is free software: you can redistribute it and/or modify  it under the terms of the GNU
 *  Affero 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 Affero General Public License for more details.
 *  You should have received a copy of the GNU Affero General Public License along with this program.
 *    If not, see http://www.gnu.org/licenses/.
 */

package org.croudtrip.fragments.join;

import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.gc.materialdesign.views.Slider;
import com.getbase.floatingactionbutton.FloatingActionButton;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.common.GooglePlayServicesRepairableException;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.location.places.Place;
import com.google.android.gms.location.places.PlaceBuffer;
import com.google.android.gms.location.places.Places;
import com.google.android.gms.location.places.ui.PlacePicker;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.pnikosis.materialishprogress.ProgressWheel;

import org.croudtrip.Constants;
import org.croudtrip.MainApplication;
import org.croudtrip.R;
import org.croudtrip.db.DatabaseHelper;
import org.croudtrip.fragments.SubscriptionFragment;
import org.croudtrip.fragments.offer.DispatchOfferTripFragment;
import org.croudtrip.location.LocationUpdater;
import org.croudtrip.location.MyAutoCompleteTextView;
import org.croudtrip.location.PlaceAutocompleteAdapter;
import org.croudtrip.utils.CrashPopup;
import org.croudtrip.utils.DefaultTransformer;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;

import it.neokree.materialnavigationdrawer.MaterialNavigationDrawer;
import it.neokree.materialnavigationdrawer.elements.MaterialSection;
import pl.charmas.android.reactivelocation.ReactiveLocationProvider;
import roboguice.inject.InjectView;
import rx.Observable;
import rx.Subscription;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.schedulers.Schedulers;
import timber.log.Timber;

/**
 * Created by alex on 22.04.15.
 */
public class JoinSearchFragment extends SubscriptionFragment
        implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {

    private final int REQUEST_PLACE_PICKER = 122;
    private DatabaseHelper dbHelper;
    private GoogleApiClient googleApiClient;
    private PlaceAutocompleteAdapter adapter;

    private org.croudtrip.db.Place lastSelected;
    private Location specifiedLocation;

    @InjectView(R.id.address)
    private TextView tv_address;
    @InjectView(R.id.places)
    private Button btn_destination;
    @InjectView(R.id.destination)
    private MyAutoCompleteTextView tv_destination;
    @InjectView(R.id.slider_waitingTime)
    private Slider slider_waitingTime;
    @InjectView(R.id.waitingTime)
    private TextView tv_waitingTime;
    @InjectView(R.id.pb_join_trip_destination)
    private ProgressWheel progressBar;
    @InjectView(R.id.layout_load_location)
    private LinearLayout loadLocationLayout;
    @InjectView(R.id.join)
    private Button btn_join;

    @Inject
    LocationUpdater locationUpdater;
    private Geocoder geocoder;

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

        geocoder = new Geocoder(getActivity());
        dbHelper = ((MainApplication) getActivity().getApplication()).getHelper();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        setHasOptionsMenu(true);

        if (googleApiClient == null) {
            googleApiClient = new GoogleApiClient.Builder(getActivity().getApplicationContext())
                    .addConnectionCallbacks(this).addOnConnectionFailedListener(this).addApi(Places.GEO_DATA_API)
                    .build();

            googleApiClient.connect();
        } else if (!googleApiClient.isConnected()) {
            googleApiClient.connect();
        }

        View view = inflater.inflate(R.layout.fragment_join_search, container, false);
        return view;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        /*
        Set up the autocomplete textView
         */
        tv_destination.setOnItemClickListener(mAutocompleteClickListener);
        tv_destination.setThreshold(0);
        LatLngBounds bounds = null;
        if (locationUpdater.getLastLocation() != null) {
            bounds = LatLngBounds.builder().include(new LatLng(locationUpdater.getLastLocation().getLatitude(),
                    locationUpdater.getLastLocation().getLongitude())).build();

        }
        adapter = new PlaceAutocompleteAdapter(getActivity(), android.R.layout.simple_list_item_1, bounds, null);
        tv_destination.setAdapter(adapter);
        adapter.setGoogleApiClient(googleApiClient);
        tv_destination.clearFocus();
        tv_destination.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View view, boolean hasFocus) {
                if (hasFocus) {
                    tv_destination.showDropDown();
                }
            }
        });

        /*
        Populate the autocomplete textView
         */
        try {
            List<org.croudtrip.db.Place> savedPlaces = dbHelper.getPlaceDao().queryForAll();
            ArrayList<PlaceAutocompleteAdapter.PlaceAutocomplete> history = new ArrayList<>();
            for (int i = savedPlaces.size() - 1; i >= 0; i--) {
                if (history.size() == 5) {
                    break;
                }
                PlaceAutocompleteAdapter.PlaceAutocomplete a = adapter.new PlaceAutocomplete(
                        savedPlaces.get(i).getId(), savedPlaces.get(i).getDescription());
                history.add(a);
            }
            adapter.setHistory(history);
        } catch (SQLException e) {
            CrashPopup.show(getActivity(), e);
            e.printStackTrace();
        }

        /*
        Insert the last known location as soon as it is known
         */
        ReactiveLocationProvider locationProvider = new ReactiveLocationProvider(getActivity());
        Subscription subscription = locationProvider.getLastKnownLocation().observeOn(Schedulers.io())
                .subscribe(new Action1<Location>() {
                    @Override
                    public void call(Location location) {
                        LatLngBounds bounds = LatLngBounds.builder()
                                .include(new LatLng(location.getLatitude(), location.getLongitude())).build();
                        adapter.setBounds(bounds);
                    }
                });
        subscriptions.add(subscription);

        /*
        Open the placepicker on button click
         */
        btn_destination.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    PlacePicker.IntentBuilder intentBuilder = new PlacePicker.IntentBuilder();
                    Intent intent = intentBuilder.build(getActivity().getApplicationContext());

                    startActivityForResult(intent, REQUEST_PLACE_PICKER);
                } catch (GooglePlayServicesRepairableException e) {
                    CrashPopup.show(getActivity(), e);
                    e.printStackTrace();
                } catch (GooglePlayServicesNotAvailableException e) {
                    CrashPopup.show(getActivity(), e);
                    e.printStackTrace();
                }
            }
        });

        /*
        Load and set the maximum waiting time
         */
        final SharedPreferences prefs = getActivity().getSharedPreferences(Constants.SHARED_PREF_FILE_PREFERENCES,
                Context.MODE_PRIVATE);
        int waitingTime = prefs.getInt(Constants.SHARED_PREF_KEY_WAITING_TIME, 10);
        tv_waitingTime.setText(getString(R.string.join_max_waiting) + " " + waitingTime);
        slider_waitingTime.setValue(waitingTime);

        slider_waitingTime.setOnValueChangedListener(new Slider.OnValueChangedListener() {
            @Override
            public void onValueChanged(int i) {
                tv_waitingTime.setText(getString(R.string.join_max_waiting) + " " + i);
            }
        });

        /*
        Retrieve starting position, save destination and try to join a trip
         */
        btn_join.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                /*
                Save maximum waiting time
                 */
                SharedPreferences.Editor editor = prefs.edit();
                editor.putInt(Constants.SHARED_PREF_KEY_WAITING_TIME, slider_waitingTime.getValue());
                editor.apply();

                org.croudtrip.db.Place tempPlace = lastSelected;
                lastSelected = null;

                /*
                Get the starting position either by placepicker or GPS data
                 */
                Location currentLocation;
                if (specifiedLocation == null) {
                    // retrieve current position
                    currentLocation = locationUpdater.getLastLocation();
                    if (currentLocation == null) {
                        Toast.makeText(getActivity().getApplicationContext(), R.string.offer_trip_no_location,
                                Toast.LENGTH_SHORT).show();

                        AlertDialog.Builder adb = new AlertDialog.Builder(getActivity());
                        adb.setTitle(getResources().getString(R.string.enable_gps_title));
                        adb.setMessage(getResources().getString(R.string.gpd_not_available));
                        adb.setPositiveButton(getResources().getString(R.string.redirect_to_placepicker),
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int which) {

                                        try {
                                            PlacePicker.IntentBuilder intentBuilder = new PlacePicker.IntentBuilder();
                                            Intent intent = intentBuilder
                                                    .build(getActivity().getApplicationContext());

                                            startActivityForResult(intent, REQUEST_PLACE_PICKER);
                                        } catch (GooglePlayServicesRepairableException e) {
                                            CrashPopup.show(getActivity(), e);
                                            e.printStackTrace();
                                        } catch (GooglePlayServicesNotAvailableException e) {
                                            CrashPopup.show(getActivity(), e);
                                            e.printStackTrace();
                                        }

                                        return;
                                    }
                                });
                        adb.show();
                        return;
                    }
                } else {
                    currentLocation = specifiedLocation;
                    specifiedLocation = null;
                }

                // get destination from string
                LatLng destination = null;
                try {
                    List<Address> addresses = null;
                    if (tv_address.getText() == null || tv_address.getText().equals("")) {
                        addresses = geocoder.getFromLocationName(tv_destination.getText().toString(), 1);
                    } else {
                        addresses = geocoder.getFromLocationName(tv_address.getText().toString(), 1);
                    }
                    if (addresses != null && addresses.size() > 0)
                        destination = new LatLng(addresses.get(0).getLatitude(), addresses.get(0).getLongitude());
                } catch (IOException e) {
                    Toast.makeText(getActivity().getApplicationContext(), R.string.join_trip_no_destination,
                            Toast.LENGTH_SHORT).show();
                    return;
                }
                // no destination received
                if (destination == null) {
                    Toast.makeText(getActivity().getApplicationContext(), R.string.offer_trip_no_destination,
                            Toast.LENGTH_SHORT).show();
                    return;
                }

                if (currentLocation == null) {
                    Toast.makeText(getActivity().getApplicationContext(), R.string.offer_trip_no_location,
                            Toast.LENGTH_SHORT).show();
                    return;
                }

                /*
                Save or update destination in database
                 */
                try {
                    if (tempPlace != null) {
                        dbHelper.getPlaceDao().delete(tempPlace);
                        dbHelper.getPlaceDao().create(tempPlace);
                    } else {
                        tempPlace = new org.croudtrip.db.Place();
                        tempPlace.setId(tv_destination.getText().toString());
                        tempPlace.setDescription(tv_destination.getText().toString());
                        dbHelper.getPlaceDao().delete(tempPlace);
                        dbHelper.getPlaceDao().create(tempPlace);
                    }
                } catch (SQLException e) {
                    CrashPopup.show(getActivity(), e);
                    e.printStackTrace();
                }

                /*
                Set status to "searching"
                 */
                editor.putBoolean(Constants.SHARED_PREF_KEY_SEARCHING, true);
                editor.apply();

                /*
                Add trip information to extras and update UI
                 */
                Bundle extras = new Bundle();
                //extras.putString(JoinDispatchFragment.KEY_ACTION_TO_RUN, JoinDispatchFragment.ACTION_START_BACKGROUND_SEARCH);
                extras.putInt(JoinDispatchFragment.KEY_MAX_WAITING_TIME, slider_waitingTime.getValue() * 60); // max waiting time in seconds
                extras.putDouble(JoinDispatchFragment.KEY_CURRENT_LOCATION_LATITUDE, currentLocation.getLatitude());
                extras.putDouble(JoinDispatchFragment.KEY_CURRENT_LOCATION_LONGITUDE,
                        currentLocation.getLongitude());
                extras.putDouble(JoinDispatchFragment.KEY_DESTINATION_LATITUDE, destination.latitude);
                extras.putDouble(JoinDispatchFragment.KEY_DESTINATION_LONGITUDE, destination.longitude);

                Intent startingIntent = new Intent(Constants.EVENT_CHANGE_JOIN_UI);
                startingIntent.putExtras(extras);
                LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(startingIntent);
            }
        });

        /*
        Open the "Offer Trip" Fragment on click at the floating action button
         */
        FloatingActionButton btn_offer = (FloatingActionButton) view.findViewById(R.id.btn_offer_trip);
        btn_offer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MaterialNavigationDrawer drawer = (MaterialNavigationDrawer) getActivity();
                drawer.setFragment(new DispatchOfferTripFragment(), getString(R.string.menu_offer_trip));
                MaterialSection section = drawer.getSectionByTitle(getString(R.string.menu_offer_trip));

                if (section == null) {
                    drawer.getSectionByTitle(getString(R.string.menu_my_trip));
                }

                drawer.setSection(section);
            }
        });

        // if there is currently no position available disable the offer trip button
        if (locationUpdater.getLastLocation() == null && specifiedLocation == null) {
            btn_join.setEnabled(false);
            loadLocationLayout.setVisibility(View.VISIBLE);
            Subscription sub = locationProvider.getLastKnownLocation()
                    /* JUST FOR TESTING!!!
                            .observeOn( Schedulers.newThread() )
                            .subscribeOn(Schedulers.newThread())
                            .flatMap(new Func1<Location, Observable<Location>>() {
                                @Override
                                public Observable<Location> call(Location location) {
                                    try {
                                        Thread.sleep(4000);
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                    return Observable.just(location);
                                }
                            })*/
                    .compose(new DefaultTransformer<Location>()).subscribe(new Action1<Location>() {
                        @Override
                        public void call(Location location) {
                            if (location == null)
                                return;

                            locationUpdater.setLastLocation(location);
                            btn_join.setEnabled(true);
                            loadLocationLayout.setVisibility(View.GONE);
                        }
                    });

            subscriptions.add(sub);
        }

    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        // The user has selected a place. Extract the location
        if (requestCode == REQUEST_PLACE_PICKER && resultCode == Activity.RESULT_OK) {
            Place place = PlacePicker.getPlace(data, getActivity());
            Location l = new Location("placePicker");
            l.setLatitude(place.getLatLng().latitude);
            l.setLongitude(place.getLatLng().longitude);
            specifiedLocation = l;

            btn_join.setEnabled(true);
            //loadLocationLayout.setVisibility(View.VISIBLE);
        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        menu.clear();
    }

    @Override
    public void onConnected(Bundle bundle) {
        adapter.setGoogleApiClient(googleApiClient);
    }

    @Override
    public void onConnectionSuspended(int i) {
        adapter.setGoogleApiClient(null);
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Toast.makeText(getActivity(),
                "Could not connect to Google API Client: Error " + connectionResult.getErrorCode(),
                Toast.LENGTH_SHORT).show();

        // Disable API access in the adapter because the client was not initialised correctly.
        adapter.setGoogleApiClient(null);
    }

    private AdapterView.OnItemClickListener mAutocompleteClickListener = new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            /*
             Retrieve the place ID of the selected item from the Adapter.
             The adapter stores each Place suggestion in a PlaceAutocomplete object from which we
             read the place ID.
              */
            final PlaceAutocompleteAdapter.PlaceAutocomplete item = adapter.getItem(position);
            final String placeId = String.valueOf(item.placeId);

            /*
             Issue a request to the Places Geo Data API to retrieve a Place object with additional
              details about the place.
              */
            progressBar.setVisibility(View.VISIBLE);
            PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi.getPlaceById(googleApiClient, placeId);
            placeResult.setResultCallback(new ResultCallback<PlaceBuffer>() {
                @Override
                public void onResult(PlaceBuffer places) {
                    if (!places.getStatus().isSuccess()) {
                        // Request did not complete successfully
                        places.release();
                        return;
                    }

                    Place place;
                    try {
                        place = places.get(0);
                    } catch (IllegalStateException e) {
                        places.release();
                        return;
                    }
                    lastSelected = new org.croudtrip.db.Place();
                    lastSelected.setId(place.getId());
                    lastSelected.setDescription(place.getAddress() + "");
                    tv_address.setText(place.getAddress());
                    progressBar.setVisibility(View.GONE);

                    places.release();

                    InputMethodManager imm = (InputMethodManager) getActivity()
                            .getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                }
            });

            Toast.makeText(getActivity().getApplicationContext(), "Clicked: " + item.description,
                    Toast.LENGTH_SHORT).show();
        }
    };
}