com.gsma.rcs.ri.sharing.SharingListView.java Source code

Java tutorial

Introduction

Here is the source code for com.gsma.rcs.ri.sharing.SharingListView.java

Source

/*******************************************************************************
 * Software Name : RCS IMS Stack
 * <p/>
 * Copyright (C) 2010-2016 Orange.
 * <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 com.gsma.rcs.ri.sharing;

import com.gsma.rcs.api.connection.ConnectionManager.RcsServiceName;
import com.gsma.rcs.api.connection.utils.ExceptionUtil;
import com.gsma.rcs.api.connection.utils.RcsFragmentActivity;
import com.gsma.rcs.ri.R;
import com.gsma.rcs.ri.sharing.geoloc.GeolocSharingLogView;
import com.gsma.rcs.ri.sharing.image.ImageSharingLogView;
import com.gsma.rcs.ri.sharing.video.VideoSharingLogView;
import com.gsma.rcs.ri.utils.ContactListAdapter;
import com.gsma.rcs.ri.utils.ContactUtil;
import com.gsma.rcs.ri.utils.LogUtils;
import com.gsma.rcs.ri.utils.RcsContactUtil;
import com.gsma.rcs.ri.utils.Utils;
import com.gsma.services.rcs.RcsGenericException;
import com.gsma.services.rcs.RcsService.Direction;
import com.gsma.services.rcs.RcsServiceException;
import com.gsma.services.rcs.RcsServiceNotAvailableException;
import com.gsma.services.rcs.contact.ContactId;
import com.gsma.services.rcs.history.HistoryLog;
import com.gsma.services.rcs.history.HistoryUriBuilder;
import com.gsma.services.rcs.sharing.geoloc.GeolocSharing;
import com.gsma.services.rcs.sharing.geoloc.GeolocSharingListener;
import com.gsma.services.rcs.sharing.geoloc.GeolocSharingLog;
import com.gsma.services.rcs.sharing.geoloc.GeolocSharingService;
import com.gsma.services.rcs.sharing.image.ImageSharing.ReasonCode;
import com.gsma.services.rcs.sharing.image.ImageSharing.State;
import com.gsma.services.rcs.sharing.image.ImageSharingListener;
import com.gsma.services.rcs.sharing.image.ImageSharingLog;
import com.gsma.services.rcs.sharing.image.ImageSharingService;
import com.gsma.services.rcs.sharing.video.VideoSharing;
import com.gsma.services.rcs.sharing.video.VideoSharingListener;
import com.gsma.services.rcs.sharing.video.VideoSharingLog;
import com.gsma.services.rcs.sharing.video.VideoSharingService;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.CursorAdapter;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

/**
 * A class to view the sharing logs
 */
public class SharingListView extends RcsFragmentActivity implements LoaderManager.LoaderCallbacks<Cursor> {
    /**
     * The loader's unique ID. Loader IDs are specific to the Activity in which they reside.
     */
    private static final int LOADER_ID = 1;

    // @formatter:off
    private static final String[] PROJECTION = { HistoryLog.BASECOLUMN_ID, HistoryLog.ID, HistoryLog.PROVIDER_ID,
            HistoryLog.CONTACT, HistoryLog.TIMESTAMP, HistoryLog.DIRECTION, HistoryLog.STATUS, HistoryLog.FILENAME,
            HistoryLog.DURATION, HistoryLog.CONTENT, HistoryLog.MIME_TYPE, HistoryLog.TRANSFERRED,
            HistoryLog.FILESIZE };
    // @formatter:on

    private static final String LOGTAG = LogUtils.getTag(SharingListView.class.getName());

    private static final int MAX_LENGTH_DESCRIPTION = 30;
    private static final String SORT_BY = "timestamp DESC";
    private static final String WHERE_CLAUSE_WITH_CONTACT = "contact=?";
    /**
     * Associate the providers name menu with providerIds defined in HistoryLog
     */
    private static final TreeMap<Integer, String> sProviders = new TreeMap<>();

    private boolean[] mCheckedProviders;
    private AlertDialog mFilterAlertDialog;
    private List<String> mFilterMenuItems;
    private GeolocSharingListener mGeolocSharingListener;
    private boolean mGeolocSharingListenerSet;
    private GeolocSharingService mGeolocSharingService;
    private final Handler mHandler = new Handler();
    private ImageSharingListener mImageSharingListener;
    private boolean mImageSharingListenerSet;
    private ImageSharingService mImageSharingService;
    private List<Integer> mProviderIds;
    private SharingLogAdapter mAdapter;
    private Spinner mSpinner;
    private VideoSharingListener mVideoSharingListener;
    private boolean mVideoSharingListenerSet;
    private VideoSharingService mVideoSharingService;

    private class ViewHolder {

        private final int mColumnContactIdx;
        private final int mColumnTimestampIdx;
        private final int mColumnStatusIdx;
        private final int mColumnDirectionIdx;
        private final TextView mTypeView;
        private final TextView mContactView;
        private final TextView mDescriptionView;
        private final TextView mDateView;
        private final ImageView mDirectionIconImageView;
        private final int mColumnProviderIdIdx;
        private final int mColumnFilenameIdx;
        private final int mColumnDurationIdx;
        private final int mColumnContentIdx;

        public ViewHolder(View view, Cursor cursor) {
            mColumnProviderIdIdx = cursor.getColumnIndexOrThrow(HistoryLog.PROVIDER_ID);
            mColumnContactIdx = cursor.getColumnIndexOrThrow(HistoryLog.CONTACT);
            mColumnTimestampIdx = cursor.getColumnIndexOrThrow(HistoryLog.TIMESTAMP);
            mColumnDirectionIdx = cursor.getColumnIndexOrThrow(HistoryLog.DIRECTION);
            mColumnStatusIdx = cursor.getColumnIndexOrThrow(HistoryLog.STATUS);
            mColumnFilenameIdx = cursor.getColumnIndexOrThrow(HistoryLog.FILENAME);
            mColumnDurationIdx = cursor.getColumnIndexOrThrow(HistoryLog.DURATION);
            mColumnContentIdx = cursor.getColumnIndexOrThrow(HistoryLog.CONTENT);

            mTypeView = (TextView) view.findViewById(R.id.conversation_type);
            mContactView = (TextView) view.findViewById(R.id.contact_label);
            mDescriptionView = (TextView) view.findViewById(R.id.description);
            mDateView = (TextView) view.findViewById(R.id.date);
            mDirectionIconImageView = (ImageView) view.findViewById(R.id.call_type_icon);
        }

        public int getColumnProviderIdIdx() {
            return mColumnProviderIdIdx;
        }

        public int getColumnContactIdx() {
            return mColumnContactIdx;
        }

        public int getColumnTimestampIdx() {
            return mColumnTimestampIdx;
        }

        public int getColumnStatusIdx() {
            return mColumnStatusIdx;
        }

        public int getColumnDirectionIdx() {
            return mColumnDirectionIdx;
        }

        public TextView getTypeView() {
            return mTypeView;
        }

        public TextView getContactView() {
            return mContactView;
        }

        public TextView getDescriptionView() {
            return mDescriptionView;
        }

        public TextView getDateView() {
            return mDateView;
        }

        public ImageView getDirectionIconImageView() {
            return mDirectionIconImageView;
        }

        public int getColumnFilenameIdx() {
            return mColumnFilenameIdx;
        }

        public int getColumnDurationIdx() {
            return mColumnDurationIdx;
        }

        public int getColumnContentIdx() {
            return mColumnContentIdx;
        }
    }

    private class SharingLogAdapter extends CursorAdapter {
        private final LayoutInflater mInflater;
        private final RcsContactUtil mRcsContactUtil;
        private Drawable mDrawableIncoming;
        private Drawable mDrawableIncomingFailed;
        private Drawable mDrawableOutgoing;
        private Drawable mDrawableOutgoingFailed;

        public SharingLogAdapter(Activity activity) {
            super(activity, null, 0);
            mRcsContactUtil = RcsContactUtil.getInstance(activity);
            mInflater = LayoutInflater.from(SharingListView.this);
            Resources resources = activity.getResources();
            mDrawableIncomingFailed = resources.getDrawable(R.drawable.ri_incoming_call_failed);
            mDrawableOutgoingFailed = resources.getDrawable(R.drawable.ri_outgoing_call_failed);
            mDrawableIncoming = resources.getDrawable(R.drawable.ri_incoming_call);
            mDrawableOutgoing = resources.getDrawable(R.drawable.ri_outgoing_call);
        }

        @Override
        public int getItemViewType(int position) {
            return 1;
        }

        @Override
        public int getViewTypeCount() {
            return 1;
        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            View view = mInflater.inflate(R.layout.sharing_log_list, parent, false);
            view.setTag(new ViewHolder(view, cursor));
            return view;
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            ViewHolder holder = (ViewHolder) view.getTag();

            // Set contact number
            String phone = cursor.getString(holder.getColumnContactIdx());
            ContactId contact = ContactUtil.formatContact(phone);
            holder.getContactView().setText(mRcsContactUtil.getDisplayName(contact));

            // Set the date/time field by mixing relative and absolute times
            long date = cursor.getLong(holder.getColumnTimestampIdx());
            holder.getDateView().setText(DateUtils.getRelativeTimeSpanString(date, System.currentTimeMillis(),
                    DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE));

            // Set the status text and destination icon
            int status = cursor.getInt(holder.getColumnStatusIdx());
            Direction dir = Direction.valueOf(cursor.getInt(holder.getColumnDirectionIdx()));
            switch (dir) {
            case INCOMING:
                if (status != State.FAILED.toInt() && status != VideoSharing.State.FAILED.toInt()
                        && status != GeolocSharing.State.FAILED.toInt()) {
                    holder.getDirectionIconImageView().setImageDrawable(mDrawableIncoming);
                } else {
                    holder.getDirectionIconImageView().setImageDrawable(mDrawableIncomingFailed);
                }
                break;

            case OUTGOING:
                if (status != State.FAILED.toInt() && status != VideoSharing.State.FAILED.toInt()
                        && status != GeolocSharing.State.FAILED.toInt()) {
                    holder.getDirectionIconImageView().setImageDrawable(mDrawableOutgoing);
                } else {
                    holder.getDirectionIconImageView().setImageDrawable(mDrawableOutgoingFailed);
                }
                break;
            }
            int providerId = cursor.getInt(holder.getColumnProviderIdIdx());
            switch (providerId) {
            case ImageSharingLog.HISTORYLOG_MEMBER_ID:
                holder.getTypeView().setText(R.string.label_sharing_log_menu_ish);
                String filename = cursor.getString(holder.getColumnFilenameIdx());
                holder.getDescriptionView().setText(
                        TextUtils.isEmpty(filename) ? "" : truncateString(filename, MAX_LENGTH_DESCRIPTION));
                break;

            case VideoSharingLog.HISTORYLOG_MEMBER_ID:
                holder.getTypeView().setText(R.string.label_sharing_log_menu_vsh);
                long duration = cursor.getLong(holder.getColumnDurationIdx());
                holder.getDescriptionView().setText(
                        getString(R.string.value_log_duration, DateUtils.formatElapsedTime(duration / 1000L)));
                break;

            case GeolocSharingLog.HISTORYLOG_MEMBER_ID:
                holder.getTypeView().setText(R.string.label_sharing_log_menu_gsh);
                String content = cursor.getString(holder.getColumnContentIdx());
                holder.getDescriptionView()
                        .setText(TextUtils.isEmpty(content) ? "" : truncateString(content, MAX_LENGTH_DESCRIPTION));
            default:
            }
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        setContentView(R.layout.history_log_sharing);
        initialize();
    }

    @Override
    protected void onResume() {
        super.onResume();
        queryHistoryLogAndRefreshView();
    }

    private void initialize() {
        final Runnable updateUi = new Runnable() {
            @Override
            public void run() {
                queryHistoryLogAndRefreshView();
            }
        };
        mImageSharingService = getImageSharingApi();
        mImageSharingListener = new ImageSharingListener() {
            @Override
            public void onStateChanged(ContactId contact, String sharingId, State state, ReasonCode reasonCode) {
            }

            @Override
            public void onProgressUpdate(ContactId contact, String sharingId, long currentSize, long totalSize) {
            }

            @Override
            public void onDeleted(ContactId contact, Set<String> sharingIds) {
                Log.d(SharingListView.LOGTAG, "onDeleted contact=" + contact + " for sharing IDs="
                        + Arrays.toString(sharingIds.toArray()));
                mHandler.post(updateUi);
            }
        };
        mVideoSharingService = getVideoSharingApi();
        mVideoSharingListener = new VideoSharingListener() {
            @Override
            public void onStateChanged(ContactId contact, String sharingId, VideoSharing.State state,
                    VideoSharing.ReasonCode reasonCode) {
            }

            @Override
            public void onDeleted(ContactId contact, Set<String> sharingIds) {
                Log.d(SharingListView.LOGTAG, "onDeleted contact=" + contact + " for sharing IDs="
                        + Arrays.toString(sharingIds.toArray()));
                mHandler.post(updateUi);
            }
        };
        mGeolocSharingService = getGeolocSharingApi();
        mGeolocSharingListener = new GeolocSharingListener() {
            @Override
            public void onStateChanged(ContactId contact, String sharingId, GeolocSharing.State state,
                    GeolocSharing.ReasonCode reasonCode) {
            }

            @Override
            public void onProgressUpdate(ContactId contact, String sharingId, long currentSize, long totalSize) {
            }

            @Override
            public void onDeleted(ContactId contact, Set<String> sharingIds) {
                Log.d(SharingListView.LOGTAG, "onDeleted contact=" + contact + " for sharing IDs="
                        + Arrays.toString(sharingIds.toArray()));
                mHandler.post(updateUi);
            }
        };
        mAdapter = new SharingLogAdapter(this);
        ListView listView = (ListView) findViewById(android.R.id.list);
        listView.setEmptyView(findViewById(android.R.id.empty));
        listView.setAdapter(mAdapter);
        registerForContextMenu(listView);

        mSpinner = (Spinner) findViewById(R.id.contact);
        mSpinner.setAdapter(ContactListAdapter.createContactListAdapter(this,
                getString(R.string.label_sharing_log_contact_spinner_default_value)));
        mSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
                /* Call when an item is selected so also at the start of the activity to initialize */
                queryHistoryLogAndRefreshView();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
        listView.setOnItemClickListener(getOnItemClickListener());

        sProviders.put(ImageSharingLog.HISTORYLOG_MEMBER_ID, getString(R.string.label_sharing_log_menu_ish));
        sProviders.put(VideoSharingLog.HISTORYLOG_MEMBER_ID, getString(R.string.label_sharing_log_menu_vsh));
        sProviders.put(GeolocSharingLog.HISTORYLOG_MEMBER_ID, getString(R.string.label_sharing_log_menu_gsh));
        setProviders(sProviders);

        setCursorLoader(true);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        try {
            if (mImageSharingService != null && mImageSharingListenerSet) {
                mImageSharingService.removeEventListener(mImageSharingListener);
            }
            if (mVideoSharingService != null && mVideoSharingListenerSet) {
                mVideoSharingService.removeEventListener(mVideoSharingListener);
            }
            if (mGeolocSharingService != null && mGeolocSharingListenerSet) {
                mGeolocSharingService.removeEventListener(mGeolocSharingListener);
            }
        } catch (RcsServiceException e) {
            Log.w(LOGTAG, ExceptionUtil.getFullStackTrace(e));
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        new MenuInflater(getApplicationContext()).inflate(R.menu.menu_historylog, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.menu_filter:
            Builder builder = new Builder(this);
            builder.setTitle(R.string.title_sharing_log_dialog_filter_logs);
            builder.setMultiChoiceItems(mFilterMenuItems.toArray(new CharSequence[mFilterMenuItems.size()]),
                    mCheckedProviders, new DialogInterface.OnMultiChoiceClickListener() {
                        public void onClick(DialogInterface dialog, int which, boolean isChecked) {
                            mCheckedProviders[which] = isChecked;
                        }
                    });
            builder.setPositiveButton(R.string.label_ok, new OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    mFilterAlertDialog.dismiss();
                    queryHistoryLogAndRefreshView();
                }
            });
            builder.setNegativeButton(R.string.label_cancel, new OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    mFilterAlertDialog.dismiss();
                }
            });
            mFilterAlertDialog = builder.show();
            registerDialog(mFilterAlertDialog);
            break;

        case R.id.menu_delete:
            if (!isServiceConnected(RcsServiceName.IMAGE_SHARING, RcsServiceName.VIDEO_SHARING,
                    RcsServiceName.GEOLOC_SHARING)) {
                showMessage(R.string.label_service_not_available);
                break;
            }
            Log.d(LOGTAG, "delete all image sharing sessions");
            try {
                if (!mImageSharingListenerSet) {
                    mImageSharingService.addEventListener(mImageSharingListener);
                    mImageSharingListenerSet = true;
                }
                mImageSharingService.deleteImageSharings();
                if (!mVideoSharingListenerSet) {
                    mVideoSharingService.addEventListener(mVideoSharingListener);
                    mVideoSharingListenerSet = true;
                }
                mVideoSharingService.deleteVideoSharings();
                if (!mGeolocSharingListenerSet) {
                    mGeolocSharingService.addEventListener(mGeolocSharingListener);
                    mGeolocSharingListenerSet = true;
                }
                mGeolocSharingService.deleteGeolocSharings();
            } catch (RcsServiceException e) {
                showExceptionThenExit(e);

            }
            break;
        }
        return true;
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        getMenuInflater().inflate(R.menu.menu_log_sharing_item, menu);
        menu.findItem(R.id.menu_sharing_display).setVisible(false);
        // Get the list item position
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
        Cursor cursor = (Cursor) mAdapter.getItem(info.position);
        Direction dir = Direction.valueOf(cursor.getInt(cursor.getColumnIndexOrThrow(HistoryLog.DIRECTION)));
        String mimeType = cursor.getString(cursor.getColumnIndexOrThrow(HistoryLog.MIME_TYPE));
        if (mimeType != null && Utils.isImageType(mimeType)) {
            if (Direction.INCOMING == dir) {
                Long transferred = cursor.getLong(cursor.getColumnIndexOrThrow(HistoryLog.TRANSFERRED));
                Long fileSize = cursor.getLong(cursor.getColumnIndexOrThrow(HistoryLog.FILESIZE));
                if (fileSize.equals(transferred)) {
                    menu.findItem(R.id.menu_sharing_display).setVisible(true);
                    return;
                }
                return;
            }
            menu.findItem(R.id.menu_sharing_display).setVisible(true);
        }
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
        Cursor cursor = (Cursor) mAdapter.getItem(info.position);
        int providerId = cursor.getInt(cursor.getColumnIndexOrThrow(HistoryLog.PROVIDER_ID));
        String sharingId = cursor.getString(cursor.getColumnIndexOrThrow(HistoryLog.ID));
        if (LogUtils.isActive) {
            Log.d(LOGTAG, "onContextItemSelected sharing ID=".concat(sharingId));
        }
        try {
            switch (item.getItemId()) {
            case R.id.menu_sharing_delete:
                Log.d(LOGTAG, "Delete sharing ID=".concat(sharingId));
                switch (providerId) {
                case ImageSharingLog.HISTORYLOG_MEMBER_ID:
                    if (!mImageSharingListenerSet) {
                        mImageSharingService.addEventListener(mImageSharingListener);
                        mImageSharingListenerSet = true;
                    }
                    mImageSharingService.deleteImageSharing(sharingId);
                    return true;

                case VideoSharingLog.HISTORYLOG_MEMBER_ID:
                    if (!mVideoSharingListenerSet) {
                        mVideoSharingService.addEventListener(mVideoSharingListener);
                        mVideoSharingListenerSet = true;
                    }
                    mVideoSharingService.deleteVideoSharing(sharingId);
                    return true;
                case GeolocSharingLog.HISTORYLOG_MEMBER_ID:
                    if (!mGeolocSharingListenerSet) {
                        mGeolocSharingService.addEventListener(mGeolocSharingListener);
                        mGeolocSharingListenerSet = true;
                    }
                    mGeolocSharingService.deleteGeolocSharing(sharingId);
                    return true;
                default:
                    return true;
                }
            case R.id.menu_sharing_display:
                Utils.showPicture(this,
                        Uri.parse(cursor.getString(cursor.getColumnIndexOrThrow(HistoryLog.CONTENT))));
                return true;

            default:
                return super.onContextItemSelected(item);
            }
        } catch (RcsServiceNotAvailableException e) {
            showMessage(R.string.label_service_not_available);
            return true;

        } catch (RcsGenericException e2) {
            showExceptionThenExit(e2);
            return true;
        }
    }

    private OnItemClickListener getOnItemClickListener() {
        return new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View v, int pos, long id) {
                Cursor cursor = (Cursor) mAdapter.getItem(pos);
                int providerId = cursor.getInt(cursor.getColumnIndexOrThrow(HistoryLog.PROVIDER_ID));
                String sharingId = cursor.getString(cursor.getColumnIndexOrThrow(HistoryLog.ID));
                switch (providerId) {
                case ImageSharingLog.HISTORYLOG_MEMBER_ID:
                    ImageSharingLogView.startActivity(SharingListView.this, sharingId);
                    break;
                case VideoSharingLog.HISTORYLOG_MEMBER_ID:
                    VideoSharingLogView.startActivity(SharingListView.this, sharingId);
                    break;
                case GeolocSharingLog.HISTORYLOG_MEMBER_ID:
                    GeolocSharingLogView.startActivity(SharingListView.this, sharingId);
                    break;
                default:
                }
            }
        };
    }

    private String getSelectedContact() {
        MatrixCursor cursor = (MatrixCursor) mSpinner.getSelectedItem();
        String contact = cursor.getString(1);
        if (getString(R.string.label_history_log_contact_spinner_default_value).equals(contact)) {
            return contact;
        }
        return ContactUtil.formatContact(contact).toString();
    }

    /**
     * A method called to query the history log and refresh view
     */
    private void queryHistoryLogAndRefreshView() {
        Cursor cursor = null;
        List<Integer> selectedProviderIds = getSelectedProviderIds();
        String contact = getSelectedContact();
        if (!selectedProviderIds.isEmpty()) {
            if (getString(R.string.label_sharing_log_contact_spinner_default_value).equals(contact)) {
                /*
                 * No contact is selected
                 */
                Uri uri = createSharingLogUri(selectedProviderIds);
                cursor = getContentResolver().query(uri, PROJECTION, null, null, SORT_BY);
            } else {
                Uri uri = createSharingLogUri(selectedProviderIds);
                cursor = getContentResolver().query(uri, PROJECTION, WHERE_CLAUSE_WITH_CONTACT,
                        new String[] { contact }, SORT_BY);
            }
        }
        mAdapter.changeCursor(cursor);
    }

    /**
     * Truncate a string
     *
     * @param in string to truncate
     * @param maxLength maximum length
     * @return truncated string
     */
    private String truncateString(String in, int maxLength) {
        if (in.length() > maxLength) {
            in = in.substring(0, maxLength).concat("...");
        }
        return "\"" + in + "\"";
    }

    /**
     * Sets the providers
     *
     * @param providers ordered map of providers IDs associated with their name
     */
    private void setProviders(TreeMap<Integer, String> providers) {
        mProviderIds = new ArrayList<>();
        mFilterMenuItems = new ArrayList<>();
        for (Entry<Integer, String> entry : providers.entrySet()) {
            mFilterMenuItems.add(entry.getValue());
            mProviderIds.add(entry.getKey());
        }
        /* Upon setting, all providers are checked True */
        mCheckedProviders = new boolean[providers.size()];
        for (int i = 0; i < mCheckedProviders.length; i++) {
            mCheckedProviders[i] = true;
        }
    }

    /**
     * Gets the list of selected providers IDs
     *
     * @return the list of selected providers IDs
     */
    private List<Integer> getSelectedProviderIds() {
        List<Integer> providers = new ArrayList<>();
        for (int i = 0; i < mCheckedProviders.length; i++) {
            if (mCheckedProviders[i]) {
                providers.add(mProviderIds.get(i));
            }
        }
        return providers;
    }

    /**
     * Create History URI from list of provider IDs
     *
     * @param providerIds list of provider IDs
     * @return Uri
     */
    private Uri createSharingLogUri(List<Integer> providerIds) {
        HistoryUriBuilder uriBuilder = new HistoryUriBuilder(HistoryLog.CONTENT_URI);
        for (Integer providerId : providerIds) {
            uriBuilder.appendProvider(providerId);
        }
        return uriBuilder.build();
    }

    private void setCursorLoader(boolean firstLoad) {
        if (firstLoad) {
            // Initialize the Loader with id '1' and callbacks 'mCallbacks'.
            getSupportLoaderManager().initLoader(LOADER_ID, null, this);
        } else {
            // We switched from one contact to another: reload history since.
            getSupportLoaderManager().restartLoader(LOADER_ID, null, this);
        }
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        if (LogUtils.isActive) {
            Log.d(LOGTAG, "onCreateLoader " + id);
        }
        List<Integer> selectedProviderIds = getSelectedProviderIds();
        String contact = getSelectedContact();
        if (!selectedProviderIds.isEmpty()) {
            Uri uri = createSharingLogUri(selectedProviderIds);
            // Create a new CursorLoader with the following query parameters.
            if (getString(R.string.label_sharing_log_contact_spinner_default_value).equals(contact)) {
                // No contact is selected
                return new CursorLoader(this, uri, PROJECTION, null, null, SORT_BY);
            }
            return new CursorLoader(this, uri, PROJECTION, WHERE_CLAUSE_WITH_CONTACT, new String[] { contact },
                    SORT_BY);
        }
        return null;
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        if (LogUtils.isActive) {
            Log.d(LOGTAG, "onLoadFinished " + loader.getId());
        }
        // A switch-case is useful when dealing with multiple Loaders/IDs
        switch (loader.getId()) {
        case LOADER_ID:
            // The asynchronous load is complete and the data
            // is now available for use. Only now can we associate
            // the queried Cursor with the CursorAdapter.
            mAdapter.swapCursor(cursor);
            break;
        }
        // The listview now displays the queried data.
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        if (LogUtils.isActive) {
            Log.d(LOGTAG, "onLoaderReset " + loader.getId());
        }
        // For whatever reason, the Loader's data is now unavailable.
        // Remove any references to the old data by replacing it with a null
        // Cursor.
        mAdapter.swapCursor(null);
    }

}