com.ibm.mil.readyapps.telco.hotspots.HotSpotActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.ibm.mil.readyapps.telco.hotspots.HotSpotActivity.java

Source

/*
 * Licensed Materials - Property of IBM
 *  Copyright IBM Corporation 2015. All Rights Reserved.
 */

package com.ibm.mil.readyapps.telco.hotspots;

import android.graphics.Point;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.widget.NestedScrollView;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptor;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.ibm.mil.readyapps.telco.R;
import com.ibm.mil.readyapps.telco.analytics.GestureListener;
import com.ibm.mil.readyapps.telco.utils.JsonUtils;
import com.ibm.mil.readyapps.telco.utils.MapUtils;
import com.ibm.mil.readyapps.telco.utils.RxUtils;
import com.ibm.mil.readyapps.telco.utils.Utils;
import com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar;

import java.text.DecimalFormat;
import java.util.List;
import java.util.Locale;

import butterknife.ButterKnife;
import butterknife.Bind;
import butterknife.OnClick;
import rx.Observable;
import rx.functions.Action1;
import rx.subjects.PublishSubject;

public class HotSpotActivity extends AppCompatActivity implements HotSpotView, OnMapReadyCallback {
    private static final LatLng DEFAULT_LOCATION = new LatLng(30.398974, -97.712885);
    private static final DecimalFormat distanceFormatter = new DecimalFormat("0.0");
    private GestureDetectorCompat detector;
    @Bind(R.id.toolbar)
    Toolbar toolbar;
    @Bind(R.id.nested_scroll_view)
    NestedScrollView nestedScrollView;
    @Bind(R.id.map_area)
    View mapArea;
    @Bind(R.id.map_touchevent_capture_view)
    View mapTouchEventCaptureView;
    @Bind(R.id.content_area)
    View contentArea;
    @Bind(R.id.progress_bar)
    CircleProgressBar progressBar;
    @Bind(R.id.fab)
    FloatingActionButton fab;
    @Bind(R.id.hotspot_name)
    TextView hotSpotName;
    @Bind(R.id.verification_status)
    TextView verificationStatus;
    @Bind(R.id.hotspot_distance)
    TextView hotspotDistance;
    @Bind(R.id.address_line1)
    TextView addressLine1;
    @Bind(R.id.address_line2)
    TextView addressLine2;
    @Bind(R.id.download_speed)
    TextView downloadSpeed;
    @Bind(R.id.sign_in_requirement)
    TextView signInRequirement;
    @Bind(R.id.connection_count)
    TextView connectionCount;
    private GoogleMap map;
    private HotSpot currentHotSpot;
    private Marker currentMarker;
    private Marker userMarker;
    private HotSpotPresenter presenter;
    private BitmapDescriptor activePin;
    private BitmapDescriptor defaultPin;

    private static SpannableString spanSuffix(String text, String suffix, Object... spans) {
        String fullText = text + " " + suffix;
        int startIndex = fullText.indexOf(suffix);
        int endIndex = fullText.length();

        return createSpan(fullText, startIndex, endIndex, spans);
    }

    private static SpannableString createSpan(String text, int start, int stop, Object... spans) {
        SpannableString spannableString = new SpannableString(text);
        for (Object span : spans) {
            spannableString.setSpan(span, start, stop, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        }
        return spannableString;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hot_spot);
        ButterKnife.bind(this);
        detector = new GestureDetectorCompat(this, new GestureListener());
        presenter = new HotSpotPresenterImpl(this, new HotSpotModelImpl());

        setSupportActionBar(toolbar);
        assert getSupportActionBar() != null;
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDisplayShowTitleEnabled(false);

        progressBar.setColorSchemeColors(R.color.dark_indigo);

        // make map area 1/3 of available screen size
        Point screenSize = new Point();
        getWindowManager().getDefaultDisplay().getSize(screenSize);
        mapArea.setLayoutParams(
                new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, screenSize.y / 3));

        // prevent nested scroll view from scrolling up and down when gesture is performed on map
        mapTouchEventCaptureView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                switch (motionEvent.getAction()) {
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_DOWN:
                    nestedScrollView.requestDisallowInterceptTouchEvent(true);
                    return false;

                default:
                    return true;
                }
            }
        });

        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap map) {
        this.map = map;

        activePin = BitmapDescriptorFactory.fromResource(R.drawable.pin);
        defaultPin = BitmapDescriptorFactory.fromResource(R.drawable.dot);

        map.setMyLocationEnabled(false);
        map.getUiSettings().setMyLocationButtonEnabled(false);
        map.getUiSettings().setMapToolbarEnabled(false);
        map.getUiSettings().setCompassEnabled(false);

        // have presenter watch for marker clicks
        final PublishSubject<LatLng> markerPublisher = PublishSubject.create();
        presenter.watchMarkerClick(markerPublisher);
        map.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
            @Override
            public boolean onMarkerClick(Marker marker) {
                // define no behavior for clicking user marker
                if (marker.getPosition().equals(userMarker.getPosition())) {
                    return true;
                }

                // notify subscriber (presenter) that a new marker was selected
                // this will cause the presenter to fetch the detailed data for the hotspot
                markerPublisher.onNext(marker.getPosition());

                // reset marker icon to dot
                if (currentMarker != null) {
                    currentMarker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.dot));
                    currentMarker.setAnchor(0.5f, 0.5f);
                }

                marker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.pin));
                marker.setAnchor(0.5f, 1.0f);
                currentMarker = marker;

                return false;
            }
        });

        Location userLocation = initUserMarker();
        if (Utils.isConnected(this)) {
            useOnlineMode(userLocation);
        } else {
            useOfflineMode(userLocation, null);
        }
    }

    private void useOnlineMode(final Location userLocation) {
        final Geocoder geocoder = new Geocoder(this, Locale.getDefault());

        presenter.getOnlineHotSpots(geocoder, userLocation).compose(hotSpotTransformer()).subscribe(hotSpotOnNext(),
                new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        useOfflineMode(userLocation, geocoder);
                    }
                });
    }

    private void useOfflineMode(Location userLocation, Geocoder geocoder) {
        String json = JsonUtils.parseJsonFile(this, "offline_hotspots.json");
        presenter.getOfflineHotSpots(json, geocoder, userLocation).compose(hotSpotTransformer())
                .subscribe(hotSpotOnNext());
    }

    private Observable.Transformer<HotSpot, List<HotSpot>> hotSpotTransformer() {
        return new Observable.Transformer<HotSpot, List<HotSpot>>() {
            @Override
            public Observable<List<HotSpot>> call(Observable<HotSpot> observable) {
                return observable.toList().compose(RxUtils.<List<HotSpot>>showBackgroundWork());
            }
        };
    }

    private Action1<List<HotSpot>> hotSpotOnNext() {
        return new Action1<List<HotSpot>>() {
            @Override
            public void call(List<HotSpot> hotSpots) {
                displayHotSpots(hotSpots);
            }
        };
    }

    private Location initUserMarker() {
        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
        Location userLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

        LatLng userPosition = DEFAULT_LOCATION; // default if no user location exists
        if (userLocation != null) {
            userPosition = new LatLng(userLocation.getLatitude(), userLocation.getLongitude());
        }

        userMarker = map.addMarker(new MarkerOptions().position(userPosition).anchor(0.5f, 0.5f)
                .icon(BitmapDescriptorFactory.fromResource(R.drawable.person)));

        return MapUtils.convertLatLng(userMarker.getPosition());
    }

    private void displayHotSpots(List<HotSpot> hotSpots) {
        for (int i = 0, size = hotSpots.size(); i < size; i++) {
            HotSpot hotSpot = hotSpots.get(i);
            LatLng location = new LatLng(hotSpot.getLatitude(), hotSpot.getLongitude());

            Marker marker = map
                    .addMarker(new MarkerOptions().position(location).anchor(0.5f, 0.5f).icon(defaultPin));

            // select first (nearest) hotspot
            if (i == 0) {
                currentMarker = marker;
                currentHotSpot = hotSpot;
                showHotSpotDetails(hotSpot);
                marker.setIcon(activePin);
                marker.setAnchor(0.5f, 1.0f);
                map.moveCamera(CameraUpdateFactory.newLatLngZoom(location, 10.0f));
            }
        }

        contentArea.setVisibility(View.VISIBLE);
        fab.setVisibility(View.VISIBLE);
    }

    @Override
    public void showHotSpotDetails(HotSpot hotSpot) {
        currentHotSpot = hotSpot;

        hotSpotName.setText(hotSpot.getName());
        addressLine1.setText(hotSpot.getAddressLine1());
        addressLine2.setText(hotSpot.getAddressLine2());

        if (hotSpot.isVerified()) {
            verificationStatus.setText(R.string.verified_network);
        } else {
            verificationStatus.setText(R.string.unverified_network);
        }

        if (hotSpot.getSignInRequired()) {
            signInRequirement.setText(R.string.sign_in);
        } else {
            signInRequirement.setText(R.string.no_sign_in);
        }

        downloadSpeed.setText(spanSuffix(Integer.toString(hotSpot.getDownloadSpeed()),
                getString(R.string.internet_unit), new RelativeSizeSpan(0.75f)));

        connectionCount.setText(spanSuffix(Integer.toString(hotSpot.getConnections()),
                getString(R.string.connections), new RelativeSizeSpan(0.75f)));

        hotspotDistance.setText(spanSuffix(distanceFormatter.format(hotSpot.getDistanceAway()),
                getString(R.string.distance_away), new RelativeSizeSpan(0.66f),
                new ForegroundColorSpan(getResources().getColor(R.color.gray_ae))));
    }

    @OnClick(R.id.fab)
    public void getDirections(View view) {
        MapUtils.showDirections(this, MapUtils.convertLatLng(userMarker.getPosition()),
                MapUtils.convertLatLng(currentHotSpot.getLatitude(), currentHotSpot.getLongitude()));
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == android.R.id.home) {
            finish();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        this.detector.onTouchEvent(event);
        return super.onTouchEvent(event);
    }

}