fr.cph.chicago.core.activity.BusActivity.java Source code

Java tutorial

Introduction

Here is the source code for fr.cph.chicago.core.activity.BusActivity.java

Source

/**
 * Copyright 2016 Carl-Philipp Harmant
 * <p>
 * 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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.
 */

package fr.cph.chicago.core.activity;

import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.Toolbar;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.annimon.stream.Stream;

import org.apache.commons.collections4.MultiValuedMap;
import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import butterknife.BindColor;
import butterknife.BindString;
import butterknife.BindView;
import butterknife.ButterKnife;
import fr.cph.chicago.R;
import fr.cph.chicago.connection.CtaConnect;
import fr.cph.chicago.core.App;
import fr.cph.chicago.core.listener.GoogleMapDirectionOnClickListener;
import fr.cph.chicago.core.listener.GoogleMapOnClickListener;
import fr.cph.chicago.core.listener.GoogleStreetOnClickListener;
import fr.cph.chicago.data.Preferences;
import fr.cph.chicago.entity.BusArrival;
import fr.cph.chicago.entity.Position;
import fr.cph.chicago.entity.enumeration.TrainLine;
import fr.cph.chicago.exception.ConnectException;
import fr.cph.chicago.exception.ParserException;
import fr.cph.chicago.exception.TrackerException;
import fr.cph.chicago.parser.XmlParser;
import fr.cph.chicago.util.Util;

import static fr.cph.chicago.Constants.BUSES_PATTERN_URL;
import static fr.cph.chicago.connection.CtaRequestType.BUS_ARRIVALS;

/**
 * Activity that represents the bus stop
 *
 * @author Carl-Philipp Harmant
 * @version 1
 */
public class BusActivity extends AbstractStationActivity {

    @BindView(R.id.activity_bus_stop_swipe_refresh_layout)
    SwipeRefreshLayout scrollView;
    @BindView(R.id.activity_favorite_star)
    ImageView favoritesImage;
    @BindView(R.id.activity_bus_stops)
    LinearLayout stopsView;
    @BindView(R.id.activity_bus_streetview_image)
    ImageView streetViewImage;
    @BindView(R.id.activity_bus_steetview_text)
    TextView streetViewText;
    @BindView(R.id.activity_map_image)
    ImageView mapImage;
    @BindView(R.id.activity_map_direction)
    ImageView directionImage;
    @BindView(R.id.favorites_container)
    LinearLayout favoritesImageContainer;
    @BindView(R.id.walk_container)
    LinearLayout walkContainer;
    @BindView(R.id.map_container)
    LinearLayout mapContainer;
    @BindView(R.id.activity_bus_station_value)
    TextView busRouteNameView2;
    @BindView(R.id.toolbar)
    Toolbar toolbar;

    @BindString(R.string.bundle_bus_stop_id)
    String bundleBusStopId;
    @BindString(R.string.bundle_bus_route_id)
    String bundleBusRouteId;
    @BindString(R.string.bundle_bus_bound)
    String bundleBusBound;
    @BindString(R.string.bundle_bus_bound_title)
    String bundleBusBoundTitle;
    @BindString(R.string.bundle_bus_stop_name)
    String bundleBusStopName;
    @BindString(R.string.bundle_bus_route_name)
    String bundleBusRouteName;
    @BindString(R.string.bundle_bus_latitude)
    String bundleBusLatitude;
    @BindString(R.string.bundle_bus_longitude)
    String bundleBusLongitude;
    @BindString(R.string.bus_activity_no_service)
    String busActivityNoService;
    @BindString(R.string.analytics_bus_details)
    String analyticsBusDetails;
    @BindString(R.string.request_rt)
    String requestRt;
    @BindString(R.string.request_stop_id)
    String requestStopId;

    @BindColor(R.color.grey_5)
    int grey_5;
    @BindColor(R.color.grey)
    int grey;
    @BindColor(R.color.yellowLineDark)
    int yellowLineDark;

    private List<BusArrival> busArrivals;
    private String busRouteId, bound, boundTitle;
    private Integer busStopId;
    private String busStopName, busRouteName;
    private double latitude, longitude;
    private boolean isFavorite;

    @Override
    protected final void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        App.checkBusData(this);
        if (!this.isFinishing()) {
            setContentView(R.layout.activity_bus);
            ButterKnife.bind(this);

            if (busStopId == null || busRouteId == null || bound == null || busStopName == null
                    || busRouteName == null || boundTitle == null) {
                final Bundle extras = getIntent().getExtras();
                busStopId = extras.getInt(bundleBusStopId);
                busRouteId = extras.getString(bundleBusRouteId);
                bound = extras.getString(bundleBusBound);
                boundTitle = extras.getString(bundleBusBoundTitle);
                busStopName = extras.getString(bundleBusStopName);
                busRouteName = extras.getString(bundleBusRouteName);
                latitude = extras.getDouble(bundleBusLatitude);
                longitude = extras.getDouble(bundleBusLongitude);
            }

            final Position position = new Position();
            position.setLatitude(latitude);
            position.setLongitude(longitude);

            isFavorite = isFavorite();

            mapImage.setColorFilter(grey_5);
            directionImage.setColorFilter(grey_5);
            favoritesImageContainer.setOnClickListener(v -> switchFavorite());

            if (isFavorite) {
                favoritesImage.setColorFilter(yellowLineDark);
            } else {
                favoritesImage.setColorFilter(grey_5);
            }
            scrollView.setOnRefreshListener(() -> new LoadStationDataTask().execute());
            streetViewImage.setOnClickListener(new GoogleStreetOnClickListener(latitude, longitude));
            mapContainer.setOnClickListener(new GoogleMapOnClickListener(latitude, longitude));
            walkContainer.setOnClickListener(new GoogleMapDirectionOnClickListener(latitude, longitude));

            busRouteNameView2.setText(busRouteName + " (" + boundTitle + ")");

            // Load google street picture and data
            createGoogleStreetObservable(position.getLatitude(), position.getLongitude());
            subscribeToGoogleStreet(streetViewImage, streetViewText);
            new LoadStationDataTask().execute();

            setToolBar();

            // Google analytics
            Util.trackScreen(getApplicationContext(), analyticsBusDetails);
        }
    }

    private void setToolBar() {
        toolbar.inflateMenu(R.menu.main);
        toolbar.setOnMenuItemClickListener((item -> {
            scrollView.setRefreshing(true);
            new LoadStationDataTask().execute();
            return false;
        }));
        Util.setWindowsColor(this, toolbar, TrainLine.NA);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            toolbar.setElevation(4);
        }
        toolbar.setTitle(busRouteId + " - " + busStopName);
        toolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp);
        toolbar.setOnClickListener(v -> finish());
    }

    @Override
    public void onRestoreInstanceState(final Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        busStopId = savedInstanceState.getInt(bundleBusStopId);
        busRouteId = savedInstanceState.getString(bundleBusRouteId);
        bound = savedInstanceState.getString(bundleBusBound);
        boundTitle = savedInstanceState.getString(bundleBusBoundTitle);
        busStopName = savedInstanceState.getString(bundleBusStopName);
        busRouteName = savedInstanceState.getString(bundleBusRouteName);
        latitude = savedInstanceState.getDouble(bundleBusLatitude);
        longitude = savedInstanceState.getDouble(bundleBusLongitude);
    }

    @Override
    public void onSaveInstanceState(final Bundle savedInstanceState) {
        savedInstanceState.putInt(bundleBusStopId, busStopId);
        savedInstanceState.putString(bundleBusRouteId, busRouteId);
        savedInstanceState.putString(bundleBusBound, bound);
        savedInstanceState.putString(bundleBusBoundTitle, boundTitle);
        savedInstanceState.putString(bundleBusStopName, busStopName);
        savedInstanceState.putString(bundleBusRouteName, busRouteName);
        savedInstanceState.putDouble(bundleBusLatitude, latitude);
        savedInstanceState.putDouble(bundleBusLongitude, longitude);
        super.onSaveInstanceState(savedInstanceState);
    }

    public void setBusArrivals(@NonNull final List<BusArrival> busArrivals) {
        this.busArrivals = busArrivals;
    }

    /**
     * Draw arrivals in current main.java.fr.cph.chicago.res.layout
     */
    public void drawArrivals() {
        final Map<String, TextView> tempMap = new HashMap<>();
        if (busArrivals.size() != 0) {
            Stream.of(busArrivals).filter(arrival -> arrival.getRouteDirection().equals(bound)
                    || arrival.getRouteDirection().equals(boundTitle)).forEach(arrival -> {
                        final String destination = arrival.getBusDestination();
                        final String arrivalText;
                        if (tempMap.containsKey(destination)) {
                            final TextView arrivalView = tempMap.get(destination);
                            arrivalText = arrival.isDly() ? arrivalView.getText() + " Delay"
                                    : arrivalView.getText() + " " + arrival.getTimeLeft();
                            arrivalView.setText(arrivalText);
                        } else {
                            final TextView arrivalView = new TextView(getApplicationContext());
                            arrivalText = arrival.isDly() ? arrival.getBusDestination() + " Delay"
                                    : arrival.getBusDestination() + " " + arrival.getTimeLeft();
                            arrivalView.setText(arrivalText);
                            arrivalView.setTextColor(grey);
                            tempMap.put(destination, arrivalView);
                        }
                    });
        } else {
            final TextView arrivalView = new TextView(getApplicationContext());
            arrivalView.setTextColor(grey);
            arrivalView.setText(busActivityNoService);
            tempMap.put("", arrivalView);
        }
        stopsView.removeAllViews();
        Stream.of(tempMap.entrySet()).forEach(entry -> stopsView.addView(entry.getValue()));
    }

    @Override
    protected boolean isFavorite() {
        final List<String> favorites = Preferences.getBusFavorites(getApplicationContext(),
                App.PREFERENCE_FAVORITES_BUS);
        return Stream.of(favorites)
                .filter(favorite -> favorite.equals(busRouteId + "_" + busStopId + "_" + boundTitle)).findFirst()
                .isPresent();
    }

    /**
     * Add or remove from favorites
     */
    private void switchFavorite() {
        if (isFavorite) {
            Util.removeFromBusFavorites(busRouteId, String.valueOf(busStopId), boundTitle, scrollView);
            favoritesImage.setColorFilter(grey_5);
            isFavorite = false;
        } else {
            Util.addToBusFavorites(busRouteId, String.valueOf(busStopId), boundTitle, scrollView);
            Preferences.addBusRouteNameMapping(getApplicationContext(), String.valueOf(busStopId), busRouteName);
            Preferences.addBusStopNameMapping(getApplicationContext(), String.valueOf(busStopId), busStopName);
            favoritesImage.setColorFilter(yellowLineDark);
            isFavorite = true;
        }
    }

    private class LoadStationDataTask extends AsyncTask<Void, Void, List<BusArrival>> {

        private TrackerException trackerException;

        private LoadStationDataTask() {
        }

        @Override
        protected List<BusArrival> doInBackground(final Void... params) {
            final MultiValuedMap<String, String> reqParams = new ArrayListValuedHashMap<>();
            reqParams.put(requestRt, busRouteId);
            reqParams.put(requestStopId, Integer.toString(busStopId));
            final CtaConnect connect = CtaConnect.getInstance(getApplicationContext());
            try {
                final XmlParser xml = XmlParser.getInstance();
                // Connect to CTA API bus to get XML result of inc buses
                final InputStream xmlResult = connect.connect(BUS_ARRIVALS, reqParams);
                // Parse and return arrival buses
                return xml.parseBusArrivals(xmlResult);
            } catch (final ParserException | ConnectException e) {
                this.trackerException = e;
            }
            Util.trackAction(BusActivity.this, R.string.analytics_category_req, R.string.analytics_action_get_bus,
                    BUSES_PATTERN_URL, 0);
            return null;
        }

        @Override
        protected final void onProgressUpdate(final Void... values) {
        }

        @Override
        protected final void onPostExecute(final List<BusArrival> result) {
            if (trackerException == null) {
                setBusArrivals(result);
                drawArrivals();
            } else {
                Util.showNetworkErrorMessage(scrollView);
            }
            scrollView.setRefreshing(false);
        }
    }
}