fr.cph.chicago.core.adapter.FavoritesAdapter.java Source code

Java tutorial

Introduction

Here is the source code for fr.cph.chicago.core.adapter.FavoritesAdapter.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.adapter;

import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.util.SparseArray;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.annimon.stream.Collectors;
import com.annimon.stream.Optional;
import com.annimon.stream.Stream;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import fr.cph.chicago.R;
import fr.cph.chicago.core.App;
import fr.cph.chicago.core.activity.BikeStationActivity;
import fr.cph.chicago.core.activity.BusMapActivity;
import fr.cph.chicago.core.activity.MainActivity;
import fr.cph.chicago.core.activity.StationActivity;
import fr.cph.chicago.core.activity.TrainMapActivity;
import fr.cph.chicago.core.listener.BusStopOnClickListener;
import fr.cph.chicago.core.listener.GoogleMapOnClickListener;
import fr.cph.chicago.data.FavoritesData;
import fr.cph.chicago.entity.BikeStation;
import fr.cph.chicago.entity.BusArrival;
import fr.cph.chicago.entity.BusRoute;
import fr.cph.chicago.entity.Station;
import fr.cph.chicago.entity.TrainArrival;
import fr.cph.chicago.entity.dto.BusDetailsDTO;
import fr.cph.chicago.entity.enumeration.BusDirection;
import fr.cph.chicago.entity.enumeration.TrainLine;
import fr.cph.chicago.util.LayoutUtil;
import fr.cph.chicago.util.Util;

import static java.util.Map.Entry;

/**
 * Adapter that will handle favoritesData
 *
 * @author Carl-Philipp Harmant
 * @version 1
 */
// TODO to analyze and refactor
public final class FavoritesAdapter extends RecyclerView.Adapter<FavoritesAdapter.FavoritesViewHolder> {

    private final int grey5;
    private final Context context;
    private final MainActivity activity;
    private final FavoritesData favoritesData;
    private final int marginLeftPixel;
    private final int pixels;
    private final int pixelsHalf;
    private final int pixelsQuarter;

    private String lastUpdate;

    public FavoritesAdapter(@NonNull final MainActivity activity) {
        this.context = activity.getApplicationContext();
        this.grey5 = ContextCompat.getColor(context, R.color.grey_5);

        this.activity = activity;
        this.favoritesData = FavoritesData.getInstance(context);

        this.marginLeftPixel = Util.convertDpToPixel(context, 10);
        this.pixels = Util.convertDpToPixel(context, 16);
        this.pixelsHalf = pixels / 2;
        this.pixelsQuarter = pixels / 4;
    }

    static class FavoritesViewHolder extends RecyclerView.ViewHolder {
        final ViewGroup parent;
        final LinearLayout mainLayout;
        final RelativeLayout buttonsLayout;
        final TextView lastUpdateTextView;
        final TextView stationNameTextView;
        final ImageView favoriteImage;
        final Button detailsButton;
        final Button mapButton;

        private FavoritesViewHolder(final View view, final ViewGroup parent) {
            super(view);
            this.parent = parent;
            this.mainLayout = (LinearLayout) view.findViewById(R.id.favorites_arrival_layout);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                this.mainLayout
                        .setBackground(ContextCompat.getDrawable(parent.getContext(), R.drawable.any_selector));
            }
            this.buttonsLayout = (RelativeLayout) view.findViewById(R.id.favorites_buttons);
            this.favoriteImage = (ImageView) view.findViewById(R.id.favorites_icon);

            this.stationNameTextView = (TextView) view.findViewById(R.id.favorites_station_name);
            this.stationNameTextView.setLines(1);
            this.stationNameTextView.setEllipsize(TextUtils.TruncateAt.END);

            this.lastUpdateTextView = (TextView) view.findViewById(R.id.last_update);

            this.detailsButton = (Button) view.findViewById(R.id.details_button);
            this.mapButton = (Button) view.findViewById(R.id.view_map_button);
        }
    }

    @Override
    public FavoritesViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
        // create a new view
        final View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_favorites_train, parent,
                false);
        return new FavoritesViewHolder(v, parent);
    }

    @Override
    public void onBindViewHolder(final FavoritesViewHolder holder, final int position) {
        resetData(holder);
        final Optional<?> optional = favoritesData.getObject(position);
        holder.lastUpdateTextView.setText(lastUpdate);
        if (optional.isPresent()) {
            final Object object = optional.get();
            if (object instanceof Station) {
                final Station station = (Station) object;
                handleStation(holder, station);
            } else if (object instanceof BusRoute) {
                final BusRoute busRoute = (BusRoute) object;
                handleBusRoute(holder, busRoute);
            } else {
                final BikeStation bikeStation = (BikeStation) object;
                handleBikeStation(holder, bikeStation);
            }
        }
    }

    private void resetData(@NonNull final FavoritesViewHolder holder) {
        holder.mainLayout.removeAllViews();
    }

    private void handleStation(@NonNull final FavoritesViewHolder holder, @NonNull final Station station) {
        final int stationId = station.getId();
        final Set<TrainLine> trainLines = station.getLines();

        holder.favoriteImage.setImageResource(R.drawable.ic_train_white_24dp);
        holder.stationNameTextView.setText(station.getName());
        holder.detailsButton.setOnClickListener(v -> {
            if (!Util.isNetworkAvailable(context)) {
                Util.showNetworkErrorMessage(activity);
            } else {
                // Start station activity
                final Bundle extras = new Bundle();
                final Intent intent = new Intent(context, StationActivity.class);
                extras.putInt(activity.getString(R.string.bundle_train_stationId), stationId);
                intent.putExtras(extras);
                activity.startActivity(intent);
            }
        });

        holder.mapButton.setText(activity.getString(R.string.favorites_view_trains));
        holder.mapButton.setOnClickListener(v -> {
            if (!Util.isNetworkAvailable(context)) {
                Util.showNetworkErrorMessage(activity);
            } else {
                if (trainLines.size() == 1) {
                    startActivity(trainLines.iterator().next());
                } else {
                    final List<Integer> colors = new ArrayList<>();
                    final List<String> values = Stream.of(trainLines).flatMap(line -> {
                        final int color = line != TrainLine.YELLOW ? line.getColor()
                                : ContextCompat.getColor(context, R.color.yellowLine);
                        colors.add(color);
                        return Stream.of(line.toStringWithLine());
                    }).collect(Collectors.toList());

                    final PopupFavoritesTrainAdapter ada = new PopupFavoritesTrainAdapter(activity, values, colors);

                    final List<TrainLine> lines = new ArrayList<>();
                    lines.addAll(trainLines);

                    final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
                    builder.setAdapter(ada, (dialog, position) -> startActivity(lines.get(position)));

                    final int[] screenSize = Util.getScreenSize(context);
                    final AlertDialog dialog = builder.create();
                    dialog.show();
                    if (dialog.getWindow() != null) {
                        dialog.getWindow().setLayout((int) (screenSize[0] * 0.7), LayoutParams.WRAP_CONTENT);
                    }
                }
            }
        });

        Stream.of(trainLines).forEach(trainLine -> {
            boolean newLine = true;
            int i = 0;
            final Map<String, StringBuilder> etas = favoritesData.getTrainArrivalByLine(stationId, trainLine);
            for (final Entry<String, StringBuilder> entry : etas.entrySet()) {
                final LinearLayout.LayoutParams containParam = getInsideParams(newLine, i == etas.size() - 1);
                final LinearLayout container = new LinearLayout(context);
                container.setOrientation(LinearLayout.HORIZONTAL);
                container.setLayoutParams(containParam);

                // Left
                final RelativeLayout.LayoutParams leftParam = new RelativeLayout.LayoutParams(
                        LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
                final RelativeLayout left = new RelativeLayout(context);
                left.setLayoutParams(leftParam);

                final RelativeLayout lineIndication = LayoutUtil.createColoredRoundForFavorites(context, trainLine);
                int lineId = Util.generateViewId();
                lineIndication.setId(lineId);

                final RelativeLayout.LayoutParams destinationParams = new RelativeLayout.LayoutParams(
                        LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
                destinationParams.addRule(RelativeLayout.RIGHT_OF, lineId);
                destinationParams.setMargins(pixelsHalf, 0, 0, 0);

                final String destination = entry.getKey();
                final TextView destinationTextView = new TextView(context);
                destinationTextView.setTextColor(grey5);
                destinationTextView.setText(destination);
                destinationTextView.setLines(1);
                destinationTextView.setLayoutParams(destinationParams);

                left.addView(lineIndication);
                left.addView(destinationTextView);

                // Right
                final LinearLayout.LayoutParams rightParams = new LinearLayout.LayoutParams(
                        LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
                rightParams.setMargins(marginLeftPixel, 0, 0, 0);
                final LinearLayout right = new LinearLayout(context);
                right.setOrientation(LinearLayout.VERTICAL);
                right.setLayoutParams(rightParams);

                final StringBuilder currentEtas = entry.getValue();
                final TextView arrivalText = new TextView(context);
                arrivalText.setText(currentEtas);
                arrivalText.setGravity(Gravity.END);
                arrivalText.setSingleLine(true);
                arrivalText.setTextColor(grey5);
                arrivalText.setEllipsize(TextUtils.TruncateAt.END);

                right.addView(arrivalText);

                container.addView(left);
                container.addView(right);

                holder.mainLayout.addView(container);

                newLine = false;
                i++;
            }
        });
    }

    private void startActivity(final TrainLine trainLine) {
        final Bundle extras = new Bundle();
        final Intent intent = new Intent(context, TrainMapActivity.class);
        extras.putString(activity.getString(R.string.bundle_train_line), trainLine.toTextString());
        intent.putExtras(extras);
        activity.startActivity(intent);
    }

    @NonNull
    private LinearLayout.LayoutParams getInsideParams(final boolean newLine, final boolean lastLine) {
        final LinearLayout.LayoutParams paramsLeft = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.WRAP_CONTENT);
        if (newLine && lastLine) {
            paramsLeft.setMargins(pixels, pixelsQuarter, pixels, pixelsQuarter);
        } else if (newLine) {
            paramsLeft.setMargins(pixels, pixelsQuarter, pixels, 0);
        } else if (lastLine) {
            paramsLeft.setMargins(pixels, 0, pixels, pixelsQuarter);
        } else {
            paramsLeft.setMargins(pixels, 0, pixels, 0);
        }
        return paramsLeft;
    }

    private void handleBusRoute(@NonNull final FavoritesViewHolder holder, @NonNull final BusRoute busRoute) {
        holder.stationNameTextView.setText(busRoute.getId());
        holder.favoriteImage.setImageResource(R.drawable.ic_directions_bus_white_24dp);

        final List<BusDetailsDTO> busDetailsDTOs = new ArrayList<>();

        final Map<String, Map<String, List<BusArrival>>> busArrivals = favoritesData
                .getBusArrivalsMapped(busRoute.getId());
        for (final Entry<String, Map<String, List<BusArrival>>> entry : busArrivals.entrySet()) {
            // Build data for button outside of the loop
            final String stopName = entry.getKey();
            final String stopNameTrimmed = Util.trimBusStopNameIfNeeded(stopName);
            final Map<String, List<BusArrival>> value = entry.getValue();
            for (final String key2 : value.keySet()) {
                final BusArrival busArrival = value.get(key2).get(0);
                final String boundTitle = busArrival.getRouteDirection();
                final BusDirection.BusDirectionEnum busDirectionEnum = BusDirection.BusDirectionEnum
                        .fromString(boundTitle);
                final BusDetailsDTO busDetails = BusDetailsDTO.builder().busRouteId(busArrival.getRouteId())
                        .bound(busDirectionEnum.getShortUpperCase()).boundTitle(boundTitle)
                        .stopId(Integer.toString(busArrival.getStopId())).routeName(busRoute.getName())
                        .stopName(stopName).build();
                busDetailsDTOs.add(busDetails);
            }

            boolean newLine = true;
            int i = 0;

            for (final Entry<String, List<BusArrival>> entry2 : value.entrySet()) {
                final LinearLayout.LayoutParams containParams = getInsideParams(newLine, i == value.size() - 1);
                final LinearLayout container = new LinearLayout(context);
                container.setOrientation(LinearLayout.HORIZONTAL);
                container.setLayoutParams(containParams);

                // Left
                final LinearLayout.LayoutParams leftParams = new LinearLayout.LayoutParams(
                        LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
                final RelativeLayout left = new RelativeLayout(context);
                left.setLayoutParams(leftParams);

                final RelativeLayout lineIndication = LayoutUtil.createColoredRoundForFavorites(context,
                        TrainLine.NA);
                int lineId = Util.generateViewId();
                lineIndication.setId(lineId);

                final RelativeLayout.LayoutParams destinationParams = new RelativeLayout.LayoutParams(
                        LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                destinationParams.addRule(RelativeLayout.RIGHT_OF, lineId);
                destinationParams.setMargins(pixelsHalf, 0, 0, 0);

                final String bound = BusDirection.BusDirectionEnum.fromString(entry2.getKey()).getShortLowerCase();
                final String leftString = stopNameTrimmed + " " + bound;
                final SpannableString destinationSpannable = new SpannableString(leftString);
                destinationSpannable.setSpan(new RelativeSizeSpan(0.65f), stopNameTrimmed.length(),
                        leftString.length(), 0); // set size
                destinationSpannable.setSpan(new ForegroundColorSpan(grey5), 0, leftString.length(), 0); // set color

                final TextView boundCustomTextView = new TextView(context);
                boundCustomTextView.setText(destinationSpannable);
                boundCustomTextView.setSingleLine(true);
                boundCustomTextView.setLayoutParams(destinationParams);

                left.addView(lineIndication);
                left.addView(boundCustomTextView);

                // Right
                final LinearLayout.LayoutParams rightParams = new LinearLayout.LayoutParams(
                        LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
                rightParams.setMargins(marginLeftPixel, 0, 0, 0);
                final LinearLayout right = new LinearLayout(context);
                right.setOrientation(LinearLayout.VERTICAL);
                right.setLayoutParams(rightParams);

                final List<BusArrival> buses = entry2.getValue();
                final StringBuilder currentEtas = new StringBuilder();
                for (final BusArrival arri : buses) {
                    currentEtas.append(" ").append(arri.getTimeLeftDueDelay());
                }
                final TextView arrivalText = new TextView(context);
                arrivalText.setText(currentEtas);
                arrivalText.setGravity(Gravity.END);
                arrivalText.setSingleLine(true);
                arrivalText.setTextColor(grey5);
                arrivalText.setEllipsize(TextUtils.TruncateAt.END);

                right.addView(arrivalText);

                container.addView(left);
                container.addView(right);

                holder.mainLayout.addView(container);

                newLine = false;
                i++;
            }
        }

        holder.mapButton.setText(activity.getString(R.string.favorites_view_buses));
        holder.detailsButton
                .setOnClickListener(new BusStopOnClickListener(activity, holder.parent, busDetailsDTOs));
        holder.mapButton.setOnClickListener(v -> {
            if (!Util.isNetworkAvailable(context)) {
                Util.showNetworkErrorMessage(activity);
            } else {
                final Set<String> bounds = Stream.of(busDetailsDTOs).map(BusDetailsDTO::getBound)
                        .collect(Collectors.toSet());
                final Intent intent = new Intent(activity.getApplicationContext(), BusMapActivity.class);
                final Bundle extras = new Bundle();
                extras.putString(activity.getString(R.string.bundle_bus_route_id), busRoute.getId());
                extras.putStringArray(activity.getString(R.string.bundle_bus_bounds),
                        bounds.toArray(new String[bounds.size()]));
                intent.putExtras(extras);
                activity.startActivity(intent);
            }
        });
    }

    private void handleBikeStation(@NonNull final FavoritesViewHolder holder,
            @NonNull final BikeStation bikeStation) {
        holder.stationNameTextView.setText(bikeStation.getName());
        holder.favoriteImage.setImageResource(R.drawable.ic_directions_bike_white_24dp);

        holder.detailsButton.setOnClickListener(v -> {
            if (!Util.isNetworkAvailable(context)) {
                Util.showNetworkErrorMessage(activity);
            } else if (bikeStation.getLatitude() != 0 && bikeStation.getLongitude() != 0) {
                final Intent intent = new Intent(activity.getApplicationContext(), BikeStationActivity.class);
                final Bundle extras = new Bundle();
                extras.putParcelable(activity.getString(R.string.bundle_bike_station), bikeStation);
                intent.putExtras(extras);
                activity.startActivity(intent);
            } else {
                Util.showMessage(activity, R.string.message_not_ready);
            }
        });

        holder.mapButton.setText(activity.getString(R.string.favorites_view_station));
        holder.mapButton.setOnClickListener(
                new GoogleMapOnClickListener(bikeStation.getLatitude(), bikeStation.getLongitude()));

        final LinearLayout.LayoutParams containerParams = getInsideParams(true, true);
        final LinearLayout container = new LinearLayout(context);
        container.setOrientation(LinearLayout.VERTICAL);
        container.setLayoutParams(containerParams);

        final LinearLayout firstLine = createBikeFirstLine(bikeStation);
        container.addView(firstLine);

        final LinearLayout secondLine = createBikeSecondLine(bikeStation);
        container.addView(secondLine);

        holder.mainLayout.addView(container);
    }

    @NonNull
    private LinearLayout createBikeFirstLine(@NonNull final BikeStation bikeStation) {
        return createBikeLine(bikeStation, true);
    }

    @NonNull
    private LinearLayout createBikeSecondLine(@NonNull final BikeStation bikeStation) {
        return createBikeLine(bikeStation, false);
    }

    @NonNull
    private LinearLayout createBikeLine(@NonNull final BikeStation bikeStation, final boolean firstLine) {
        final LinearLayout.LayoutParams lineParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT);
        final LinearLayout line = new LinearLayout(context);
        line.setOrientation(LinearLayout.HORIZONTAL);
        line.setLayoutParams(lineParams);

        // Left
        final LinearLayout.LayoutParams leftParam = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT);
        final RelativeLayout left = new RelativeLayout(context);
        left.setLayoutParams(leftParam);

        final RelativeLayout lineIndication = LayoutUtil.createColoredRoundForFavorites(context, TrainLine.NA);
        int lineId = Util.generateViewId();
        lineIndication.setId(lineId);

        final RelativeLayout.LayoutParams availableParam = new RelativeLayout.LayoutParams(
                LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        availableParam.addRule(RelativeLayout.RIGHT_OF, lineId);
        availableParam.setMargins(pixelsHalf, 0, 0, 0);

        final TextView boundCustomTextView = new TextView(context);
        boundCustomTextView.setText(activity.getString(R.string.bike_available_docks));
        boundCustomTextView.setSingleLine(true);
        boundCustomTextView.setLayoutParams(availableParam);
        boundCustomTextView.setTextColor(grey5);
        int availableId = Util.generateViewId();
        boundCustomTextView.setId(availableId);

        final RelativeLayout.LayoutParams availableValueParam = new RelativeLayout.LayoutParams(
                LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        availableValueParam.addRule(RelativeLayout.RIGHT_OF, availableId);
        availableValueParam.setMargins(pixelsHalf, 0, 0, 0);

        final TextView amountBike = new TextView(context);
        final String text = firstLine ? activity.getString(R.string.bike_available_bikes)
                : activity.getString(R.string.bike_available_docks);
        boundCustomTextView.setText(text);
        final Integer data = firstLine ? bikeStation.getAvailableBikes() : bikeStation.getAvailableDocks();
        if (data == null) {
            amountBike.setText("?");
            amountBike.setTextColor(ContextCompat.getColor(context, R.color.orange));
        } else {
            amountBike.setText(String.valueOf(data));
            final int color = data == 0 ? R.color.red : R.color.green;
            amountBike.setTextColor(ContextCompat.getColor(context, color));
        }
        amountBike.setLayoutParams(availableValueParam);

        left.addView(lineIndication);
        left.addView(boundCustomTextView);
        left.addView(amountBike);
        line.addView(left);
        return line;
    }

    @Override
    public final long getItemId(final int position) {
        return position;
    }

    @Override
    public final int getItemCount() {
        return favoritesData.size();
    }

    public final void setTrainArrivals(@NonNull final SparseArray<TrainArrival> arrivals) {
        favoritesData.setTrainArrivals(arrivals);
    }

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

    public final void setBikeStations(@NonNull final List<BikeStation> bikeStations) {
        favoritesData.setBikeStations(bikeStations);
    }

    /**
     * Set favoritesData
     */
    public final void setFavorites() {
        favoritesData.setFavorites();
    }

    /**
     * Refresh date update
     */
    public final void refreshUpdated() {
        App.modifyLastUpdate(Calendar.getInstance().getTime());
    }

    /**
     * Refresh udpdated view
     */
    public final void refreshUpdatedView() {
        lastUpdate = getLastUpdateInMinutes();
        notifyDataSetChanged();
    }

    /**
     * Get last update in minutes
     *
     * @return a string
     */
    private String getLastUpdateInMinutes() {
        final StringBuilder lastUpdateInMinutes = new StringBuilder();
        final Date currentDate = Calendar.getInstance().getTime();
        final long[] diff = getTimeDifference(App.getLastUpdate(), currentDate);
        final long hours = diff[0];
        final long minutes = diff[1];
        if (hours == 0 && minutes == 0) {
            lastUpdateInMinutes.append(activity.getString(R.string.time_now));
        } else {
            if (hours == 0) {
                lastUpdateInMinutes.append(minutes).append(activity.getString(R.string.time_min));
            } else {
                lastUpdateInMinutes.append(hours).append(activity.getString(R.string.time_hour)).append(minutes)
                        .append(activity.getString(R.string.time_min));
            }
        }
        return lastUpdateInMinutes.toString();
    }

    /**
     * Get time difference between 2 dates
     *
     * @param date1 the date one
     * @param date2 the date two
     * @return a tab containing in 0 the hour and in 1 the minutes
     */
    private long[] getTimeDifference(@NonNull final Date date1, @NonNull final Date date2) {
        final long[] result = new long[2];
        final Calendar cal = Calendar.getInstance();
        cal.setTime(date1);
        final long t1 = cal.getTimeInMillis();
        cal.setTime(date2);
        long diff = Math.abs(cal.getTimeInMillis() - t1);
        final int day = 1000 * 60 * 60 * 24;
        final int hour = day / 24;
        final int minute = hour / 60;
        diff %= day;
        long h = diff / hour;
        diff %= hour;
        long m = diff / minute;
        result[0] = h;
        result[1] = m;
        return result;
    }
}