# HG changeset patch # User "Vincent Veronis" # Date 1313140395 -7200 # Node ID 43e0206f11354e4ca41e5516e3c1e37b345289ed # Parent 965a9876c37a22f57c7120493be962c3e37f0a56 Code format diff -r 965a9876c37a -r 43e0206f1135 src/com/beem/project/beem/BeemService.java --- a/src/com/beem/project/beem/BeemService.java Sat Jul 23 01:28:07 2011 +0200 +++ b/src/com/beem/project/beem/BeemService.java Fri Aug 12 11:13:15 2011 +0200 @@ -43,20 +43,13 @@ */ package com.beem.project.beem; -import java.io.IOException; -import java.util.ArrayList; import java.util.HashMap; import java.util.Map; -import org.jivesoftware.smack.ConnectionConfiguration; import org.jivesoftware.smack.Roster; -import org.jivesoftware.smack.RosterEntry; -import org.jivesoftware.smack.RosterGroup; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.Roster.SubscriptionMode; -import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.provider.ProviderManager; -import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.packet.ChatStateExtension; import org.jivesoftware.smackx.provider.DelayInfoProvider; import org.jivesoftware.smackx.provider.DiscoverInfoProvider; @@ -67,23 +60,16 @@ import org.jivesoftware.smackx.pubsub.provider.PubSubProvider; import android.accounts.Account; -import android.accounts.AccountManager; import android.app.Notification; import android.app.NotificationManager; import android.app.Service; import android.content.BroadcastReceiver; -import android.content.ContentProviderOperation; -import android.content.ContentUris; -import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.OperationApplicationException; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; -import android.database.Cursor; import android.net.ConnectivityManager; -import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; @@ -91,14 +77,10 @@ import android.os.Looper; import android.os.Message; import android.os.RemoteException; -import android.provider.ContactsContract; import android.util.Log; -import com.beem.project.beem.service.BeemAvatarCache; -import com.beem.project.beem.service.RosterAdapter; import com.beem.project.beem.service.XmppConnectionAdapter; import com.beem.project.beem.service.XmppFacade; -import com.beem.project.beem.service.aidl.IRoster; import com.beem.project.beem.service.aidl.IXmppFacade; import com.beem.project.beem.smack.avatar.AvatarMetadataProvider; import com.beem.project.beem.smack.avatar.AvatarProvider; @@ -119,9 +101,9 @@ private static final String TAG = "BeemService"; private static final int MESSAGE_CONNECT = 0x1; - private static final int MESSAGE_SEND_MSG = 0x2; - private static final int MESSAGE_SYNC = 0x3; - private static final int NB_DB_OPERATION = 50; + private static final int MESSAGE_DISCONNECT = 0x2; + private static final int MESSAGE_SEND_MSG = 0x3; + private static final int MESSAGE_SYNC = 0x4; private NotificationManager mNotificationManager; private Map mConnection = new HashMap(); @@ -293,7 +275,6 @@ */ public IXmppFacade getBind() { //TODO: Prendre le bon mbind dans le tableau - Log.e(TAG, "GETBIND"); return mBind.get(0); } @@ -469,6 +450,8 @@ String action = intent.getAction(); if (BeemIntent.ACTION_CONNECT.equals(action)) { msg = mHandler.obtainMessage(MESSAGE_CONNECT, intent.getExtras()); + } else if (BeemIntent.ACTION_DISCONNECT.equals(action)) { + msg = mHandler.obtainMessage(MESSAGE_DISCONNECT, intent.getExtras()); } else if (BeemIntent.ACTION_SEND_MESSAGE.equals(action)) { msg = mHandler.obtainMessage(MESSAGE_SEND_MSG, intent.getExtras()); } else if (BeemIntent.ACTION_SYNC.equals(action)) { @@ -493,6 +476,9 @@ case MESSAGE_CONNECT: handleConnect(b); break; + case MESSAGE_DISCONNECT: + handleDisconnect(b); + break; case MESSAGE_SEND_MSG: String account = b.getString(BeemIntent.EXTRA_ACCOUNT); XmppConnectionAdapter con = mConnection.get(account); @@ -500,14 +486,17 @@ con.handleMessage(msg); } break; - case MESSAGE_SYNC: + case MESSAGE_SYNC: Account a = b.getParcelable(BeemIntent.EXTRA_ACCOUNT); Bundle accountName = new Bundle(); accountName.putString(BeemIntent.EXTRA_ACCOUNT, a.name); + //TODO: Connect with option to not show status handleConnect(accountName); XmppConnectionAdapter co = mConnection.get(a.name); if (co != null) { - manageRoster(co.getAdaptee().getRoster(), a); + BeemSync sync = new BeemSync(getBaseContext()); + if (co.getAdaptee() != null) + sync.manageRoster(co.getAdaptee().getRoster(), a); } break; default: @@ -518,305 +507,54 @@ private void handleConnect(Bundle b) { Intent res = new Intent(BeemIntent.ACTION_DISCONNECTED); - + String account = null; if (b != null) { - Log.e("VIEW", "ID"+b.getInt("VIEW")); account = b.getString(BeemIntent.EXTRA_ACCOUNT); res.putExtra(BeemIntent.EXTRA_ACCOUNT, account); } - if (account == null) //TODO temporary - account = "dummy"; - if (account == null) { - //connect all + if (mConnection.containsKey(account)) { + res.setAction(BeemIntent.ACTION_CONNECTED); } else { - BeemConnection beemco = new BeemConnection(BeemService.this.getSharedPreferences(account, MODE_PRIVATE), - mPreferenceListener); - if (beemco.getSettings().getBoolean("settings_away_chk", false)) { - mOnOffReceiverIsRegistered = true; - registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF)); - registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON)); - } - mBeemConnection.put(account, beemco); - XmppConnectionAdapter beemcoAdapter = new XmppConnectionAdapter(beemco.getConnectionConfiguration(), beemco - .getJid(), beemco.getPassword(), this); - - try { - Log.i(TAG, "Starting connection of " + account); - if (beemcoAdapter.connectSync()) { - mConnection.put(account, beemcoAdapter); - mBind.put(account, new XmppFacade(beemcoAdapter)); - res.setAction(BeemIntent.ACTION_CONNECTED); - Log.e(TAG, "Account configuration : " + account.toString() + " DONE"); - } else { - Log.w(TAG, "Unable to connect " + account); + if (account == null) //TODO temporary + account = "dummy"; + if (account == null) { + //connect all + } else { + BeemConnection beemco = new BeemConnection( + BeemService.this.getSharedPreferences(account, MODE_PRIVATE), mPreferenceListener); + if (beemco.getSettings().getBoolean("settings_away_chk", false)) { + mOnOffReceiverIsRegistered = true; + registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF)); + registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON)); } - } catch (RemoteException e) { - Log.e(TAG, "Unable to connect " + account, e); - } - sendBroadcast(res); - } - } - - /** - * Method to execute content provider operation. - * @param ops - */ - private void executeOperation(final ArrayList ops) { - try { - getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); - } catch (RemoteException e) { - Log.d(TAG, "Error during sync of contact", e); - } catch (OperationApplicationException e) { - Log.d(TAG, "Error during sync of contact", e); - } - ops.clear(); - } + mBeemConnection.put(account, beemco); + XmppConnectionAdapter beemcoAdapter = new XmppConnectionAdapter(beemco.getConnectionConfiguration(), + beemco.getJid(), beemco.getPassword(), this); - /** - * Roster sync method. - * @param r The roster to sync - * @param a The account related - */ - private void manageRoster(final Roster r, final Account a) { - Log.e("OOO", "roster" + r + "account" + a); - ArrayList ops = new ArrayList(); - for (RosterGroup group : r.getGroups()) { - if (group != null) { - manageGroup(ops, a, group); - } - if (ops.size() > NB_DB_OPERATION) - executeOperation(ops); - } - if (ops.size() > 0) - executeOperation(ops); - for (RosterEntry entry : r.getEntries()) { - if (entry != null) { - long rawContactID = manageEntry(ops, a, entry); - addUpdateStatus(ops, entry, r.getPresence(entry.getUser()), rawContactID); - } - if (ops.size() > NB_DB_OPERATION) - executeOperation(ops); - } - if (ops.size() > 0) - executeOperation(ops); - } + try { + Log.i(TAG, "Starting connection of " + account); + if (beemcoAdapter.connectSync()) { + mConnection.put(account, beemcoAdapter); + mBind.put(account, new XmppFacade(beemcoAdapter)); + res.setAction(BeemIntent.ACTION_CONNECTED); + Log.e(TAG, "Account configuration : " + account.toString() + " DONE"); + } else { + Log.w(TAG, "Unable to connect " + account); + } + } catch (RemoteException e) { + Log.e(TAG, "Unable to connect " + account, e); + } - private void manageGroup(ArrayList ops, Account account, RosterGroup group) { - Log.i(TAG, "Sync group : " + group.getName() + " " + group.getEntryCount()); - long rawGroupID = getRawGroupID(account.name, group.getName()); - if (rawGroupID == -1) { - ContentProviderOperation.Builder builder = ContentProviderOperation - .newInsert(ContactsContract.Groups.CONTENT_URI); - builder.withValue(ContactsContract.Groups.ACCOUNT_NAME, account.name); - builder.withValue(ContactsContract.Groups.ACCOUNT_TYPE, account.type); - builder.withValue(ContactsContract.Groups.TITLE, group.getName()); - ops.add(builder.build()); + } } - } - - /** - * RosterEntry sync method. - * @param ops The content provider operation - * @param account The account related - * @param entry The roster entry to sync - * @return The raw contact ID - */ - private long manageEntry(ArrayList ops, Account account, RosterEntry entry) { - long rawContactID = getRawContactID(account.name, entry.getUser()); - Log.i(TAG, "Sync Contact : " + entry.getUser() + " RawContactID : " + rawContactID); - if (rawContactID == -1) { // Not found in database, add new - ContentValues values = new ContentValues(); - values.put(ContactsContract.RawContacts.ACCOUNT_TYPE, account.type); - values.put(ContactsContract.RawContacts.ACCOUNT_NAME, account.name); - values.put(ContactsContract.RawContacts.SOURCE_ID, entry.getUser()); - Uri rawContactUri = getContentResolver().insert(ContactsContract.RawContacts.CONTENT_URI, values); - rawContactID = ContentUris.parseId(rawContactUri); - values.clear(); - ContentProviderOperation.Builder builder = addUpdateStructuredName(entry, rawContactID, true); - ops.add(builder.build()); - for (RosterGroup group : entry.getGroups()) { - builder = addUpdateGroup(entry, rawContactID, getRawGroupID(account.name, group.getName()), true); - ops.add(builder.build()); - } - builder = createProfile(entry, rawContactID, account); - ops.add(builder.build()); - } else { // Found, update - ContentProviderOperation.Builder builder = addUpdateStructuredName(entry, rawContactID, false); - ops.add(builder.build()); - //TODO: ADD AVATAR - //builder = addUpdatePhoto(entry, rawContactID, false); - //ops.add(builder.build()); - } - return rawContactID; + sendBroadcast(res); } - /** - * Method to insert or update structured name informations. - * @param entry The roster entry to sync - * @param rawContactID The contact ID in the android database - * @param isInsert Insert boolean - * @return - */ - private ContentProviderOperation.Builder addUpdateStructuredName(RosterEntry entry, long rawContactID, - boolean isInsert) { - String displayName = entry.getName() != null ? entry.getName() : entry.getUser(); - ContentProviderOperation.Builder builder; - if (isInsert) { - builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); - builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID); - builder.withValue(ContactsContract.Data.MIMETYPE, - ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE); - builder.withValue(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, rawContactID); - } else { - builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI); - builder.withSelection( - ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID + " =? AND " - + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE - + "'", new String[] { String.valueOf(rawContactID) }); - } - builder.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName); - builder.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, displayName); - builder.withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, displayName); - return builder; - } - - private ContentProviderOperation.Builder addUpdatePhoto(RosterEntry entry, long rawContactID, boolean isInsert) { - String displayName = entry.getName() != null ? entry.getName() : entry.getUser(); - ContentProviderOperation.Builder builder; - if (isInsert) { - builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); - builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID); - builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE); - builder.withValue(ContactsContract.CommonDataKinds.Photo.RAW_CONTACT_ID, rawContactID); - } else { - builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI); - builder.withSelection(ContactsContract.CommonDataKinds.Photo.RAW_CONTACT_ID + " =? AND " - + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE - + "'", new String[] { String.valueOf(rawContactID) }); - } - BeemAvatarCache bac = new BeemAvatarCache(getBaseContext()); - try { - builder.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, bac.get(entry.getUser())); - } catch (IOException e) { - Log.e(TAG, "Error cache beem avatar", e); - } - return builder; - } - - /** - * Method to insert or update group name informations. - * @param entry The roster entry to sync - * @param rawContactID The contact ID in the android database - * @param rawGroupID The group ID in the android database - * @param isInsert Insert boolean - * @return - */ - private ContentProviderOperation.Builder addUpdateGroup(RosterEntry entry, long rawContactID, long rawGroupID, - boolean isInsert) { - String displayName = entry.getName() != null ? entry.getName() : entry.getUser(); - Log.e(TAG + "UPDATE GROUP", "Contact : " + displayName + " GroupID :" + rawGroupID); - ContentProviderOperation.Builder builder = null; - if (isInsert) { - builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); - builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID); - builder.withValue(ContactsContract.Data.MIMETYPE, - ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE); - builder.withValue(ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID, rawGroupID); - } - //TODO: delete - contact doesnt appear anymore in this group - return builder; - } - - /** - * Method to insert or update IM informations. - * @param entry The roster entry to sync - * @param rawContactID The contact ID in the android database - * @param isInsert Insert boolean - * @return - */ - private ContentProviderOperation.Builder createProfile(RosterEntry entry, long rawContactID, Account account) { - String displayName = entry.getName() != null ? entry.getName() : entry.getUser(); - ContentProviderOperation.Builder builder; - builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); - builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID); - builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE); - builder.withValue(ContactsContract.CommonDataKinds.Im.RAW_CONTACT_ID, rawContactID); - builder.withValue(ContactsContract.CommonDataKinds.Im.DATA1, displayName); - builder.withValue(ContactsContract.CommonDataKinds.Im.PROTOCOL, - ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER); - return builder; - } - - /** - * Method to insert or update IM informations. - * @param entry The roster entry to sync - * @param rawContactID The contact ID in the android database - * @param isInsert Insert boolean - * @return - */ - private void addUpdateStatus(ArrayList ops, RosterEntry entry, Presence p, - long rawContactID) { - String displayName = entry.getName() != null ? entry.getName() : entry.getUser(); - Log.i(TAG + "UPDATESTATUS", "Contact : " + displayName + " Presence status : " + p.getStatus() - + " Presence status state : " + Status.getStatusFromPresence(p)); - ContentProviderOperation.Builder builder; - builder = ContentProviderOperation.newInsert(ContactsContract.StatusUpdates.CONTENT_URI); - builder.withValue(ContactsContract.StatusUpdates.PROTOCOL, ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER); - builder.withValue(ContactsContract.StatusUpdates.IM_HANDLE, displayName); - //TODO: Get account name - builder.withValue(ContactsContract.StatusUpdates.IM_ACCOUNT, "beem@elyzion.net"); - builder.withValue(ContactsContract.StatusUpdates.STATUS, p.getStatus()); - builder.withValue(ContactsContract.StatusUpdates.STATUS_RES_PACKAGE, "com.beem.project.beem"); - builder.withValue(ContactsContract.StatusUpdates.STATUS_LABEL, R.string.app_name); - //TODO: Get status icon - builder.withValue(ContactsContract.StatusUpdates.STATUS_ICON, R.drawable.beem_status_icon); - //TODO: Pb presence ... 2 appear on 3 raw .... random appear - builder.withValue(ContactsContract.StatusUpdates.PRESENCE, Status.getStatusFromPresence(p)); - ops.add(builder.build()); - } - - /** - * Get contact ID from android database. - * @param account The account related - * @param jid The jid related - * @return ID in the database of the jid - */ - private long getRawContactID(String account, String jid) { - long authorId = -1; - final Cursor c = getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI, - new String[] { ContactsContract.RawContacts._ID, ContactsContract.RawContacts.SOURCE_ID }, - ContactsContract.RawContacts.ACCOUNT_NAME + "=? AND " + ContactsContract.RawContacts.SOURCE_ID + "=?", - new String[] { account, jid }, null); - try { - if (c.moveToFirst()) - authorId = c.getInt(c.getColumnIndex(ContactsContract.RawContacts._ID)); - } finally { - if (c != null) - c.close(); - } - return authorId; - } - - /** - * Get group ID from android database. - * @param account The account related - * @param group The group related - * @return ID in the database of the jid - */ - private long getRawGroupID(String account, String group) { - long authorId = -1; - final Cursor c = getContentResolver().query(ContactsContract.Groups.CONTENT_URI, - new String[] { ContactsContract.Groups._ID }, - ContactsContract.Groups.ACCOUNT_NAME + "=? AND " + ContactsContract.Groups.TITLE + "=?", - new String[] { account, group }, null); - try { - if (c.moveToFirst()) - authorId = c.getInt(c.getColumnIndex(ContactsContract.Groups._ID)); - } finally { - if (c != null) - c.close(); - } - return authorId; + private void handleDisconnect(Bundle b) { + Intent res = new Intent(BeemIntent.ACTION_DISCONNECTED); + String account = b.getString(BeemIntent.EXTRA_ACCOUNT); + mConnection.remove(account); + sendBroadcast(res); } } diff -r 965a9876c37a -r 43e0206f1135 src/com/beem/project/beem/BeemSync.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/com/beem/project/beem/BeemSync.java Fri Aug 12 11:13:15 2011 +0200 @@ -0,0 +1,345 @@ +/* + BEEM is a videoconference application on the Android Platform. + + Copyright (C) 2009 by Frederic-Charles Barthelery, + Jean-Manuel Da Silva, + Nikita Kozlov, + Philippe Lago, + Jean Baptiste Vergely, + Vincent Veronis. + + This file is part of BEEM. + + BEEM 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. + + BEEM 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 BEEM. If not, see . + + Please send bug reports with examples or suggestions to + contact@beem-project.com or http://dev.beem-project.com/ + */ + +package com.beem.project.beem; + +import java.io.IOException; +import java.util.ArrayList; + +import org.jivesoftware.smack.Roster; +import org.jivesoftware.smack.RosterEntry; +import org.jivesoftware.smack.RosterGroup; +import org.jivesoftware.smack.packet.Presence; + +import android.accounts.Account; +import android.content.ContentProviderOperation; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Context; +import android.content.OperationApplicationException; +import android.database.Cursor; +import android.net.Uri; +import android.os.RemoteException; +import android.provider.ContactsContract; +import android.util.Log; + +import com.beem.project.beem.service.BeemAvatarCache; +import com.beem.project.beem.utils.Status; + +/** + * Roster synchronisation, informations in database. + * @author Vincent V. + */ +public class BeemSync { + + private static final String TAG = "BeemSync"; + private static final int NB_DB_OPERATION = 50; + + private Context mContext; + + /** + * Constructor. + * @param c the context parameter. + */ + public BeemSync(Context c) { + mContext = c; + } + + /** + * Method to execute content provider operation. + * @param ops + */ + private void executeOperation(final ArrayList ops) { + try { + mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); + } catch (RemoteException e) { + Log.d(TAG, "Error during sync of contact", e); + } catch (OperationApplicationException e) { + Log.d(TAG, "Error during sync of contact", e); + } + ops.clear(); + } + + /** + * Roster sync method. + * @param r The roster to sync + * @param a The account related + */ + public void manageRoster(final Roster r, final Account a) { + if (r == null) { + Log.w(TAG, "Roster is null cant sync informations"); + return; + } + ArrayList ops = new ArrayList(); + for (RosterGroup group : r.getGroups()) { + if (group != null) { + manageGroup(ops, a, group); + } + if (ops.size() > NB_DB_OPERATION) + executeOperation(ops); + } + if (ops.size() > 0) + executeOperation(ops); + for (RosterEntry entry : r.getEntries()) { + if (entry != null) { + long rawContactID = manageEntry(ops, a, entry); + addUpdateStatus(ops, entry, r.getPresence(entry.getUser()), rawContactID); + } + if (ops.size() > NB_DB_OPERATION) + executeOperation(ops); + } + if (ops.size() > 0) + executeOperation(ops); + } + + private void manageGroup(ArrayList ops, Account account, RosterGroup group) { + Log.i(TAG, "Sync group : " + group.getName() + " " + group.getEntryCount()); + long rawGroupID = getRawGroupID(account.name, group.getName()); + if (rawGroupID == -1) { + ContentProviderOperation.Builder builder = ContentProviderOperation + .newInsert(ContactsContract.Groups.CONTENT_URI); + builder.withValue(ContactsContract.Groups.ACCOUNT_NAME, account.name); + builder.withValue(ContactsContract.Groups.ACCOUNT_TYPE, account.type); + builder.withValue(ContactsContract.Groups.TITLE, group.getName()); + ops.add(builder.build()); + } + } + + /** + * RosterEntry sync method. + * @param ops The content provider operation + * @param account The account related + * @param entry The roster entry to sync + * @return The raw contact ID + */ + private long manageEntry(ArrayList ops, Account account, RosterEntry entry) { + long rawContactID = getRawContactID(account.name, entry.getUser()); + Log.i(TAG, "Sync Contact : " + entry.getUser() + " RawContactID : " + rawContactID); + if (rawContactID == -1) { // Not found in database, add new + ContentValues values = new ContentValues(); + values.put(ContactsContract.RawContacts.ACCOUNT_TYPE, account.type); + values.put(ContactsContract.RawContacts.ACCOUNT_NAME, account.name); + values.put(ContactsContract.RawContacts.SOURCE_ID, entry.getUser()); + Uri rawContactUri = mContext.getContentResolver().insert(ContactsContract.RawContacts.CONTENT_URI, values); + rawContactID = ContentUris.parseId(rawContactUri); + values.clear(); + ContentProviderOperation.Builder builder = addUpdateStructuredName(entry, rawContactID, true); + ops.add(builder.build()); + for (RosterGroup group : entry.getGroups()) { + builder = addUpdateGroup(entry, rawContactID, getRawGroupID(account.name, group.getName()), true); + ops.add(builder.build()); + } + builder = createProfile(entry, rawContactID, account); + ops.add(builder.build()); + } else { // Found, update + ContentProviderOperation.Builder builder = addUpdateStructuredName(entry, rawContactID, false); + ops.add(builder.build()); + //TODO: ADD AVATAR + //builder = addUpdatePhoto(entry, rawContactID, false); + //ops.add(builder.build()); + } + return rawContactID; + } + + /** + * Method to insert or update structured name informations. + * @param entry The roster entry to sync + * @param rawContactID The contact ID in the android database + * @param isInsert Insert boolean + * @return + */ + private ContentProviderOperation.Builder addUpdateStructuredName(RosterEntry entry, long rawContactID, + boolean isInsert) { + String displayName = entry.getName() != null ? entry.getName() : entry.getUser(); + ContentProviderOperation.Builder builder; + if (isInsert) { + builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); + builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID); + builder.withValue(ContactsContract.Data.MIMETYPE, + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE); + builder.withValue(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, rawContactID); + } else { + builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI); + builder.withSelection( + ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID + " =? AND " + + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE + + "'", new String[] { String.valueOf(rawContactID) }); + } + builder.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName); + builder.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, displayName); + builder.withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, displayName); + return builder; + } + + /** + * Method to insert or update avatar. + * @param entry The roster entry to sync + * @param rawContactID The contact ID in the android database + * @param isInsert Insert boolean + * @return + */ + private ContentProviderOperation.Builder addUpdatePhoto(RosterEntry entry, long rawContactID, boolean isInsert) { + String displayName = entry.getName() != null ? entry.getName() : entry.getUser(); + ContentProviderOperation.Builder builder; + if (isInsert) { + builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); + builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID); + builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE); + builder.withValue(ContactsContract.CommonDataKinds.Photo.RAW_CONTACT_ID, rawContactID); + } else { + builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI); + builder.withSelection(ContactsContract.CommonDataKinds.Photo.RAW_CONTACT_ID + " =? AND " + + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + + "'", new String[] { String.valueOf(rawContactID) }); + } + BeemAvatarCache bac = new BeemAvatarCache(mContext); + try { + builder.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, bac.get(entry.getUser())); + } catch (IOException e) { + Log.e(TAG, "Error cache beem avatar", e); + } + return builder; + } + + /** + * Method to insert or update group name informations. + * @param entry The roster entry to sync + * @param rawContactID The contact ID in the android database + * @param rawGroupID The group ID in the android database + * @param isInsert Insert boolean + * @return + */ + private ContentProviderOperation.Builder addUpdateGroup(RosterEntry entry, long rawContactID, long rawGroupID, + boolean isInsert) { + String displayName = entry.getName() != null ? entry.getName() : entry.getUser(); + Log.e(TAG + "UPDATE GROUP", "Contact : " + displayName + " GroupID :" + rawGroupID); + ContentProviderOperation.Builder builder = null; + if (isInsert) { + builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); + builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID); + builder.withValue(ContactsContract.Data.MIMETYPE, + ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE); + builder.withValue(ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID, rawGroupID); + } + //TODO: delete - contact doesnt appear anymore in this group + return builder; + } + + /** + * Method to insert or update IM informations. + * @param entry The roster entry to sync + * @param rawContactID The contact ID in the android database + * @param isInsert Insert boolean + * @return + */ + private ContentProviderOperation.Builder createProfile(RosterEntry entry, long rawContactID, Account account) { + String displayName = entry.getName() != null ? entry.getName() : entry.getUser(); + ContentProviderOperation.Builder builder; + builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); + builder.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID); + builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE); + builder.withValue(ContactsContract.CommonDataKinds.Im.RAW_CONTACT_ID, rawContactID); + builder.withValue(ContactsContract.CommonDataKinds.Im.DATA1, displayName); + builder.withValue(ContactsContract.CommonDataKinds.Im.PROTOCOL, + ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER); + return builder; + } + + /** + * Method to insert or update IM informations. + * @param entry The roster entry to sync + * @param rawContactID The contact ID in the android database + * @param isInsert Insert boolean + * @return + */ + private void addUpdateStatus(ArrayList ops, RosterEntry entry, Presence p, + long rawContactID) { + String displayName = entry.getName() != null ? entry.getName() : entry.getUser(); + Log.i(TAG + "UPDATESTATUS", "Contact : " + displayName + " Presence status : " + p.getStatus() + + " Presence status state : " + Status.getStatusFromPresence(p)); + ContentProviderOperation.Builder builder; + builder = ContentProviderOperation.newInsert(ContactsContract.StatusUpdates.CONTENT_URI); + builder.withValue(ContactsContract.StatusUpdates.PROTOCOL, ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER); + builder.withValue(ContactsContract.StatusUpdates.IM_HANDLE, displayName); + //TODO: Get account name + builder.withValue(ContactsContract.StatusUpdates.IM_ACCOUNT, "beem@elyzion.net"); + builder.withValue(ContactsContract.StatusUpdates.STATUS, p.getStatus()); + builder.withValue(ContactsContract.StatusUpdates.STATUS_RES_PACKAGE, "com.beem.project.beem"); + builder.withValue(ContactsContract.StatusUpdates.STATUS_LABEL, R.string.app_name); + //TODO: Get status icon + builder.withValue(ContactsContract.StatusUpdates.STATUS_ICON, R.drawable.beem_status_icon); + //TODO: Pb presence ... 2 appear on 3 raw .... random appear + builder.withValue(ContactsContract.StatusUpdates.PRESENCE, Status.getStatusFromPresence(p)); + ops.add(builder.build()); + } + + /** + * Get contact ID from android database. + * @param account The account related + * @param jid The jid related + * @return ID in the database of the jid + */ + private long getRawContactID(String account, String jid) { + long authorId = -1; + final Cursor c = mContext.getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI, + new String[] { ContactsContract.RawContacts._ID, ContactsContract.RawContacts.SOURCE_ID }, + ContactsContract.RawContacts.ACCOUNT_NAME + "=? AND " + ContactsContract.RawContacts.SOURCE_ID + "=?", + new String[] { account, jid }, null); + try { + if (c.moveToFirst()) + authorId = c.getInt(c.getColumnIndex(ContactsContract.RawContacts._ID)); + } finally { + if (c != null) + c.close(); + } + return authorId; + } + + /** + * Get group ID from android database. + * @param account The account related + * @param group The group related + * @return ID in the database of the jid + */ + private long getRawGroupID(String account, String group) { + long authorId = -1; + final Cursor c = mContext.getContentResolver().query(ContactsContract.Groups.CONTENT_URI, + new String[] { ContactsContract.Groups._ID }, + ContactsContract.Groups.ACCOUNT_NAME + "=? AND " + ContactsContract.Groups.TITLE + "=?", + new String[] { account, group }, null); + try { + if (c.moveToFirst()) + authorId = c.getInt(c.getColumnIndex(ContactsContract.Groups._ID)); + } finally { + if (c != null) + c.close(); + } + return authorId; + } +} diff -r 965a9876c37a -r 43e0206f1135 src/com/beem/project/beem/account/Authenticator.java --- a/src/com/beem/project/beem/account/Authenticator.java Sat Jul 23 01:28:07 2011 +0200 +++ b/src/com/beem/project/beem/account/Authenticator.java Fri Aug 12 11:13:15 2011 +0200 @@ -25,21 +25,6 @@ Please send bug reports with examples or suggestions to contact@beem-project.com or http://dev.beem-project.com/ - - Epitech, hereby disclaims all copyright interest in the program "Beem" - written by Frederic-Charles Barthelery, - Jean-Manuel Da Silva, - Nikita Kozlov, - Philippe Lago, - Jean Baptiste Vergely, - Vincent Veronis. - - Nicolas Sadirac, November 26, 2009 - President of Epitech. - - Flavien Astraud, November 26, 2009 - Head of the EIP Laboratory. - */ package com.beem.project.beem.account; diff -r 965a9876c37a -r 43e0206f1135 src/com/beem/project/beem/account/AuthenticatorService.java --- a/src/com/beem/project/beem/account/AuthenticatorService.java Sat Jul 23 01:28:07 2011 +0200 +++ b/src/com/beem/project/beem/account/AuthenticatorService.java Fri Aug 12 11:13:15 2011 +0200 @@ -25,21 +25,6 @@ Please send bug reports with examples or suggestions to contact@beem-project.com or http://dev.beem-project.com/ - - Epitech, hereby disclaims all copyright interest in the program "Beem" - written by Frederic-Charles Barthelery, - Jean-Manuel Da Silva, - Nikita Kozlov, - Philippe Lago, - Jean Baptiste Vergely, - Vincent Veronis. - - Nicolas Sadirac, November 26, 2009 - President of Epitech. - - Flavien Astraud, November 26, 2009 - Head of the EIP Laboratory. - */ package com.beem.project.beem.account; diff -r 965a9876c37a -r 43e0206f1135 src/com/beem/project/beem/account/SyncAdapter.java --- a/src/com/beem/project/beem/account/SyncAdapter.java Sat Jul 23 01:28:07 2011 +0200 +++ b/src/com/beem/project/beem/account/SyncAdapter.java Fri Aug 12 11:13:15 2011 +0200 @@ -25,21 +25,6 @@ Please send bug reports with examples or suggestions to contact@beem-project.com or http://dev.beem-project.com/ - - Epitech, hereby disclaims all copyright interest in the program "Beem" - written by Frederic-Charles Barthelery, - Jean-Manuel Da Silva, - Nikita Kozlov, - Philippe Lago, - Jean Baptiste Vergely, - Vincent Veronis. - - Nicolas Sadirac, November 26, 2009 - President of Epitech. - - Flavien Astraud, November 26, 2009 - Head of the EIP Laboratory. - */ package com.beem.project.beem.account; diff -r 965a9876c37a -r 43e0206f1135 src/com/beem/project/beem/account/SyncAdapterService.java --- a/src/com/beem/project/beem/account/SyncAdapterService.java Sat Jul 23 01:28:07 2011 +0200 +++ b/src/com/beem/project/beem/account/SyncAdapterService.java Fri Aug 12 11:13:15 2011 +0200 @@ -25,61 +25,23 @@ Please send bug reports with examples or suggestions to contact@beem-project.com or http://dev.beem-project.com/ - - Epitech, hereby disclaims all copyright interest in the program "Beem" - written by Frederic-Charles Barthelery, - Jean-Manuel Da Silva, - Nikita Kozlov, - Philippe Lago, - Jean Baptiste Vergely, - Vincent Veronis. - - Nicolas Sadirac, November 26, 2009 - President of Epitech. - - Flavien Astraud, November 26, 2009 - Head of the EIP Laboratory. - */ package com.beem.project.beem.account; -import java.io.IOException; -import java.util.ArrayList; - -import org.jivesoftware.smack.Roster; -import org.jivesoftware.smack.RosterEntry; -import org.jivesoftware.smack.RosterGroup; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.packet.Presence; - import android.accounts.Account; import android.accounts.OperationCanceledException; import android.app.Service; import android.content.ContentProviderClient; -import android.content.ContentProviderOperation; import android.content.ContentResolver; -import android.content.ContentUris; -import android.content.ContentValues; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; -import android.content.OperationApplicationException; import android.content.SyncResult; -import android.database.Cursor; -import android.net.Uri; import android.os.Bundle; import android.os.IBinder; -import android.os.RemoteException; -import android.provider.ContactsContract; import android.util.Log; -import com.beem.project.beem.BeemConnection; import com.beem.project.beem.BeemIntent; -import com.beem.project.beem.R; -import com.beem.project.beem.service.BeemAvatarCache; -import com.beem.project.beem.utils.Status; /** * Class to integrate beem in android's account. diff -r 965a9876c37a -r 43e0206f1135 src/com/beem/project/beem/ui/Login.java --- a/src/com/beem/project/beem/ui/Login.java Sat Jul 23 01:28:07 2011 +0200 +++ b/src/com/beem/project/beem/ui/Login.java Fri Aug 12 11:13:15 2011 +0200 @@ -81,10 +81,10 @@ */ public class Login extends Activity { - private BroadcastReceiver mReceiver; private BeemAccountList mAdapterAccountList; private List mListAccount = new ArrayList(); private final BeemAccountListOnClick mOnAccountClick = new BeemAccountListOnClick(); + private final BroadcastReceiver mOnBroadcastReceiver = new BeemBroadcastReceiver(); /** * Constructor. @@ -101,34 +101,6 @@ listView.setClickable(true); listView.setOnItemClickListener(mOnAccountClick); listView.setAdapter(mAdapterAccountList); - - mReceiver = new BroadcastReceiver() { - public void onReceive(Context ctx, Intent intent) { - String action = intent.getAction(); - String account = intent.getExtras().getString(BeemIntent.EXTRA_ACCOUNT); - int hash = account.hashCode(); - if (hash < 0 ) hash = hash - 2 * hash; - - View v = findViewById(hash); - TextView text = (TextView) v.findViewById(R.id.accountstatus); - ImageButton logo = (ImageButton) v.findViewById(R.id.loginanim_logo_anim); - - if (BeemIntent.ACTION_CONNECTED.equals(action)) { - if (text != null) text.setText(R.string.contact_status_msg_available); - if (logo != null) { - logo.setImageResource(R.drawable.beem_launcher_icon_color); - logo.clearAnimation(); - } - } else if (BeemIntent.ACTION_DISCONNECTED.equals(action)) { - if (text != null) text.setText(R.string.contact_status_msg_offline); - if (logo != null) { - logo.setImageResource(R.drawable.beem_launcher_icon_silver); - logo.clearAnimation(); - } - } - } - }; - } @Override @@ -228,8 +200,9 @@ logo.setOnClickListener(new BeemConnectionOnClick(v)); TextView name = (TextView) v.findViewById(R.id.accountname); name.setText(mListAccount.get(position)); - int hash = mListAccount.get(position).hashCode(); - if (hash < 0 ) hash = hash - 2 * hash; + int hash = mListAccount.get(position).hashCode(); + if (hash < 0) + hash = hash - 2 * hash; v.setId(hash); return v; } @@ -237,16 +210,18 @@ } /** - * Event simple click on item of the bitton of account list. + * Event simple click on item of the button of account list. */ private class BeemConnectionOnClick implements android.view.View.OnClickListener { private View mView; + /** * Constructor. */ public BeemConnectionOnClick(View v) { mView = v; } + @Override public void onClick(View v) { //TODO: Check if already connected -> disconnect @@ -261,7 +236,7 @@ intent.putExtra(BeemIntent.EXTRA_ACCOUNT, accountName.getText()); IntentFilter filter = new IntentFilter(BeemIntent.ACTION_CONNECTED); filter.addAction(BeemIntent.ACTION_DISCONNECTED); - registerReceiver(mReceiver, filter); + registerReceiver(mOnBroadcastReceiver, filter); startService(intent); } } @@ -282,9 +257,55 @@ @Override public void onItemClick(AdapterView arg0, View v, int pos, long lpos) { Intent i = new Intent(Login.this, ContactList.class); - TextView accountName = (TextView)v.findViewById(R.id.accountname); - i.putExtra(BeemIntent.EXTRA_ACCOUNT, accountName.getText()); + TextView accountName = (TextView) v.findViewById(R.id.accountname); + i.putExtra(BeemIntent.EXTRA_ACCOUNT, accountName.getText()); startActivity(i); } - } + } + + /** + * Event receive from service. + */ + private class BeemBroadcastReceiver extends BroadcastReceiver { + + /** + * Constructor. + */ + public BeemBroadcastReceiver() { + + } + + /** + * {@inheritDoc} + */ + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + String account = intent.getExtras().getString(BeemIntent.EXTRA_ACCOUNT); + int hash = account.hashCode(); + if (hash < 0) + hash = hash - 2 * hash; + + View v = findViewById(hash); + TextView text = (TextView) v.findViewById(R.id.accountstatus); + ImageButton logo = (ImageButton) v.findViewById(R.id.loginanim_logo_anim); + + if (BeemIntent.ACTION_CONNECTED.equals(action)) { + if (text != null) + text.setText(R.string.contact_status_msg_available); + if (logo != null) { + logo.setImageResource(R.drawable.beem_launcher_icon_color); + logo.clearAnimation(); + } + } else if (BeemIntent.ACTION_DISCONNECTED.equals(action)) { + if (text != null) + text.setText(R.string.contact_status_msg_offline); + if (logo != null) { + logo.setImageResource(R.drawable.beem_launcher_icon_silver); + logo.clearAnimation(); + } + } + } + + } }