com.gsma.rcs.ri.utils.RcsContactUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.gsma.rcs.ri.utils.RcsContactUtil.java

Source

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

import com.gsma.rcs.api.connection.ConnectionManager;
import com.gsma.rcs.api.connection.utils.ExceptionUtil;
import com.gsma.rcs.ri.R;
import com.gsma.services.rcs.RcsServiceException;
import com.gsma.services.rcs.RcsServiceNotAvailableException;
import com.gsma.services.rcs.contact.ContactId;
import com.gsma.services.rcs.contact.ContactService;
import com.gsma.services.rcs.contact.RcsContact;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.ContactsContract;
import android.support.v4.util.LruCache;
import android.util.Log;

import java.io.InputStream;

/**
 * Utilities to manage the RCS display name
 * 
 * @author Philippe LEMORDANT
 */
public class RcsContactUtil {

    private static final int MAX_DISPLAY_NAME_IN_CACHE = 200;
    private static final String LOGTAG = LogUtils.getTag(RcsContactUtil.class.getSimpleName());

    private static volatile RcsContactUtil sInstance;
    private final ContentResolver mResolver;
    private ContactService mService;
    private final String mDefaultDisplayName;
    private LruCache<ContactId, String> mDisplayNameAndroidCache;
    private LruCache<ContactId, Bitmap> mPhotoContactCache;

    private static final String[] PROJ_DISPLAY_NAME = new String[] { ContactsContract.PhoneLookup.DISPLAY_NAME };

    private static final String[] PROJ_CONTACT_ID = new String[] { ContactsContract.PhoneLookup._ID };

    /**
     * Constructor
     * 
     * @param context the context
     */
    private RcsContactUtil(Context context) {
        mService = ConnectionManager.getInstance().getContactApi();
        mResolver = context.getContentResolver();
        mDefaultDisplayName = context.getString(R.string.label_no_contact);
        mDisplayNameAndroidCache = new LruCache<>(MAX_DISPLAY_NAME_IN_CACHE);
        mPhotoContactCache = new LruCache<>(MAX_DISPLAY_NAME_IN_CACHE);
    }

    /**
     * Get an instance of RcsDisplayName.
     * 
     * @param context the context
     * @return the singleton instance.
     */
    public static RcsContactUtil getInstance(Context context) {
        if (sInstance != null) {
            return sInstance;
        }
        synchronized (RcsContactUtil.class) {
            if (sInstance == null) {
                sInstance = new RcsContactUtil(context);
            }
            return sInstance;
        }
    }

    private String getDisplayNameFromAddressBook(ContactId contact) {
        /* First try to get it from cache */
        String displayName = mDisplayNameAndroidCache.get(contact);
        if (displayName != null) {
            return displayName;
        }
        /* Not found in cache: query the Android address book */
        Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
                Uri.encode(contact.toString()));
        Cursor cursor = null;
        try {
            cursor = mResolver.query(uri, PROJ_DISPLAY_NAME, null, null, null);
            if (cursor == null) {
                throw new SQLException("Cannot query display name for contact=" + contact);
            }
            if (!cursor.moveToFirst()) {
                return null;
            }
            displayName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.PhoneLookup.DISPLAY_NAME));
            /* Insert in cache */
            mDisplayNameAndroidCache.put(contact, displayName);
            return displayName;

        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }

    /**
     * Returns display name which can be displayed on UI
     * 
     * @param contact the contact
     * @return the display name
     */
    public String getDisplayName(ContactId contact) {
        if (contact == null) {
            return mDefaultDisplayName;
        }
        String displayName = getDisplayNameFromAddressBook(contact);
        if (displayName != null) {
            /*
             * Contact exists in Android Address Book: returns the AB display name.
             */
            return displayName;
        }
        try {
            if (mService == null) {
                mService = ConnectionManager.getInstance().getContactApi();
            }
            RcsContact rcsContact = mService.getRcsContact(contact);
            if (rcsContact == null) {
                /*
                 * Contact is not RCS: returns the phone number.
                 */
                return contact.toString();
            }
            displayName = rcsContact.getDisplayName();
            if (displayName == null) {
                return contact.toString();
            } else {
                return displayName;
            }
        } catch (RcsServiceNotAvailableException ignore) {

        } catch (RcsServiceException e) {
            Log.w(LOGTAG, ExceptionUtil.getFullStackTrace(e));
        }
        /* By default display name is set to the MSISDN */
        return contact.toString();
    }

    /**
     * get RCS display in a String which can be displayed on UI
     * 
     * @param number the phone number
     * @return the name which can be displayed on UI
     */
    public String getDisplayName(String number) {
        if (number == null) {
            return mDefaultDisplayName;
        }
        if (!ContactUtil.isValidContact(number)) {
            return number;
        }
        ContactId contact = ContactUtil.formatContact(number);
        return getDisplayName(contact);
    }

    /**
     * Gets the photo of a contact, or null if no photo is present
     * 
     * @param contact the contact ID
     * @return an Bitmap of the photo, or null if no photo is present
     */
    public Bitmap getPhotoFromContactId(ContactId contact) {
        /* First try to get it from cache */
        Bitmap photo = mPhotoContactCache.get(contact);
        if (photo != null) {
            return photo;
        }
        Uri contactUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_FILTER_URI,
                Uri.encode(contact.toString()));
        Cursor cursor = null;
        try {
            cursor = mResolver.query(contactUri, PROJ_CONTACT_ID, null, null, null);
            if (cursor == null) {
                throw new SQLException("Cannot query photo for contact=" + contact);
            }
            if (!cursor.moveToFirst()) {
                return null;
            }
            long contactId = cursor.getLong(cursor.getColumnIndexOrThrow(ContactsContract.PhoneLookup._ID));
            InputStream photoInputStream = ContactsContract.Contacts.openContactPhotoInputStream(mResolver,
                    ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId));
            if (photoInputStream != null) {
                photo = BitmapFactory.decodeStream(photoInputStream);
                /* Insert in cache */
                mPhotoContactCache.put(contact, photo);
                return photo;
            }
            return null;

        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }
}