im.vector.contacts.ContactsManager.java Source code

Java tutorial

Introduction

Here is the source code for im.vector.contacts.ContactsManager.java

Source

/*
 * Copyright 2015 OpenMarket Ltd
 *
 * 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 im.vector.contacts;

import android.Manifest;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Build;
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.util.Log;

import org.matrix.androidsdk.MXSession;
import org.matrix.androidsdk.rest.callback.ApiCallback;
import org.matrix.androidsdk.rest.model.MatrixError;
import org.matrix.androidsdk.rest.model.User;

import im.vector.Matrix;
import im.vector.VectorApp;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Set;

/**
 * Manage the local contacts
 */
public class ContactsManager {
    private static final String LOG_TAG = "ContactsManager";

    public interface ContactsManagerListener {
        /**
         * Called when the contacts list have been
         */
        void onRefresh();

        /**
         * Called when an user presence has been updated
         */
        void onContactPresenceUpdate(Contact contact, String matrixId);
    }

    private static Collection<Contact> mContactsList = null;
    private static ArrayList<ContactsManagerListener> mListeners = null;

    // retriever listener
    private static final PIDsRetriever.PIDsRetrieverListener mPIDsRetrieverListener = new PIDsRetriever.PIDsRetrieverListener() {
        /**
         * Warn the listeners about a contact information update.
         * @param contact the contact
         * @param mxid the mxid
         */
        private void onContactPresenceUpdate(Contact contact, Contact.MXID mxid) {
            if (null != mListeners) {
                for (ContactsManagerListener listener : mListeners) {
                    try {
                        listener.onContactPresenceUpdate(contact, mxid.mMatrixId);
                    } catch (Exception e) {
                        Log.e(LOG_TAG, "onContactPresenceUpdate failed " + e.getLocalizedMessage());
                    }
                }
            }
        }

        @Override
        public void onPIDsRetrieved(final String accountId, final Contact contact, final boolean has3PIDs) {
            // privacy
            // Log.d(LOG_TAG, "onPIDsRetrieved : the contact " + contact + " retrieves its 3PIds.");

            if (has3PIDs) {
                MXSession session = Matrix.getInstance(VectorApp.getInstance().getApplicationContext())
                        .getSession(accountId);

                if (null != session) {
                    Set<String> medias = contact.getMatrixIdMedias();

                    // privacy
                    //Log.d(LOG_TAG, "medias " + medias);

                    for (String media : medias) {
                        final Contact.MXID mxid = contact.getMXID(media);

                        onContactPresenceUpdate(contact, mxid);

                        mxid.mUser = session.getDataHandler().getUser(mxid.mMatrixId);

                        // if the user is not known, get its presence
                        if (null == mxid.mUser) {
                            session.getPresenceApiClient().getPresence(mxid.mMatrixId, new ApiCallback<User>() {
                                @Override
                                public void onSuccess(User user) {
                                    Log.d(LOG_TAG, "retrieve the presence of " + mxid.mMatrixId + " :" + user);
                                    mxid.mUser = user;
                                    onContactPresenceUpdate(contact, mxid);
                                }

                                /**
                                 * Error method
                                 * @param errorMessage the error description
                                 */
                                private void onError(String errorMessage) {
                                    Log.e(LOG_TAG, "cannot retrieve the presence of " + mxid.mMatrixId + " :"
                                            + errorMessage);
                                    onContactPresenceUpdate(contact, mxid);
                                }

                                @Override
                                public void onNetworkError(Exception e) {
                                    onError(e.getLocalizedMessage());
                                }

                                @Override
                                public void onMatrixError(MatrixError e) {
                                    onError(e.getLocalizedMessage());
                                }

                                @Override
                                public void onUnexpectedError(Exception e) {
                                    onError(e.getLocalizedMessage());
                                }
                            });
                        }
                    }
                }
            }
        }
    };

    /**
     * Refresh the local contacts list snapshot.
     * @param context the context.
     * @return a local contacts list
     */
    public static Collection<Contact> getLocalContactsSnapshot(Context context) {
        if (null == mContactsList) {
            refreshLocalContactsSnapshot(context);
        }
        return mContactsList;
    }

    /**
     * reset
     */
    public static void reset() {
        mListeners = null;
        mContactsList = null;
    }

    /**
     * Clear the current snapshot
     */
    public static void clearSnapshot() {
        mContactsList = null;
    }

    /**
     * Add a listener.
     * @param listener the listener to add.
     */
    public static void addListener(ContactsManagerListener listener) {
        if (null == mListeners) {
            mListeners = new ArrayList<>();
        }

        mListeners.add(listener);
    }

    /**
     * Remove a listener.
     * @param listener the listener to remove.
     */
    public static void removeListener(ContactsManagerListener listener) {
        if (null != mListeners) {
            mListeners.remove(listener);
        }
    }

    /**
     * List the local contacts.
     * @param context the context.
     */
    public static void refreshLocalContactsSnapshot(Context context) {
        ContentResolver cr = context.getContentResolver();
        HashMap<String, Contact> dict = new HashMap<>();

        // test if the user allows to access to the contact
        if (isContactBookAccessAllowed(context)) {
            // get the names
            Cursor namesCur = null;

            try {
                namesCur = cr.query(ContactsContract.Data.CONTENT_URI,
                        new String[] { ContactsContract.Contacts.DISPLAY_NAME_PRIMARY,
                                ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID,
                                ContactsContract.Contacts.PHOTO_THUMBNAIL_URI },
                        ContactsContract.Data.MIMETYPE + " = ?",
                        new String[] { ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE }, null);
            } catch (Exception e) {
                Log.e(LOG_TAG,
                        "## refreshLocalContactsSnapshot(): Exception - Contact names query Msg=" + e.getMessage());
            }

            if (namesCur != null) {
                try {
                    while (namesCur.moveToNext()) {
                        String displayName = namesCur
                                .getString(namesCur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY));
                        String contactId = namesCur.getString(namesCur
                                .getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID));
                        String thumbnailUri = namesCur.getString(namesCur.getColumnIndex(
                                ContactsContract.CommonDataKinds.StructuredName.PHOTO_THUMBNAIL_URI));

                        if (null != contactId) {
                            Contact contact = dict.get(contactId);

                            if (null == contact) {
                                contact = new Contact(contactId);
                                dict.put(contactId, contact);
                            }

                            if (null != displayName) {
                                contact.setDisplayName(displayName);
                            }

                            if (null != thumbnailUri) {
                                contact.setThumbnailUri(thumbnailUri);
                            }
                        }
                    }
                } catch (Exception e) {
                    Log.e(LOG_TAG, "## refreshLocalContactsSnapshot(): Exception - Contact names query2 Msg="
                            + e.getMessage());
                }

                namesCur.close();
            }

            // get the phonenumbers
            Cursor phonesCur = null;

            try {
                phonesCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                        new String[] { ContactsContract.CommonDataKinds.Phone.DATA, // actual number
                                ContactsContract.CommonDataKinds.Phone.CONTACT_ID },
                        null, null, null);
            } catch (Exception e) {
                Log.e(LOG_TAG,
                        "## refreshLocalContactsSnapshot(): Exception - Phone numbers query Msg=" + e.getMessage());
            }

            if (null != phonesCur) {
                try {
                    while (phonesCur.moveToNext()) {
                        String phone = phonesCur
                                .getString(phonesCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DATA));

                        if (!TextUtils.isEmpty(phone)) {
                            String contactId = phonesCur.getString(
                                    phonesCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));

                            if (null != contactId) {
                                Contact contact = dict.get(contactId);
                                if (null == contact) {
                                    contact = new Contact(contactId);
                                    dict.put(contactId, contact);
                                }

                                contact.addPhonenumber(phone);
                            }
                        }
                    }
                } catch (Exception e) {
                    Log.e(LOG_TAG, "## refreshLocalContactsSnapshot(): Exception - Phone numbers query2 Msg="
                            + e.getMessage());
                }

                phonesCur.close();
            }

            // get the emails
            Cursor emailsCur = null;

            try {
                emailsCur = cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,
                        new String[] { ContactsContract.CommonDataKinds.Email.DATA, // actual email
                                ContactsContract.CommonDataKinds.Email.CONTACT_ID },
                        null, null, null);
            } catch (Exception e) {
                Log.e(LOG_TAG, "## refreshLocalContactsSnapshot(): Exception - Emails query Msg=" + e.getMessage());
            }

            if (emailsCur != null) {
                try {
                    while (emailsCur.moveToNext()) {
                        String email = emailsCur
                                .getString(emailsCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
                        if (!TextUtils.isEmpty(email)) {
                            String contactId = emailsCur.getString(
                                    emailsCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.CONTACT_ID));

                            if (null != contactId) {
                                Contact contact = dict.get(contactId);
                                if (null == contact) {
                                    contact = new Contact(contactId);
                                    dict.put(contactId, contact);
                                }

                                contact.addEmailAdress(email);
                            }
                        }
                    }
                } catch (Exception e) {
                    Log.e(LOG_TAG,
                            "## refreshLocalContactsSnapshot(): Exception - Emails query2 Msg=" + e.getMessage());
                }

                emailsCur.close();
            }
        }

        PIDsRetriever.getIntance().setPIDsRetrieverListener(mPIDsRetrieverListener);

        mContactsList = dict.values();

        if (null != mListeners) {
            for (ContactsManagerListener listener : mListeners) {
                try {
                    listener.onRefresh();
                } catch (Exception e) {
                    Log.e(LOG_TAG, "refreshLocalContactsSnapshot : onRefresh failed" + e.getLocalizedMessage());
                }
            }
        }
    }

    //================================================================================
    // Contacts book management (for android < M devices)
    //================================================================================
    public static final String CONTACTS_BOOK_ACCESS_KEY = "CONTACT_BOOK_ACCESS_KEY";

    /**
     * Tells if the contacts book access has been requested.
     * For android > M devices, it only tells if the permission has been granted.
     * @param activity the calling activity
     * @return true it was requested once
     */
    public static boolean isContactBookAccessRequested(Activity activity) {
        if (Build.VERSION.SDK_INT >= 23) {
            return (PackageManager.PERMISSION_GRANTED == ContextCompat
                    .checkSelfPermission(activity.getApplicationContext(), Manifest.permission.READ_CONTACTS));
        } else {
            SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
            return preferences.contains(CONTACTS_BOOK_ACCESS_KEY);
        }
    }

    /**
     * Update the contacts book access.
     * @param activity the calling activity.
     * @param isAllowed true to allowed the contacts book access.
     */
    public static void setIsContactBookAccessAllowed(Activity activity, boolean isAllowed) {
        if (Build.VERSION.SDK_INT < 23) {
            SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
            SharedPreferences.Editor editor = preferences.edit();
            editor.putBoolean(CONTACTS_BOOK_ACCESS_KEY, isAllowed);
            editor.commit();
        }
    }

    /**
     * Tells if the contacts book access has been granted
     * @param context the context
     * @return true if it was granted.
     */
    private static boolean isContactBookAccessAllowed(Context context) {
        if (Build.VERSION.SDK_INT >= 23) {
            return (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(context,
                    Manifest.permission.READ_CONTACTS));
        } else {
            SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
            return preferences.getBoolean(CONTACTS_BOOK_ACCESS_KEY, false);
        }
    }
}