gc.david.dfm.ui.activity.ShowInfoActivity.java Source code

Java tutorial

Introduction

Here is the source code for gc.david.dfm.ui.activity.ShowInfoActivity.java

Source

/*
 * Copyright (c) 2018 David Aguiar Gonzalez
 *
 * 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
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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 gc.david.dfm.ui.activity;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.ShareActionProvider;
import android.support.v7.widget.Toolbar;
import android.text.InputType;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.TextView;

import com.google.android.gms.maps.model.LatLng;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.inject.Inject;
import javax.inject.Named;

import butterknife.BindView;
import gc.david.dfm.ConnectionManager;
import gc.david.dfm.DFMApplication;
import gc.david.dfm.R;
import gc.david.dfm.Utils;
import gc.david.dfm.address.domain.GetAddressUseCase;
import gc.david.dfm.dagger.DaggerShowInfoComponent;
import gc.david.dfm.dagger.RootModule;
import gc.david.dfm.dagger.ShowInfoModule;
import gc.david.dfm.dagger.StorageModule;
import gc.david.dfm.deviceinfo.PackageManager;
import gc.david.dfm.distance.domain.InsertDistanceUseCase;
import gc.david.dfm.logger.DFMLogger;
import gc.david.dfm.showinfo.presentation.ShowInfo;
import gc.david.dfm.showinfo.presentation.ShowInfoPresenter;

import static butterknife.ButterKnife.bind;
import static gc.david.dfm.Utils.toastIt;

public class ShowInfoActivity extends AppCompatActivity implements ShowInfo.View {

    private static final String TAG = ShowInfoActivity.class.getSimpleName();

    private static final String POSITIONS_LIST_EXTRA_KEY = "positionsList";
    private static final String DISTANCE_EXTRA_KEY = "distance";
    private static final String ORIGIN_ADDRESS_STATE_KEY = "originAddressState";
    private static final String DESTINATION_ADDRESS_STATE_KEY = "destinationAddressState";
    private static final String DISTANCE_STATE_KEY = "distanceState";
    private static final String WAS_SAVING_STATE_KEY = "wasSavingState";
    private static final String DISTANCE_DIALOG_NAME_STATE_KEY = "distanceDialogName";

    @BindView(R.id.showinfo_activity_origin_address_textview)
    protected TextView tvOriginAddress;
    @BindView(R.id.showinfo_activity_destination_address_textview)
    protected TextView tvDestinationAddress;
    @BindView(R.id.showinfo_activity_distance_textview)
    protected TextView tvDistance;
    @BindView(R.id.tbMain)
    protected Toolbar tbMain;

    @Inject
    protected Context appContext;
    @Inject
    protected PackageManager packageManager;
    @Inject
    protected ConnectionManager connectionManager;
    @Inject
    protected InsertDistanceUseCase insertDistanceUseCase;
    @Inject
    @Named("NameByCoordinates")
    protected GetAddressUseCase getOriginAddressNameByCoordinatesUseCase;
    @Inject
    @Named("NameByCoordinates")
    protected GetAddressUseCase getDestinationAddressNameByCoordinatesUseCase;

    private MenuItem refreshMenuItem;
    private List<LatLng> positionsList;
    private String distance;
    private Dialog savingInDBDialog;
    private EditText etAlias;
    private ShowInfo.Presenter showInfoPresenter;

    private String originAddress = "";
    private String destinationAddress = "";
    private boolean wasSavingWhenOrientationChanged = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        DFMLogger.logMessage(TAG, "onCreate savedInstanceState=" + Utils.dumpBundleToString(savedInstanceState));

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_show_info);
        DaggerShowInfoComponent.builder().rootModule(new RootModule((DFMApplication) getApplication()))
                .storageModule(new StorageModule()).showInfoModule(new ShowInfoModule()).build().inject(this);
        bind(this);

        setSupportActionBar(tbMain);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        // TODO: 06.02.17 store presenter in singleton Map, Loader,... to restore after config change
        showInfoPresenter = new ShowInfoPresenter(this, getOriginAddressNameByCoordinatesUseCase,
                getDestinationAddressNameByCoordinatesUseCase, insertDistanceUseCase, connectionManager);

        getIntentData();

        if (savedInstanceState == null) {
            DFMLogger.logMessage(TAG, "onCreate savedInstanceState null, filling addresses info");

            fillAddressesInfo();
        } else {
            restorePreviousState(savedInstanceState);
        }

        fillDistanceInfo();
    }

    private void restorePreviousState(final Bundle savedInstanceState) {
        originAddress = savedInstanceState.getString(ORIGIN_ADDRESS_STATE_KEY);
        destinationAddress = savedInstanceState.getString(DESTINATION_ADDRESS_STATE_KEY);

        tvOriginAddress.setText(
                formatAddress(originAddress, positionsList.get(0).latitude, positionsList.get(0).longitude));
        tvDestinationAddress
                .setText(formatAddress(destinationAddress, positionsList.get(positionsList.size() - 1).latitude,
                        positionsList.get(positionsList.size() - 1).longitude));
        distance = savedInstanceState.getString(DISTANCE_STATE_KEY);

        wasSavingWhenOrientationChanged = savedInstanceState.getBoolean(WAS_SAVING_STATE_KEY);
        if (wasSavingWhenOrientationChanged) {
            final String aliasHint = savedInstanceState.getString(DISTANCE_DIALOG_NAME_STATE_KEY);
            saveDataToDB(aliasHint);
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        DFMLogger.logMessage(TAG, "onSaveInstanceState outState=" + Utils.dumpBundleToString(outState));

        super.onSaveInstanceState(outState);

        outState.putString(ORIGIN_ADDRESS_STATE_KEY, originAddress);
        outState.putString(DESTINATION_ADDRESS_STATE_KEY, destinationAddress);
        outState.putString(DISTANCE_STATE_KEY, distance);

        if (wasSavingWhenOrientationChanged) {
            outState.putBoolean(WAS_SAVING_STATE_KEY, wasSavingWhenOrientationChanged);
            outState.putString(DISTANCE_DIALOG_NAME_STATE_KEY, etAlias.getText().toString());

            if (savingInDBDialog != null) {
                savingInDBDialog.dismiss();
                savingInDBDialog = null;
            }
        }
    }

    private void getIntentData() {
        DFMLogger.logMessage(TAG, "getIntentData");

        final Intent inputDataIntent = getIntent();
        positionsList = inputDataIntent.getParcelableArrayListExtra(POSITIONS_LIST_EXTRA_KEY);
        distance = inputDataIntent.getStringExtra(DISTANCE_EXTRA_KEY);
    }

    private void fillAddressesInfo() {
        DFMLogger.logMessage(TAG, "fillAddressesInfo");

        showInfoPresenter.searchPositionByCoordinates(positionsList.get(0),
                positionsList.get(positionsList.size() - 1));
    }

    private String formatAddress(final String address, final double latitude, final double longitude) {
        return String.format(Locale.getDefault(), "%s\n\n(%f,%f)", address, latitude, longitude);
    }

    private void fillDistanceInfo() {
        DFMLogger.logMessage(TAG, "fillDistanceInfo");

        tvDistance.setText(getString(R.string.info_distance_title, distance));
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.show_info, menu);

        final MenuItem shareItem = menu.findItem(R.id.action_social_share);
        final ShareActionProvider shareActionProvider = (ShareActionProvider) MenuItemCompat
                .getActionProvider(shareItem);
        final Intent shareDistanceIntent = createDefaultShareIntent();
        if (packageManager.isThereAnyActivityForIntent(shareDistanceIntent)) {
            shareActionProvider.setShareIntent(shareDistanceIntent);
        }
        refreshMenuItem = menu.findItem(R.id.refresh);
        return true;
    }

    private Intent createDefaultShareIntent() {
        final Intent shareIntent = new Intent(Intent.ACTION_SEND);
        shareIntent.setType("text/plain");
        shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Distance From Me (http://goo.gl/0IBHFN)");

        final String extraText = String.format(
                "\nDistance From Me (http://goo.gl/0IBHFN)\n%s\n%s\n\n%s\n%s\n\n%s\n%s",
                getString(R.string.share_distance_from_message), originAddress,
                getString(R.string.share_distance_to_message), destinationAddress,
                getString(R.string.share_distance_there_are_message), distance);
        shareIntent.putExtra(Intent.EXTRA_TEXT, extraText);
        return shareIntent;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_social_share:
            return true;
        case R.id.refresh:
            fillAddressesInfo();
            return true;
        case R.id.menu_save:
            saveDataToDB("");
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    private void saveDataToDB(final String defaultText) {
        wasSavingWhenOrientationChanged = true;

        final AlertDialog.Builder builder = new AlertDialog.Builder(ShowInfoActivity.this);
        etAlias = new EditText(appContext);
        etAlias.setTextColor(Color.BLACK);
        etAlias.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
        etAlias.setText(defaultText);

        builder.setMessage(getString(R.string.alias_dialog_message))
                .setTitle(getString(R.string.alias_dialog_title)).setView(etAlias)
                .setOnCancelListener(new OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialog) {
                        wasSavingWhenOrientationChanged = false;
                    }
                }).setPositiveButton(getString(R.string.alias_dialog_accept), new OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        showInfoPresenter.saveDistance(etAlias.getText().toString(), distance, positionsList);
                        wasSavingWhenOrientationChanged = false;
                    }
                });
        (savingInDBDialog = builder.create()).show();
    }

    @Override
    public void setPresenter(final ShowInfo.Presenter presenter) {
        this.showInfoPresenter = presenter;
    }

    @Override
    public void showNoInternetError() {
        toastIt(getString(R.string.toast_network_problems), getApplicationContext());
    }

    @Override
    public void showProgress() {
        if (refreshMenuItem != null) {
            refreshMenuItem.setActionView(R.layout.actionbar_indeterminate_progress);
        }
    }

    @Override
    public void hideProgress() {
        if (refreshMenuItem != null) {
            refreshMenuItem.setActionView(null);
        }
    }

    @Override
    public void setAddress(final String address, final boolean isOrigin) {
        if (isOrigin) {
            originAddress = address;
            tvOriginAddress.setText(
                    formatAddress(originAddress, positionsList.get(0).latitude, positionsList.get(0).longitude));
        } else {
            destinationAddress = address;
            tvDestinationAddress
                    .setText(formatAddress(destinationAddress, positionsList.get(positionsList.size() - 1).latitude,
                            positionsList.get(positionsList.size() - 1).longitude));
        }
    }

    @Override
    public void showNoMatchesMessage(final boolean isOrigin) {
        if (isOrigin) {
            tvOriginAddress.setText(R.string.error_no_address_found_message);
        } else {
            tvDestinationAddress.setText(R.string.error_no_address_found_message);
        }
    }

    @Override
    public void showError(final String errorMessage, final boolean isOrigin) {
        if (isOrigin) {
            tvOriginAddress.setText(R.string.toast_no_location_found);
        } else {
            tvDestinationAddress.setText(R.string.toast_no_location_found);
        }
        DFMLogger.logException(new Exception(errorMessage));
    }

    @Override
    public void showSuccessfulSave() {
        toastIt(R.string.alias_dialog_no_name_toast, appContext);
    }

    @Override
    public void showSuccessfulSaveWithName(final String distanceName) {
        toastIt(getString(R.string.alias_dialog_with_name_toast, distanceName), appContext);
    }

    @Override
    public void showFailedSave() {
        toastIt("Unable to save distance. Try again later.", appContext);
        DFMLogger.logException(new Exception("Unable to insert distance into database."));
    }

    public static void open(final Activity activity, final List<LatLng> coordinates, final String distanceAsText) {
        final Intent openShowInfoActivityIntent = new Intent(activity, ShowInfoActivity.class);
        openShowInfoActivityIntent.putParcelableArrayListExtra(POSITIONS_LIST_EXTRA_KEY,
                new ArrayList<Parcelable>(coordinates));
        openShowInfoActivityIntent.putExtra(DISTANCE_EXTRA_KEY, distanceAsText);
        activity.startActivity(openShowInfoActivityIntent);
    }
}