/** * Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr) * This file is part of CSipSimple. * * CSipSimple is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * If you own a pjsip commercial license you can also redistribute it * and/or modify it under the terms of the GNU Lesser General Public License * as an android library. * * CSipSimple is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with CSipSimple. If not, see <http://www.gnu.org/licenses/>. */ package com.csipsimple.ui.favorites; import android.app.AlertDialog; import android.app.Dialog; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.Intent; import android.database.Cursor; import android.database.DatabaseUtils; import android.provider.BaseColumns; import android.provider.ContactsContract.Contacts; import android.support.v4.widget.ResourceCursorAdapter; import android.text.TextUtils; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.widget.ImageView; import android.widget.TextView; import com.actionbarsherlock.internal.utils.UtilityWrapper; import com.actionbarsherlock.internal.view.menu.ActionMenuPresenter; import com.actionbarsherlock.internal.view.menu.ActionMenuView; import com.actionbarsherlock.internal.view.menu.MenuBuilder; import com.actionbarsherlock.internal.view.menu.MenuBuilder.Callback; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import com.csipsimple.R; import com.csipsimple.api.SipManager; import com.csipsimple.api.SipProfile; import com.csipsimple.api.SipUri; import com.csipsimple.models.Filter; import com.csipsimple.utils.ContactsAsyncHelper; import com.csipsimple.utils.Log; import com.csipsimple.utils.contacts.ContactsWrapper; import com.csipsimple.utils.contacts.ContactsWrapper.ContactInfo; import com.csipsimple.utils.contacts.ContactsWrapper.Phone; import com.csipsimple.widgets.contactbadge.QuickContactBadge; import com.csipsimple.wizards.WizardUtils; import java.util.List; public class FavAdapter extends ResourceCursorAdapter implements OnClickListener { private static final String THIS_FILE = "FavAdapter"; /** Listener for the primary action in the list, opens the call details. */ private final View.OnClickListener mPrimaryActionListener = new View.OnClickListener() { @Override public void onClick(View view) { ContactInfo ci = (ContactInfo) view.getTag(); Intent it = ContactsWrapper.getInstance().getViewContactIntent(ci.contactId); mContext.startActivity(it); } }; /** Listener for the secondary action in the list, either call or play. */ private final View.OnClickListener mSecondaryActionListener = new View.OnClickListener() { @Override public void onClick(View view) { ContactInfo ci = (ContactInfo) view.getTag(); List<String> phones = ContactsWrapper.getInstance().getCSipPhonesContact(mContext, ci.contactId); boolean useCSip = true; String toCall = null; if(phones != null && phones.size() > 0) { toCall = phones.get(0); }else { List<Phone> cPhones = ContactsWrapper.getInstance().getPhoneNumbers(mContext, ci.contactId, ContactsWrapper.URI_ALLS); if(cPhones != null && cPhones.size() > 0) { toCall = cPhones.get(0).getNumber(); useCSip = false; } } if(!TextUtils.isEmpty(toCall) ) { Cursor c = (Cursor) getItem((Integer) ci.userData); Long profileId = null; while(c.moveToPrevious()) { int cTypeIdx = c.getColumnIndex(ContactsWrapper.FIELD_TYPE); int cAccIdx = c.getColumnIndex(BaseColumns._ID); if(cTypeIdx >= 0 && cAccIdx >= 0) { if(c.getInt(cTypeIdx) == ContactsWrapper.TYPE_GROUP) { profileId = c.getLong(cAccIdx); break; } } } Intent it = new Intent(Intent.ACTION_CALL); it.setData(SipUri.forgeSipUri(useCSip ? SipManager.PROTOCOL_CSIP : SipManager.PROTOCOL_SIP, toCall)); it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if(profileId != null) { it.putExtra(SipProfile.FIELD_ACC_ID, profileId); } mContext.startActivity(it); } } }; public FavAdapter(Context context, Cursor c) { super(context, R.layout.fav_list_item, c, 0); } @Override public void bindView(View view, final Context context, Cursor cursor) { ContentValues cv = new ContentValues(); DatabaseUtils.cursorRowToContentValues(cursor, cv); int type = ContactsWrapper.TYPE_CONTACT; if(cv.containsKey(ContactsWrapper.FIELD_TYPE)) { type = cv.getAsInteger(ContactsWrapper.FIELD_TYPE); } showViewForType(view, type); if(type == ContactsWrapper.TYPE_GROUP) { // Get views TextView tv = (TextView) view.findViewById(R.id.header_text); ImageView icon = (ImageView) view.findViewById(R.id.header_icon); PresenceStatusSpinner presSpinner = (PresenceStatusSpinner) view.findViewById(R.id.header_presence_spinner); // Get datas SipProfile acc = new SipProfile(cursor); final Long profileId = cv.getAsLong(BaseColumns._ID); final String groupName = acc.android_group; final String displayName = acc.display_name; final String wizard = acc.wizard; final boolean publishedEnabled = (acc.publish_enabled == 1); final String domain = acc.getDefaultDomain(); // Bind datas to view tv.setText(displayName); icon.setImageResource(WizardUtils.getWizardIconRes(wizard)); presSpinner.setProfileId(profileId); // Extra menu view if not already set ViewGroup menuViewWrapper = (ViewGroup) view.findViewById(R.id.header_cfg_spinner); MenuCallback newMcb = new MenuCallback(context, profileId, groupName, domain, publishedEnabled); MenuBuilder menuBuilder; if(menuViewWrapper.getTag() == null) { final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); ActionMenuPresenter mActionMenuPresenter = new ActionMenuPresenter(mContext); mActionMenuPresenter.setReserveOverflow(true); menuBuilder = new MenuBuilder(context); menuBuilder.setCallback(newMcb); MenuInflater inflater = new MenuInflater(context); inflater.inflate(R.menu.fav_menu, menuBuilder); menuBuilder.addMenuPresenter(mActionMenuPresenter); ActionMenuView menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(menuViewWrapper); UtilityWrapper.getInstance().setBackgroundDrawable(menuView, null); menuViewWrapper.addView(menuView, layoutParams); menuViewWrapper.setTag(menuBuilder); }else { menuBuilder = (MenuBuilder) menuViewWrapper.getTag(); menuBuilder.setCallback(newMcb); } menuBuilder.findItem(R.id.share_presence).setTitle(publishedEnabled ? R.string.deactivate_presence_sharing : R.string.activate_presence_sharing); menuBuilder.findItem(R.id.set_sip_data).setVisible(!TextUtils.isEmpty(groupName)); }else if(type == ContactsWrapper.TYPE_CONTACT) { ContactInfo ci = ContactsWrapper.getInstance().getContactInfo(context, cursor); ci.userData = cursor.getPosition(); // Get views TextView tv = (TextView) view.findViewById(R.id.contact_name); QuickContactBadge badge = (QuickContactBadge) view.findViewById(R.id.quick_contact_photo); TextView statusText = (TextView) view.findViewById(R.id.status_text); ImageView statusImage = (ImageView) view.findViewById(R.id.status_icon); // Bind if(ci.contactId != null) { tv.setText(ci.displayName); badge.assignContactUri(ci.callerInfo.contactContentUri); ContactsAsyncHelper.updateImageViewWithContactPhotoAsync(context, badge.getImageView(), ci.callerInfo, R.drawable.ic_contact_picture_holo_dark); statusText.setVisibility(ci.hasPresence ? View.VISIBLE : View.GONE); statusText.setText(ci.status); statusImage.setVisibility(ci.hasPresence ? View.VISIBLE : View.GONE); statusImage.setImageResource(ContactsWrapper.getInstance().getPresenceIconResourceId(ci.presence)); } View v; v = view.findViewById(R.id.contact_view); v.setTag(ci); v.setOnClickListener(mPrimaryActionListener); v = view.findViewById(R.id.secondary_action_icon); v.setTag(ci); v.setOnClickListener(mSecondaryActionListener); } else if (type == ContactsWrapper.TYPE_CONFIGURE) { // We only bind if it's the correct type View v = view.findViewById(R.id.configure_view); v.setOnClickListener(this); ConfigureObj cfg = new ConfigureObj(); cfg.profileId = cv.getAsLong(BaseColumns._ID); v.setTag(cfg); } } private class ConfigureObj extends Object { Long profileId = SipProfile.INVALID_ID; String groupName = ""; } private void showViewForType(View view, int type) { view.findViewById(R.id.header_view).setVisibility((type == ContactsWrapper.TYPE_GROUP) ? View.VISIBLE : View.GONE); view.findViewById(R.id.contact_view).setVisibility((type == ContactsWrapper.TYPE_CONTACT) ? View.VISIBLE : View.GONE); view.findViewById(R.id.configure_view).setVisibility((type == ContactsWrapper.TYPE_CONFIGURE) ? View.VISIBLE : View.GONE); } private class MenuCallback implements Callback { private Long profileId = SipProfile.INVALID_ID; private Context context; private String groupName; private String domain; private boolean publishEnabled; public MenuCallback(Context ctxt, Long aProfileId, String aGroupName, String aDomain, boolean aPublishedEnabled) { profileId = aProfileId; context = ctxt; groupName = aGroupName; domain = aDomain; publishEnabled = aPublishedEnabled; } @Override public void onMenuModeChange(MenuBuilder menu) { // Nothing to do } @Override public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { int itemId = item.getItemId(); if(itemId == R.id.set_group) { showDialogForGroupSelection(context, profileId, groupName); return true; }else if(itemId == R.id.share_presence) { ContentValues cv = new ContentValues(); cv.put(SipProfile.FIELD_PUBLISH_ENABLED, publishEnabled ? 0 : 1); context.getContentResolver().update(ContentUris.withAppendedId(SipProfile.ACCOUNT_ID_URI_BASE, profileId), cv, null, null); return true; }else if(itemId == R.id.set_sip_data) { showDialogForSipData(context, profileId, groupName, domain); return true; } return false; } } private void showDialogForGroupSelection(final Context context, final Long profileId, final String groupName) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.set_android_group); final Cursor choiceCursor = ContactsWrapper.getInstance().getGroups(context); int selectedIndex = -1; if(choiceCursor != null) { if (choiceCursor.moveToFirst()) { int i = 0; int colIdx = choiceCursor.getColumnIndex(ContactsWrapper.FIELD_GROUP_NAME); do { String name = choiceCursor.getString(colIdx); if(!TextUtils.isEmpty(name) && name.equalsIgnoreCase(groupName)) { selectedIndex = i; break; } i ++; } while (choiceCursor.moveToNext()); } } builder.setSingleChoiceItems(choiceCursor, selectedIndex, ContactsWrapper.FIELD_GROUP_NAME, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if(choiceCursor != null) { choiceCursor.moveToPosition(which); String name = choiceCursor.getString(choiceCursor.getColumnIndex(ContactsWrapper.FIELD_GROUP_NAME)); ContentValues cv = new ContentValues(); cv.put(SipProfile.FIELD_ANDROID_GROUP, name); context.getContentResolver().update(ContentUris.withAppendedId(SipProfile.ACCOUNT_ID_URI_BASE, profileId), cv, null, null); choiceCursor.close(); } dialog.dismiss(); } }); builder.setCancelable(true); builder.setNeutralButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if(choiceCursor != null) { choiceCursor.close(); } dialog.dismiss(); } }); builder.setOnCancelListener(new OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { if(choiceCursor != null) { choiceCursor.close(); } } }); final Dialog dialog = builder.create(); dialog.show(); } private void showDialogForSipData(final Context context, final Long profileId, final String groupName, final String domain) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.set_android_group); builder.setCancelable(true); builder.setItems(R.array.sip_data_sources, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { applyNumbersToCSip(groupName, 1 << which, domain, profileId); } }); final Dialog dialog = builder.create(); dialog.show(); } @Override public void onClick(View v) { int id = v.getId(); if(id == R.id.configure_view) { ConfigureObj cfg = (ConfigureObj) v.getTag(); showDialogForGroupSelection(mContext, cfg.profileId, cfg.groupName); } } private void applyNumbersToCSip(String groupName, int flag, String domain, long profileId) { Log.d(THIS_FILE, "Apply numbers to csip " + groupName + " > " + domain); ContactsWrapper cw = ContactsWrapper.getInstance(); Cursor c = cw.getContactsByGroup(mContext, groupName); try { while (c.moveToNext()) { long contactId = c.getLong(c.getColumnIndex(Contacts._ID)); List<Phone> phones = cw.getPhoneNumbers(mContext, contactId, flag); if(phones.size() > 0){ String nbr = phones.get(0).getNumber(); if(!nbr.contains("@")){ if(flag == ContactsWrapper.URI_NBR) { // Apply rewriting rules nbr = Filter.rewritePhoneNumber(mContext, profileId, nbr); } nbr += "@" + domain; } Log.d(THIS_FILE, "Apply number to " + contactId + " > " + nbr); cw.insertOrUpdateCSipUri(mContext, contactId, nbr); } } } catch (Exception e) { Log.e(THIS_FILE, "Error while looping on contacts", e); } finally { c.close(); } } }