# HG changeset patch # User "Vincent Veronis" # Date 1311282206 -7200 # Node ID 07de7eb304b6e11e804ff3c58b9fd3ed2731098e # Parent c2c6ee3d3c7121653c543c476066c1c39378f012 New Concept service from da_risk but not up to date. Synchronisation done via new service diff -r c2c6ee3d3c71 -r 07de7eb304b6 AndroidManifest.xml --- a/AndroidManifest.xml Mon Jun 13 15:00:23 2011 +0200 +++ b/AndroidManifest.xml Thu Jul 21 23:03:26 2011 +0200 @@ -158,12 +158,12 @@ android:name=".providers.AvatarProvider" android:label="Avatar Provider" android:authorities="com.beem.project.beem.providers.avatarprovider" - android:exported="false" /> + android:exported="false" /> + android:exported="false" /> + + + + + + + . + + 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; + +public class BeemIntent { + + public static final String ACTION_CONNECT = "com.beem.project.beem.intent.action.CONNECT"; + + public static final String ACTION_DISCONNECT = "com.beem.project.beem.intent.action.DISCONNECT"; + + public static final String ACTION_SEND_MESSAGE = "com.beem.project.beem.intent.action.SEND_MESSAGE"; + + public static final String ACTION_SYNC = "com.beem.project.beem.intent.action.SYNC"; + + /*Broadcast Receiver's action */ + public static final String ACTION_CONNECTED = "com.beem.project.beem.intent.action.CONNECTED"; + + public static final String ACTION_DISCONNECTED = "com.beem.project.beem.intent.action.DISCONNECTED"; + + public static final String ACTION_MESSAGE_RECEIVED = "com.beem.project.beem.intent.action.MESSAGE_RECEIVED"; + + public static final String EXTRA_ACCOUNT = "com.beem.project.beem.intent.extra.ACCOUNT"; + + public static final String EXTRA_JID = "com.beem.project.beem.intent.extra.JID"; + + public static final String EXTRA_MESSAGE = "com.beem.project.beem.intent.extra.MESSAGE"; + +} + diff -r c2c6ee3d3c71 -r 07de7eb304b6 src/com/beem/project/beem/BeemService.java --- a/src/com/beem/project/beem/BeemService.java Mon Jun 13 15:00:23 2011 +0200 +++ b/src/com/beem/project/beem/BeemService.java Thu Jul 21 23:03:26 2011 +0200 @@ -43,13 +43,20 @@ */ 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; @@ -65,18 +72,33 @@ 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; import android.os.IBinder; +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; @@ -96,17 +118,19 @@ public static final int NOTIFICATION_STATUS_ID = 100; 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 NotificationManager mNotificationManager; - //TODO: MAP instead of LIST private Map mConnection = new HashMap(); private Map mBeemConnection = new HashMap(); - - //TODO: MAp maybe instead of LIST private Map mBind = new HashMap(); private boolean mOnOffReceiverIsRegistered; - + private Handler mHandler; + private Looper mServiceLooper; private BeemBroadcastReceiver mReceiver = new BeemBroadcastReceiver(); private BeemServicePreferenceListener mPreferenceListener = new BeemServicePreferenceListener(); private BeemServiceBroadcastReceiver mOnOffReceiver = new BeemServiceBroadcastReceiver(); @@ -117,6 +141,14 @@ public BeemService() { } + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + if (intent != null) { + handleIntent(intent); + } + return Service.START_STICKY; + } + /** * {@inheritDoc} */ @@ -125,12 +157,12 @@ Log.d(TAG, "ONBIND()"); String accountName = intent.getStringExtra("account_name"); Log.e(TAG, accountName); -// try { -// for (XmppConnectionAdapter connection : mConnection.values()) -// connection.connect(); -// } catch (RemoteException e) { -// Log.w(TAG, "Error while connecting", e); -// } + // try { + // for (XmppConnectionAdapter connection : mConnection.values()) + // connection.connect(); + // } catch (RemoteException e) { + // Log.w(TAG, "Error while connecting", e); + // } return (IBinder) mBind.get(accountName); } @@ -154,23 +186,29 @@ @Override public void onCreate() { super.onCreate(); - AccountManager am = AccountManager.get(BeemService.this); - Account allAccount[] = am.getAccountsByType("com.beem.project.com"); - for (Account account : allAccount) { - BeemConnection beemco = new BeemConnection(BeemService.this - .getSharedPreferences(account.name, 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.name, beemco); - XmppConnectionAdapter beemcoAdapter = new XmppConnectionAdapter(beemco.getConnectionConfiguration(), beemco - .getJid(), beemco.getPassword(), this); - mConnection.put(account.name, beemcoAdapter); - mBind.put(account.name, new XmppFacade(beemcoAdapter)); - Log.e(TAG, "Account configuration : " + account.toString() + " DONE"); - } + + HandlerThread thread = new HandlerThread("BeemServiceThread"); + thread.start(); + mServiceLooper = thread.getLooper(); + mHandler = new BeemServiceHandler(mServiceLooper); + + // AccountManager am = AccountManager.get(BeemService.this); + // Account allAccount[] = am.getAccountsByType("com.beem.project.com"); + // for (Account account : allAccount) { + // BeemConnection beemco = new BeemConnection(BeemService.this + // .getSharedPreferences(account.name, 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.name, beemco); + // XmppConnectionAdapter beemcoAdapter = new XmppConnectionAdapter(beemco.getConnectionConfiguration(), beemco + // .getJid(), beemco.getPassword(), this); + // mConnection.put(account.name, beemcoAdapter); + // mBind.put(account.name, new XmppFacade(beemcoAdapter)); + // Log.e(TAG, "Account configuration : " + account.toString() + " DONE"); + // } registerReceiver(mReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); configure(ProviderManager.getInstance()); @@ -204,14 +242,14 @@ public void onStart(Intent intent, int startId) { super.onStart(intent, startId); Log.d(TAG, "onStart"); -// try { -// for (XmppConnectionAdapter connection : mConnection.values()) -// connection.connectAsync(); -// } catch (RemoteException e) { -// e.printStackTrace(); -// } + // try { + // for (XmppConnectionAdapter connection : mConnection.values()) + // connection.connectAsync(); + // } catch (RemoteException e) { + // e.printStackTrace(); + // } } - + public XmppConnectionAdapter getConnection(String accountName) { return mConnection.get(accountName); } @@ -433,4 +471,388 @@ } } } + + private void handleIntent(Intent intent) { + Message msg = null; + String action = intent.getAction(); + if (BeemIntent.ACTION_CONNECT.equals(action)) { + msg = mHandler.obtainMessage(MESSAGE_CONNECT, 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)) { + msg = mHandler.obtainMessage(MESSAGE_SYNC, intent.getExtras()); + } else { + Log.w(TAG, "Unknown intent " + intent); + } + if (msg != null) + mHandler.sendMessage(msg); + } + + private class BeemServiceHandler extends Handler { + + public BeemServiceHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + Bundle b = (Bundle) msg.obj; + switch (msg.what) { + case MESSAGE_CONNECT: + handleConnect(b); + break; + case MESSAGE_SEND_MSG: + String account = b.getString(BeemIntent.EXTRA_ACCOUNT); + XmppConnectionAdapter con = mConnection.get(account); + if (con != null) { + con.handleMessage(msg); + } + break; + case MESSAGE_SYNC: + Account a = b.getParcelable(BeemIntent.EXTRA_ACCOUNT); + Bundle accountName = new Bundle(); + accountName.putString(BeemIntent.EXTRA_ACCOUNT, a.name); + handleConnect(accountName); + XmppConnectionAdapter co = mConnection.get(a.name); + if (co != null) { + manageRoster(co.getAdaptee().getRoster(), a); + } + break; + default: + Log.w(TAG, "Unknown message " + msg); + } + } + } + + private void handleConnect(Bundle b) { + Intent res = new Intent(BeemIntent.ACTION_DISCONNECTED); + String account = null; + if (b != null) + account = b.getString(BeemIntent.EXTRA_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)); + } + 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); + } + } catch (RemoteException e) { + Log.e(TAG, "Unable to connect " + account, e); + } + + // res.putExtra(BeemIntent.EXTRA_ACCOUNT, account); + // XmppConnectionAdapter con = mConnections.get(account); + // if (con != null && con.isAuthentificated()) + // return; + // if (con == null ) { + // ConnectionConfiguration config = initConnectionConfig(account); + // String login = StringUtils.parseName(account); + // String password = mSettings.getString(BeemApplication.ACCOUNT_PASSWORD_KEY, ""); + // + // if (mSettings.getBoolean(BeemApplication.FULL_JID_LOGIN_KEY, false) || + // "gmail.com".equals(mService) || "googlemail.com".equals(mService)) { + // login = account; + // } + // con = new XmppConnectionAdapter(config, login, password, this); + // try { + // Log.i(TAG, "Starting connection of " + account); + // if(con.connectSync()){ + // mConnections.put(account, con); + // mConnection = con; + // + // //TODO + // mBind = new XmppFacade(con); + // } else { + // Log.w(TAG, "Unable to connect " + account); + // } + // } 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(); + } + + /** + * 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); + } + + 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; + } + + /** + * 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; + } } diff -r c2c6ee3d3c71 -r 07de7eb304b6 src/com/beem/project/beem/account/SyncAdapterService.java --- a/src/com/beem/project/beem/account/SyncAdapterService.java Mon Jun 13 15:00:23 2011 +0200 +++ b/src/com/beem/project/beem/account/SyncAdapterService.java Thu Jul 21 23:03:26 2011 +0200 @@ -64,6 +64,7 @@ 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; @@ -75,6 +76,7 @@ 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; @@ -139,293 +141,38 @@ */ public static void performSync(Context context, final Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) throws OperationCanceledException { - mContentResolver = context.getContentResolver(); - Log.i(TAG, "performSync: " + account.toString()); - - //TODO: Get BeemService connectino support - //TODO: Get resource information - BeemConnection beemco = new BeemConnection(mContext.getSharedPreferences(account.name, MODE_PRIVATE), null); - //if (!BeemService.getIsLaunch()) - //beemco.setNoPresence(); - XMPPConnection con = new XMPPConnection(beemco.getConnectionConfiguration()); - Roster roster = null; - try { - con.connect(); - //SharedPreferences sp = context.getSharedPreferences(account.name, MODE_PRIVATE); - con.login(beemco.getLogin(), beemco.getPassword(), "beem sync adapter"); - roster = con.getRoster(); - } catch (XMPPException e) { - Log.e(TAG, "Error while connecting with syncAdapter", e); - } catch (IllegalStateException e) { - Log.e(TAG, "Not connected to server", e); - } - if (roster != null) - manageRoster(roster, account); - con.disconnect(); - } - - /** - * Method to execute content provider operation. - * @param ops - */ - private static void executeOperation(final ArrayList ops) { - try { - mContentResolver.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 - */ - private static void manageRoster(final Roster r, final 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); - } - - private static 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()); - } - } + Log.i(TAG, "performSync: " + account.toString()); + Intent intent = new Intent(BeemIntent.ACTION_SYNC ); + intent.putExtra(BeemIntent.EXTRA_ACCOUNT, account); +// IntentFilter filter = new IntentFilter(BeemIntent.ACTION_CONNECTED); +// filter.addAction(BeemIntent.ACTION_DISCONNECTED); +// registerReceiver(mReceiver, filter); + context.startService(intent); + +// mContentResolver = context.getContentResolver(); - /** - * 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 static 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 = mContentResolver.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 static 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 static 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; +// +// //TODO: Get BeemService connectino support +// //TODO: Get resource information +// BeemConnection beemco = new BeemConnection(mContext.getSharedPreferences(account.name, MODE_PRIVATE), null); +// //if (!BeemService.getIsLaunch()) +// //beemco.setNoPresence(); +// XMPPConnection con = new XMPPConnection(beemco.getConnectionConfiguration()); +// Roster roster = null; +// try { +// con.connect(); +// //SharedPreferences sp = context.getSharedPreferences(account.name, MODE_PRIVATE); +// con.login(beemco.getLogin(), beemco.getPassword(), "beem sync adapter"); +// roster = con.getRoster(); +// } catch (XMPPException e) { +// Log.e(TAG, "Error while connecting with syncAdapter", e); +// } catch (IllegalStateException e) { +// Log.e(TAG, "Not connected to server", e); +// } +// if (roster != null) +// manageRoster(roster, account); +// con.disconnect(); } - /** - * 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 static 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 static 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 static 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 static long getRawContactID(String account, String jid) { - long authorId = -1; - final Cursor c = mContentResolver.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 static long getRawGroupID(String account, String group) { - long authorId = -1; - final Cursor c = mContentResolver.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 c2c6ee3d3c71 -r 07de7eb304b6 src/com/beem/project/beem/service/XmppConnectionAdapter.java --- a/src/com/beem/project/beem/service/XmppConnectionAdapter.java Mon Jun 13 15:00:23 2011 +0200 +++ b/src/com/beem/project/beem/service/XmppConnectionAdapter.java Thu Jul 21 23:03:26 2011 +0200 @@ -40,7 +40,7 @@ Flavien Astraud, November 26, 2009 Head of the EIP Laboratory. -*/ + */ package com.beem.project.beem.service; import java.util.Iterator; @@ -65,6 +65,7 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.os.Bundle; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.util.Log; @@ -114,8 +115,7 @@ private AvatarManager mAvatarManager; private PepSubManager mPepManager; private SharedPreferences mPref; - private final RemoteCallbackList mRemoteConnListeners = - new RemoteCallbackList(); + private final RemoteCallbackList mRemoteConnListeners = new RemoteCallbackList(); private final SubscribePacketListener mSubscribePacketListener = new SubscribePacketListener(); private final ConnexionListenerAdapter mConListener = new ConnexionListenerAdapter(); @@ -195,8 +195,8 @@ try { //TODO NIKITA DOES SOME SHIT !!! Fix this monstruosity String str = mService.getResources().getString( - mService.getResources().getIdentifier( - e.getXMPPError().getCondition().replace("-", "_"), "string", "com.beem.project.beem")); + mService.getResources().getIdentifier(e.getXMPPError().getCondition().replace("-", "_"), + "string", "com.beem.project.beem")); mErrorMsg = str; } catch (NullPointerException e2) { if (!"".equals(e.getMessage())) @@ -328,7 +328,6 @@ /** * Get the AvatarManager of this connection. - * * @return the AvatarManager or null if there is not */ public AvatarManager getAvatarManager() { @@ -408,7 +407,6 @@ return mRoster; } - /** * Returns true if currently authenticated by successfully calling the login method. * @return true when successfully authenticated @@ -450,6 +448,15 @@ return mErrorMsg; } + public void handleMessage(android.os.Message msg) { + Bundle b = (Bundle) msg.obj; + switch (msg.what) { + + default: + Log.w(TAG, "Unknown message " + msg); + } + } + /** * Initialize the features provided by beem. */ @@ -645,11 +652,10 @@ R.string.AcceptContactRequest, from), System.currentTimeMillis()); notif.flags = Notification.FLAG_AUTO_CANCEL; Intent intent = new Intent(mService, Subscription.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - .putExtra("from", from); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).putExtra("from", from); notif.setLatestEventInfo(mService, from, mService .getString(R.string.AcceptContactRequestFrom, from), PendingIntent.getActivity(mService, 0, - intent, PendingIntent.FLAG_ONE_SHOT)); + intent, PendingIntent.FLAG_ONE_SHOT)); int id = packet.hashCode(); mService.sendNotification(id, notif); } @@ -697,8 +703,8 @@ notification.flags = Notification.FLAG_AUTO_CANCEL; Intent intent = new Intent(mService, Subscription.class); intent.setData(Contact.makeXmppUri(from)); - notification.setLatestEventInfo(mService, from, mService - .getString(R.string.AcceptContactRequestFrom, from), PendingIntent.getActivity(mService, 0, + notification.setLatestEventInfo(mService, from, + mService.getString(R.string.AcceptContactRequestFrom, from), PendingIntent.getActivity(mService, 0, intent, PendingIntent.FLAG_ONE_SHOT)); int id = p.hashCode(); mService.sendNotification(id, notification); diff -r c2c6ee3d3c71 -r 07de7eb304b6 src/com/beem/project/beem/smack/avatar/AvatarManager.java --- a/src/com/beem/project/beem/smack/avatar/AvatarManager.java Mon Jun 13 15:00:23 2011 +0200 +++ b/src/com/beem/project/beem/smack/avatar/AvatarManager.java Thu Jul 21 23:03:26 2011 +0200 @@ -43,20 +43,21 @@ */ package com.beem.project.beem.smack.avatar; -import com.beem.project.beem.smack.avatar.AvatarMetadataExtension.Info; -import com.beem.project.beem.smack.pep.PEPListener; -import com.beem.project.beem.smack.pep.PepSubManager; - import java.io.IOException; - +import java.util.LinkedList; import java.util.List; -import java.util.LinkedList; import org.jivesoftware.smack.Connection; import org.jivesoftware.smack.packet.PacketExtension; import org.jivesoftware.smackx.pubsub.Item; import org.jivesoftware.smackx.pubsub.PayloadItem; +import android.util.Log; + +import com.beem.project.beem.smack.avatar.AvatarMetadataExtension.Info; +import com.beem.project.beem.smack.pep.PEPListener; +import com.beem.project.beem.smack.pep.PepSubManager; + /** * This class deals with the avatar data. * It can be configured to auto retrieve the avatar and put it in cache. diff -r c2c6ee3d3c71 -r 07de7eb304b6 src/com/beem/project/beem/ui/Login.java --- a/src/com/beem/project/beem/ui/Login.java Mon Jun 13 15:00:23 2011 +0200 +++ b/src/com/beem/project/beem/ui/Login.java Thu Jul 21 23:03:26 2011 +0200 @@ -142,7 +142,7 @@ @Override protected void onDestroy() { super.onDestroy(); - unbindService(mServConn); + //unbindService(mServConn); } @Override