# HG changeset patch # User "Vincent Veronis" # Date 1318611427 -7200 # Node ID c067ee9a604c19090b9698b4bd911e5321780544 # Parent ac9461be2bd70485117a16f9e106dc68438f6ceb Lot of modification. I dont remember .... i know nc ! diff -r ac9461be2bd7 -r c067ee9a604c AndroidManifest.xml --- a/AndroidManifest.xml Mon Aug 22 22:43:19 2011 +0200 +++ b/AndroidManifest.xml Fri Oct 14 18:57:07 2011 +0200 @@ -162,8 +162,7 @@ + android:authorities="com.beem.project.beem.providers.messageprovider" /> + android:minSdkVersion="7" + android:targetSdkVersion="7" /> mConnection = new HashMap(); - private Map mBeemConnection = new HashMap(); - 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(); - - /** - * Constructor. - */ - public BeemService() { - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - if (intent != null) { - handleIntent(intent); - } - return Service.START_STICKY; - } - - /** - * {@inheritDoc} - */ - @Override - public IBinder onBind(Intent intent) { - Log.d(TAG, "ONBIND()"); - return null;//(IBinder) mBind.get(accountName); - } - - @Override - public boolean onUnbind(Intent intent) { - Log.d(TAG, "ONUNBIND()"); - boolean isConnected = true; - for (XmppConnectionAdapter connection : mConnection.values()) { - if (!connection.getAdaptee().isConnected()) - isConnected = false; - } - if (!isConnected) { - this.stopSelf(); - } - return true; - } - - /** - * {@inheritDoc} - */ - @Override - public void onCreate() { - super.onCreate(); - - HandlerThread thread = new HandlerThread("BeemServiceThread"); - thread.start(); - mServiceLooper = thread.getLooper(); - mHandler = new BeemServiceHandler(mServiceLooper); + /** The id to use for status notification. */ + public static final int NOTIFICATION_STATUS_ID = 100; - // 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()); - mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); - Roster.setDefaultSubscriptionMode(SubscriptionMode.manual); - Log.d(TAG, "ONCREATE"); - } - - /** - * {@inheritDoc} - */ - @Override - public void onDestroy() { - super.onDestroy(); - mNotificationManager.cancelAll(); - unregisterReceiver(mReceiver); - - if (mOnOffReceiverIsRegistered) - unregisterReceiver(mOnOffReceiver); - for (XmppConnectionAdapter connection : mConnection.values()) { - if (connection.isAuthentificated() && BeemConnectivity.isConnected(this)) - connection.disconnect(); - } - Log.d(TAG, "ONDESTROY"); - } - - /** - * {@inheritDoc} - */ - @Override - 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(); - // } - } - - public XmppConnectionAdapter getConnection(String accountName) { - return mConnection.get(accountName); - } - - /** - * Show a notification using the preference of the user. - * @param id the id of the notification. - * @param notif the notification to show - */ - public void sendNotification(int id, Notification notif) { - // if (mSettings.getBoolean(BeemApplication.NOTIFICATION_VIBRATE_KEY, true)) - // notif.defaults |= Notification.DEFAULT_VIBRATE; - // notif.defaults |= Notification.DEFAULT_LIGHTS; - // String ringtoneStr = mSettings.getString(BeemApplication.NOTIFICATION_SOUND_KEY, ""); - // notif.sound = Uri.parse(ringtoneStr); - // mNotificationManager.notify(id, notif); - } - - /** - * Delete a notification. - * @param id the id of the notification - */ - public void deleteNotification(int id) { - mNotificationManager.cancel(id); - } + private static final String TAG = "BeemService"; + private static final int MESSAGE_CONNECT = 0x1; + private static final int MESSAGE_DISCONNECT = 0x2; + private static final int MESSAGE_SEND_MSG = 0x3; + private static final int MESSAGE_SYNC = 0x4; - /** - * Reset the status to online after a disconnect. - */ - public void resetStatus() { - for (BeemConnection beemco : mBeemConnection.values()) { - Editor edit = beemco.getSettings().edit(); - edit.putInt(BeemApplication.STATUS_KEY, 1); - edit.commit(); - } - - } - - /** - * Initialize Jingle from an XmppConnectionAdapter. - * @param adaptee XmppConnection used for jingle. - */ - public void initJingle(XMPPConnection adaptee) { - } - - /** - * Return a bind to an XmppFacade instance. - * @return IXmppFacade a bind to an XmppFacade instance - */ - public IXmppFacade getBind() { - //TODO: Prendre le bon mbind dans le tableau - return mBind.get(0); - } - - /** - * Get the preference of the service. - * @return the preference - */ - public SharedPreferences getServicePreference(String accountName) { - return mBeemConnection.get(accountName).getSettings(); - } - - /** - * Get the notification manager system service. - * @return the notification manager service. - */ - public NotificationManager getNotificationManager() { - return mNotificationManager; - } - - /** - * A sort of patch from this thread: http://www.igniterealtime.org/community/thread/31118. Avoid ClassCastException - * by bypassing the classloading shit of Smack. - * @param pm The ProviderManager. - */ - private void configure(ProviderManager pm) { - Log.d(TAG, "configure"); - // Service Discovery # Items - pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider()); - // Service Discovery # Info - pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider()); - - // Privacy - //pm.addIQProvider("query", "jabber:iq:privacy", new PrivacyProvider()); - // Delayed Delivery only the new version - pm.addExtensionProvider("delay", "urn:xmpp:delay", new DelayInfoProvider()); - - // Service Discovery # Items - pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider()); - // Service Discovery # Info - pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider()); - - // Chat State - ChatStateExtension.Provider chatState = new ChatStateExtension.Provider(); - pm.addExtensionProvider("active", "http://jabber.org/protocol/chatstates", chatState); - pm.addExtensionProvider("composing", "http://jabber.org/protocol/chatstates", chatState); - pm.addExtensionProvider("paused", "http://jabber.org/protocol/chatstates", chatState); - pm.addExtensionProvider("inactive", "http://jabber.org/protocol/chatstates", chatState); - pm.addExtensionProvider("gone", "http://jabber.org/protocol/chatstates", chatState); - // capabilities - pm.addExtensionProvider("c", "http://jabber.org/protocol/caps", new CapsProvider()); - //Pubsub - pm.addIQProvider("pubsub", "http://jabber.org/protocol/pubsub", new PubSubProvider()); - pm.addExtensionProvider("items", "http://jabber.org/protocol/pubsub", new ItemsProvider()); - pm.addExtensionProvider("items", "http://jabber.org/protocol/pubsub", new ItemsProvider()); - pm.addExtensionProvider("item", "http://jabber.org/protocol/pubsub", new ItemProvider()); + private NotificationManager mNotificationManager; + private Map mConnection = new HashMap(); + private Map mBeemConnection = new HashMap(); + private Map mBind = new HashMap(); - pm.addExtensionProvider("items", "http://jabber.org/protocol/pubsub#event", new ItemsProvider()); - pm.addExtensionProvider("item", "http://jabber.org/protocol/pubsub#event", new ItemProvider()); - pm.addExtensionProvider("event", "http://jabber.org/protocol/pubsub#event", new EventProvider()); - //TODO rajouter les manquants pour du full pubsub - - //PEP avatar - pm.addExtensionProvider("metadata", "urn:xmpp:avatar:metadata", new AvatarMetadataProvider()); - pm.addExtensionProvider("data", "urn:xmpp:avatar:data", new AvatarProvider()); - - // PEPProvider pep = new PEPProvider(); - // AvatarMetadataProvider avaMeta = new AvatarMetadataProvider(); - // pep.registerPEPParserExtension("urn:xmpp:avatar:metadata", avaMeta); - // pm.addExtensionProvider("event", "http://jabber.org/protocol/pubsub#event", pep); - - /* - * // Private Data Storage pm.addIQProvider("query", "jabber:iq:private", new - * PrivateDataManager.PrivateDataIQProvider()); // Time try { pm.addIQProvider("query", "jabber:iq:time", - * Class.forName("org.jivesoftware.smackx.packet.Time")); } catch (ClassNotFoundException e) { - * Log.w("TestClient", "Can't load class for org.jivesoftware.smackx.packet.Time"); } // Roster Exchange - * pm.addExtensionProvider("x", "jabber:x:roster", new RosterExchangeProvider()); // Message Events - * pm.addExtensionProvider("x", "jabber:x:event", new MessageEventProvider()); // XHTML - * pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im", new XHTMLExtensionProvider()); // - * Group Chat Invitations pm.addExtensionProvider("x", "jabber:x:conference", new - * GroupChatInvitation.Provider()); // Data Forms pm.addExtensionProvider("x", "jabber:x:data", new - * DataFormProvider()); // MUC User pm.addExtensionProvider("x", "http://jabber.org/protocol/muc#user", new - * MUCUserProvider()); // MUC Admin pm.addIQProvider("query", "http://jabber.org/protocol/muc#admin", new - * MUCAdminProvider()); // MUC Owner pm.addIQProvider("query", "http://jabber.org/protocol/muc#owner", new - * MUCOwnerProvider()); // Version try { pm.addIQProvider("query", "jabber:iq:version", - * Class.forName("org.jivesoftware.smackx.packet.Version")); } catch (ClassNotFoundException e) { // Not sure - * what's happening here. Log.w("TestClient", "Can't load class for org.jivesoftware.smackx.packet.Version"); } - * // VCard pm.addIQProvider("vCard", "vcard-temp", new VCardProvider()); // Offline Message Requests - * pm.addIQProvider("offline", "http://jabber.org/protocol/offline", new OfflineMessageRequest.Provider()); // - * Offline Message Indicator pm.addExtensionProvider("offline", "http://jabber.org/protocol/offline", new - * OfflineMessageInfo.Provider()); // Last Activity pm.addIQProvider("query", "jabber:iq:last", new - * LastActivity.Provider()); // User Search pm.addIQProvider("query", "jabber:iq:search", new - * UserSearch.Provider()); // SharedGroupsInfo pm.addIQProvider("sharedgroup", - * "http://www.jivesoftware.org/protocol/sharedgroup", new SharedGroupsInfo.Provider()); // JEP-33: Extended - * Stanza Addressing pm.addExtensionProvider("addresses", "http://jabber.org/protocol/address", new - * MultipleAddressesProvider()); // FileTransfer pm.addIQProvider("si", "http://jabber.org/protocol/si", new - * StreamInitiationProvider()); pm.addIQProvider("query", "http://jabber.org/protocol/bytestreams", new - * BytestreamsProvider()); pm.addIQProvider("open", "http://jabber.org/protocol/ibb", new IBBProviders.Open()); - * pm.addIQProvider("close", "http://jabber.org/protocol/ibb", new IBBProviders.Close()); - * pm.addExtensionProvider("data", "http://jabber.org/protocol/ibb", new IBBProviders.Data()); - * pm.addIQProvider("command", COMMAND_NAMESPACE, new AdHocCommandDataProvider()); - * pm.addExtensionProvider("malformed-action", COMMAND_NAMESPACE, new - * AdHocCommandDataProvider.MalformedActionError()); pm.addExtensionProvider("bad-locale", COMMAND_NAMESPACE, - * new AdHocCommandDataProvider.BadLocaleError()); pm.addExtensionProvider("bad-payload", COMMAND_NAMESPACE, new - * AdHocCommandDataProvider.BadPayloadError()); pm.addExtensionProvider("bad-sessionid", COMMAND_NAMESPACE, new - * AdHocCommandDataProvider.BadSessionIDError()); pm.addExtensionProvider("session-expired", COMMAND_NAMESPACE, - * new AdHocCommandDataProvider.SessionExpiredError()); - */ - } - - /** - * Listen on preference changes. - */ - public class BeemServicePreferenceListener implements SharedPreferences.OnSharedPreferenceChangeListener { - - /** - * ctor. - */ - public BeemServicePreferenceListener() { - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if ("settings_away_chk".equals(key)) { - if (sharedPreferences.getBoolean("settings_away_chk", false)) { - mOnOffReceiverIsRegistered = true; - registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF)); - registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON)); - } else { - mOnOffReceiverIsRegistered = false; - unregisterReceiver(mOnOffReceiver); - } - } - } - } - - /** - * Listen on some Intent broadcast, ScreenOn and ScreenOff. - */ - private class BeemServiceBroadcastReceiver extends BroadcastReceiver { - - private String mOldStatus; - private int mOldMode; + private boolean mOnOffReceiverIsRegistered; + private Handler mHandler; + private Looper mServiceLooper; + private BeemBroadcastReceiver mReceiver = new BeemBroadcastReceiver(); + private BeemServicePreferenceListener mPreferenceListener = new BeemServicePreferenceListener(); + private BeemServiceBroadcastReceiver mOnOffReceiver = new BeemServiceBroadcastReceiver(); /** * Constructor. */ - public BeemServiceBroadcastReceiver() { + public BeemService() { } @Override - public void onReceive(final Context context, final Intent intent) { - String intentAction = intent.getAction(); - if (intentAction.equals(Intent.ACTION_SCREEN_OFF)) { - for (Map.Entry item : mConnection.entrySet()) { - XmppConnectionAdapter connection = item.getValue(); - mOldMode = connection.getPreviousMode(); - mOldStatus = connection.getPreviousStatus(); - if (connection.isAuthentificated()) - connection.changeStatus(Status.CONTACT_STATUS_AWAY, mBeemConnection.get(item.getKey()) - .getSettings().getString("settings_away_message", "Away")); + public int onStartCommand(Intent intent, int flags, int startId) { + if (intent != null) { + handleIntent(intent); } - } else if (intentAction.equals(Intent.ACTION_SCREEN_ON)) { - for (XmppConnectionAdapter connection : mConnection.values()) { - if (connection.isAuthentificated()) - connection.changeStatus(mOldMode, mOldStatus); - } - } + return Service.START_STICKY; } - } - 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_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)) { - 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); + /** + * {@inheritDoc} + */ + @Override + public IBinder onBind(Intent intent) { + Log.d(TAG, "ONBIND()"); + return null;//(IBinder) mBind.get(accountName); } @Override - public void handleMessage(Message msg) { - Bundle b = (Bundle) msg.obj; - switch (msg.what) { - 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); - 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); - //TODO: Connect with option to not show status - handleConnect(accountName); - XmppConnectionAdapter co = mConnection.get(a.name); - if (co != null) { - BeemSync sync = new BeemSync(getBaseContext()); - if (co.getAdaptee() != null) - sync.manageRoster(co.getAdaptee().getRoster(), a); - } - break; - default: - Log.w(TAG, "Unknown message " + msg); - } + public boolean onUnbind(Intent intent) { + Log.d(TAG, "ONUNBIND()"); + boolean isConnected = true; + for (XmppConnectionAdapter connection : mConnection.values()) { + if (!connection.getAdaptee().isConnected()) + isConnected = false; + } + if (!isConnected) { + this.stopSelf(); + } + return true; } - } + + /** + * {@inheritDoc} + */ + @Override + public void onCreate() { + super.onCreate(); - private void handleConnect(Bundle b) { - Intent res = new Intent(BeemIntent.ACTION_DISCONNECTED); - res.putExtra(BeemIntent.EXTRA_MESSAGE, R.string.contact_status_msg_offline); + HandlerThread thread = new HandlerThread("BeemServiceThread"); + thread.start(); + mServiceLooper = thread.getLooper(); + mHandler = new BeemServiceHandler(mServiceLooper); + registerReceiver(mReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); + configure(ProviderManager.getInstance()); + mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + Roster.setDefaultSubscriptionMode(SubscriptionMode.manual); + Log.d(TAG, "ONCREATE"); + } + + /** + * {@inheritDoc} + */ + @Override + public void onDestroy() { + super.onDestroy(); + mNotificationManager.cancelAll(); + unregisterReceiver(mReceiver); - String account = null; - if (b != null) { - account = b.getString(BeemIntent.EXTRA_ACCOUNT); - res.putExtra(BeemIntent.EXTRA_ACCOUNT, account); + if (mOnOffReceiverIsRegistered) + unregisterReceiver(mOnOffReceiver); + for (XmppConnectionAdapter connection : mConnection.values()) { + if (connection.isAuthentificated() && BeemConnectivity.isConnected(this)) + connection.disconnect(); + } + Log.d(TAG, "ONDESTROY"); + } + + public XmppConnectionAdapter getConnection(String accountName) { + return mConnection.get(accountName); } - if (mConnection.containsKey(account)) { - res.setAction(BeemIntent.ACTION_CONNECTED); - } else { - 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); + + /** + * Show a notification using the preference of the user. + * @param id the id of the notification. + * @param notif the notification to show + */ + public void sendNotification(int id, Notification notif) { + // if (mSettings.getBoolean(BeemApplication.NOTIFICATION_VIBRATE_KEY, true)) + // notif.defaults |= Notification.DEFAULT_VIBRATE; + // notif.defaults |= Notification.DEFAULT_LIGHTS; + // String ringtoneStr = mSettings.getString(BeemApplication.NOTIFICATION_SOUND_KEY, ""); + // notif.sound = Uri.parse(ringtoneStr); + // mNotificationManager.notify(id, notif); + } - 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); - res.putExtra(BeemIntent.EXTRA_MESSAGE, beemcoAdapter.getErrorMessage()); - } - } catch (RemoteException e) { - res.putExtra(BeemIntent.EXTRA_MESSAGE, beemcoAdapter.getErrorMessage()); - Log.e(TAG, "Unable to connect " + account, e); + /** + * Delete a notification. + * @param id the id of the notification + */ + public void deleteNotification(int id) { + mNotificationManager.cancel(id); + } + + /** + * Reset the status to online after a disconnect. + */ + public void resetStatus() { + for (BeemConnection beemco : mBeemConnection.values()) { + Editor edit = beemco.getSettings().edit(); + edit.putInt(BeemApplication.STATUS_KEY, 1); + edit.commit(); } - } + } + + /** + * Initialize Jingle from an XmppConnectionAdapter. + * @param adaptee XmppConnection used for jingle. + */ + public void initJingle(XMPPConnection adaptee) { + } + + /** + * Return a bind to an XmppFacade instance. + * @return IXmppFacade a bind to an XmppFacade instance + */ + public IXmppFacade getBind() { + //TODO: Prendre le bon mbind dans le tableau + return mBind.get(0); + } + + /** + * Get the preference of the service. + * @return the preference + */ + public SharedPreferences getServicePreference(String accountName) { + Log.e(TAG, "Account name:" + accountName); + return mBeemConnection.get(accountName).getSettings(); + } + + /** + * Get the notification manager system service. + * @return the notification manager service. + */ + public NotificationManager getNotificationManager() { + return mNotificationManager; } - sendBroadcast(res); - } + + /** + * A sort of patch from this thread: http://www.igniterealtime.org/community/thread/31118. Avoid ClassCastException + * by bypassing the classloading shit of Smack. + * @param pm The ProviderManager. + */ + private void configure(ProviderManager pm) { + Log.d(TAG, "configure"); + // Service Discovery # Items + pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider()); + // Service Discovery # Info + pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider()); + + // Privacy + //pm.addIQProvider("query", "jabber:iq:privacy", new PrivacyProvider()); + // Delayed Delivery only the new version + pm.addExtensionProvider("delay", "urn:xmpp:delay", new DelayInfoProvider()); + + // Service Discovery # Items + pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider()); + // Service Discovery # Info + pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider()); + + // Chat State + ChatStateExtension.Provider chatState = new ChatStateExtension.Provider(); + pm.addExtensionProvider("active", "http://jabber.org/protocol/chatstates", chatState); + pm.addExtensionProvider("composing", "http://jabber.org/protocol/chatstates", chatState); + pm.addExtensionProvider("paused", "http://jabber.org/protocol/chatstates", chatState); + pm.addExtensionProvider("inactive", "http://jabber.org/protocol/chatstates", chatState); + pm.addExtensionProvider("gone", "http://jabber.org/protocol/chatstates", chatState); + // capabilities + pm.addExtensionProvider("c", "http://jabber.org/protocol/caps", new CapsProvider()); + //Pubsub + pm.addIQProvider("pubsub", "http://jabber.org/protocol/pubsub", new PubSubProvider()); + pm.addExtensionProvider("items", "http://jabber.org/protocol/pubsub", new ItemsProvider()); + pm.addExtensionProvider("items", "http://jabber.org/protocol/pubsub", new ItemsProvider()); + pm.addExtensionProvider("item", "http://jabber.org/protocol/pubsub", new ItemProvider()); + + pm.addExtensionProvider("items", "http://jabber.org/protocol/pubsub#event", new ItemsProvider()); + pm.addExtensionProvider("item", "http://jabber.org/protocol/pubsub#event", new ItemProvider()); + pm.addExtensionProvider("event", "http://jabber.org/protocol/pubsub#event", new EventProvider()); + //TODO rajouter les manquants pour du full pubsub + + //PEP avatar + pm.addExtensionProvider("metadata", "urn:xmpp:avatar:metadata", new AvatarMetadataProvider()); + pm.addExtensionProvider("data", "urn:xmpp:avatar:data", new AvatarProvider()); + + // PEPProvider pep = new PEPProvider(); + // AvatarMetadataProvider avaMeta = new AvatarMetadataProvider(); + // pep.registerPEPParserExtension("urn:xmpp:avatar:metadata", avaMeta); + // pm.addExtensionProvider("event", "http://jabber.org/protocol/pubsub#event", pep); + + /* + * // Private Data Storage pm.addIQProvider("query", "jabber:iq:private", new + * PrivateDataManager.PrivateDataIQProvider()); // Time try { pm.addIQProvider("query", "jabber:iq:time", + * Class.forName("org.jivesoftware.smackx.packet.Time")); } catch (ClassNotFoundException e) { + * Log.w("TestClient", "Can't load class for org.jivesoftware.smackx.packet.Time"); } // Roster Exchange + * pm.addExtensionProvider("x", "jabber:x:roster", new RosterExchangeProvider()); // Message Events + * pm.addExtensionProvider("x", "jabber:x:event", new MessageEventProvider()); // XHTML + * pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im", new XHTMLExtensionProvider()); // + * Group Chat Invitations pm.addExtensionProvider("x", "jabber:x:conference", new + * GroupChatInvitation.Provider()); // Data Forms pm.addExtensionProvider("x", "jabber:x:data", new + * DataFormProvider()); // MUC User pm.addExtensionProvider("x", "http://jabber.org/protocol/muc#user", new + * MUCUserProvider()); // MUC Admin pm.addIQProvider("query", "http://jabber.org/protocol/muc#admin", new + * MUCAdminProvider()); // MUC Owner pm.addIQProvider("query", "http://jabber.org/protocol/muc#owner", new + * MUCOwnerProvider()); // Version try { pm.addIQProvider("query", "jabber:iq:version", + * Class.forName("org.jivesoftware.smackx.packet.Version")); } catch (ClassNotFoundException e) { // Not sure + * what's happening here. Log.w("TestClient", "Can't load class for org.jivesoftware.smackx.packet.Version"); } + * // VCard pm.addIQProvider("vCard", "vcard-temp", new VCardProvider()); // Offline Message Requests + * pm.addIQProvider("offline", "http://jabber.org/protocol/offline", new OfflineMessageRequest.Provider()); // + * Offline Message Indicator pm.addExtensionProvider("offline", "http://jabber.org/protocol/offline", new + * OfflineMessageInfo.Provider()); // Last Activity pm.addIQProvider("query", "jabber:iq:last", new + * LastActivity.Provider()); // User Search pm.addIQProvider("query", "jabber:iq:search", new + * UserSearch.Provider()); // SharedGroupsInfo pm.addIQProvider("sharedgroup", + * "http://www.jivesoftware.org/protocol/sharedgroup", new SharedGroupsInfo.Provider()); // JEP-33: Extended + * Stanza Addressing pm.addExtensionProvider("addresses", "http://jabber.org/protocol/address", new + * MultipleAddressesProvider()); // FileTransfer pm.addIQProvider("si", "http://jabber.org/protocol/si", new + * StreamInitiationProvider()); pm.addIQProvider("query", "http://jabber.org/protocol/bytestreams", new + * BytestreamsProvider()); pm.addIQProvider("open", "http://jabber.org/protocol/ibb", new IBBProviders.Open()); + * pm.addIQProvider("close", "http://jabber.org/protocol/ibb", new IBBProviders.Close()); + * pm.addExtensionProvider("data", "http://jabber.org/protocol/ibb", new IBBProviders.Data()); + * pm.addIQProvider("command", COMMAND_NAMESPACE, new AdHocCommandDataProvider()); + * pm.addExtensionProvider("malformed-action", COMMAND_NAMESPACE, new + * AdHocCommandDataProvider.MalformedActionError()); pm.addExtensionProvider("bad-locale", COMMAND_NAMESPACE, + * new AdHocCommandDataProvider.BadLocaleError()); pm.addExtensionProvider("bad-payload", COMMAND_NAMESPACE, new + * AdHocCommandDataProvider.BadPayloadError()); pm.addExtensionProvider("bad-sessionid", COMMAND_NAMESPACE, new + * AdHocCommandDataProvider.BadSessionIDError()); pm.addExtensionProvider("session-expired", COMMAND_NAMESPACE, + * new AdHocCommandDataProvider.SessionExpiredError()); + */ + } + + /** + * Listen on preference changes. + */ + public class BeemServicePreferenceListener implements SharedPreferences.OnSharedPreferenceChangeListener { + + /** + * ctor. + */ + public BeemServicePreferenceListener() { + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if ("settings_away_chk".equals(key)) { + if (sharedPreferences.getBoolean("settings_away_chk", false)) { + mOnOffReceiverIsRegistered = true; + registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF)); + registerReceiver(mOnOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON)); + } else { + mOnOffReceiverIsRegistered = false; + unregisterReceiver(mOnOffReceiver); + } + } + } + } - private void handleDisconnect(Bundle b) { - Intent res = new Intent(BeemIntent.ACTION_DISCONNECTED); - String account = b.getString(BeemIntent.EXTRA_ACCOUNT); - mConnection.remove(account); - sendBroadcast(res); - } + /** + * Listen on some Intent broadcast, ScreenOn and ScreenOff. + */ + private class BeemServiceBroadcastReceiver extends BroadcastReceiver { + + private String mOldStatus; + private int mOldMode; + + /** + * Constructor. + */ + public BeemServiceBroadcastReceiver() { + } + + @Override + public void onReceive(final Context context, final Intent intent) { + String intentAction = intent.getAction(); + if (intentAction.equals(Intent.ACTION_SCREEN_OFF)) { + for (Map.Entry item : mConnection.entrySet()) { + XmppConnectionAdapter connection = item.getValue(); + mOldMode = connection.getPreviousMode(); + mOldStatus = connection.getPreviousStatus(); + if (connection.isAuthentificated()) + connection.changeStatus(Status.CONTACT_STATUS_AWAY, mBeemConnection.get(item.getKey()) + .getSettings().getString("settings_away_message", "Away")); + } + } else if (intentAction.equals(Intent.ACTION_SCREEN_ON)) { + for (XmppConnectionAdapter connection : mConnection.values()) { + if (connection.isAuthentificated()) + connection.changeStatus(mOldMode, mOldStatus); + } + } + } + } + + 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_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)) { + 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_DISCONNECT: + handleDisconnect(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); + //TODO: Connect with option to not show status + handleConnect(accountName); + XmppConnectionAdapter co = mConnection.get(a.name); + if (co != null) { + BeemSync sync = new BeemSync(getBaseContext()); + if (co.getAdaptee() != null) + sync.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); + res.putExtra(BeemIntent.EXTRA_MESSAGE, R.string.contact_status_msg_offline); + + String account = null; + if (b != null) { + account = b.getString(BeemIntent.EXTRA_ACCOUNT); + res.putExtra(BeemIntent.EXTRA_ACCOUNT, account); + } + if (mConnection.containsKey(account)) { + res.setAction(BeemIntent.ACTION_CONNECTED); + } else { + 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); + res.putExtra(BeemIntent.EXTRA_MESSAGE, beemcoAdapter.getErrorMessage()); + } + } catch (RemoteException e) { + res.putExtra(BeemIntent.EXTRA_MESSAGE, beemcoAdapter.getErrorMessage()); + Log.e(TAG, "Unable to connect " + account, e); + } + + } + } + sendBroadcast(res); + } + + 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 ac9461be2bd7 -r c067ee9a604c src/com/beem/project/beem/BeemSync.java --- a/src/com/beem/project/beem/BeemSync.java Mon Aug 22 22:43:19 2011 +0200 +++ b/src/com/beem/project/beem/BeemSync.java Fri Oct 14 18:57:07 2011 +0200 @@ -58,288 +58,288 @@ */ public class BeemSync { - private static final String TAG = "BeemSync"; - private static final int NB_DB_OPERATION = 50; + private static final String TAG = "BeemSync"; + private static final int NB_DB_OPERATION = 50; - private Context mContext; + private Context mContext; - /** - * Constructor. - * @param c the context parameter. - */ - public BeemSync(Context c) { - mContext = c; - } + /** + * 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); + /** + * 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(); } - 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; + /** + * 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); } - 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()); + 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()); + /** + * 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; } - 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) }); + /** + * 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; } - 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); + /** + * 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; } - 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); + /** + * 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; } - //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 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()); - } + /** + * 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(); + /** + * 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; } - 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(); + /** + * 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; } - return authorId; - } } diff -r ac9461be2bd7 -r c067ee9a604c src/com/beem/project/beem/providers/MessageProvider.java --- a/src/com/beem/project/beem/providers/MessageProvider.java Mon Aug 22 22:43:19 2011 +0200 +++ b/src/com/beem/project/beem/providers/MessageProvider.java Fri Oct 14 18:57:07 2011 +0200 @@ -44,6 +44,8 @@ package com.beem.project.beem.providers; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.HashMap; import android.content.ContentProvider; @@ -54,193 +56,203 @@ import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.util.Log; +import com.beem.project.beem.service.Message; + /** * Provider to store messages send/receive. * @author marseille */ public class MessageProvider extends ContentProvider { - private static final String TAG = "MessageProvider"; - private static final String DATABASE_NAME = "messages.db"; - private static final int DATABASE_VERSION = 1; - private static final int MESSAGES = 1; - private static final String MESSAGES_TABLE_NAME = "messages"; - private static final UriMatcher sUriMatcher; + private static final String TAG = "MessageProvider"; + private static final String DATABASE_NAME = "messages.db"; + private static final int DATABASE_VERSION = 1; + private static final int MESSAGES = 1; + private static final String MESSAGES_TABLE_NAME = "messages"; + private static final UriMatcher sUriMatcher; - public static final String AUTHORITY = "com.beem.project.beem.providers.messageprovider"; + public static final String AUTHORITY = "com.beem.project.beem.providers.messageprovider"; - private static HashMap messagesProjectionMap; - private DatabaseHelper dbHelper = null; + private static HashMap messagesProjectionMap; + private DatabaseHelper mDbHelper; + private Context mContext; - /** - * Constructor. - */ - public MessageProvider() { - Log.e(TAG, "MessageProvider"); - if (dbHelper == null) - dbHelper = new DatabaseHelper(getContext()); - Log.e(TAG, "MessageProvider" + dbHelper.toString()); - } + /** + * Constructor. + */ + public MessageProvider() { + Log.i(TAG, "Constructeur MessageProvider"); + } - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - SQLiteDatabase db = dbHelper.getWritableDatabase(); - int count; - switch (sUriMatcher.match(uri)) { - case MESSAGES: - count = db.delete(MESSAGES_TABLE_NAME, selection, selectionArgs); - break; + @Override + public boolean onCreate() { + Log.i(TAG, "On Create MessageProvider"); + mDbHelper = new DatabaseHelper(getContext()); + return true; - default: - throw new IllegalArgumentException("Unknown URI " + uri); } - getContext().getContentResolver().notifyChange(uri, null); - return count; - } - @Override - public String getType(Uri uri) { - switch (sUriMatcher.match(uri)) { - case MESSAGES: - return Messages.CONTENT_TYPE; - default: - throw new IllegalArgumentException("Unknown URI " + uri); - } - } + @Override + public Uri insert(Uri uri, ContentValues initialValues) { + Log.i(TAG, "insert1"); + if (sUriMatcher.match(uri) != MESSAGES) { + throw new IllegalArgumentException("Unknown URI " + uri); + } + Log.i(TAG, "insert2"); + ContentValues values; + if (initialValues != null) + values = new ContentValues(initialValues); + else + values = new ContentValues(); - @Override - public Uri insert(Uri uri, ContentValues initialValues) { - Log.e(TAG, "INSERT"); - if (sUriMatcher.match(uri) != MESSAGES) { - throw new IllegalArgumentException("Unknown URI " + uri); - } - Log.e(TAG, "INSERT"); - ContentValues values; - if (initialValues != null) { - values = new ContentValues(initialValues); - } else { - values = new ContentValues(); - } - Log.e(TAG, "INSERT"); - SQLiteDatabase db = dbHelper.getWritableDatabase(); - long rowId = db.insert(MESSAGES_TABLE_NAME, Messages.BODY, values); - if (rowId > 0) { - Uri messageUri = ContentUris.withAppendedId(Messages.CONTENT_URI, rowId); - getContext().getContentResolver().notifyChange(messageUri, null); - return messageUri; - } - Log.e(TAG, "INSERT"); - throw new SQLException("Failed to insert row into " + uri); - } + Log.i(TAG, "insert3"); + if (mDbHelper == null) + Log.e("mDbHelper", "NULL"); + SQLiteDatabase db = null; + try { + db = mDbHelper.getWritableDatabase(); + } catch (SQLiteException e) { + Log.e("SQLITEEXCEPTION", "OOOO", e); + } + Log.i(TAG, "insert3.5"); + if (db == null) + Log.e("db", "NULL"); + long rowId = db.insert(MESSAGES_TABLE_NAME, Messages.BODY, values); + Log.i(TAG, "insert4"); + if (rowId == -1) + throw new SQLException("Failed to insert row into " + uri); + Uri messageUri = ContentUris.withAppendedId(Messages.CONTENT_URI, rowId); + mContext.getContentResolver().notifyChange(messageUri, null); + Log.i(TAG, "Message inserted in database "); + return messageUri; - @Override - public boolean onCreate() { - Log.e(TAG, "ONCREATE"); - dbHelper = new DatabaseHelper(getContext()); - return true; - } - - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { - SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); - - switch (sUriMatcher.match(uri)) { - case MESSAGES: - qb.setTables(MESSAGES_TABLE_NAME); - qb.setProjectionMap(messagesProjectionMap); - break; - - default: - throw new IllegalArgumentException("Unknown URI " + uri); } - SQLiteDatabase db = dbHelper.getReadableDatabase(); - Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder); - - c.setNotificationUri(getContext().getContentResolver(), uri); - return c; - } + @Override + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - SQLiteDatabase db = dbHelper.getWritableDatabase(); - int count; - switch (sUriMatcher.match(uri)) { - case MESSAGES: - count = db.update(MESSAGES_TABLE_NAME, values, selection, selectionArgs); - break; + switch (sUriMatcher.match(uri)) { + case MESSAGES: + qb.setTables(MESSAGES_TABLE_NAME); + qb.setProjectionMap(messagesProjectionMap); + break; - default: - throw new IllegalArgumentException("Unknown URI " + uri); - } - - getContext().getContentResolver().notifyChange(uri, null); - return count; - } - - private static class DatabaseHelper extends SQLiteOpenHelper { - - DatabaseHelper(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - Log.e(TAG, "Constructor"); + default: + throw new IllegalArgumentException("Unknown URI " + uri); + } + SQLiteDatabase db = mDbHelper.getReadableDatabase(); + Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder); + c.setNotificationUri(mContext.getContentResolver(), uri); + return c; } @Override - public void onCreate(SQLiteDatabase db) { - Log.e(TAG, "onCreate"); - String createDatabase = "CREATE TABLE " + MESSAGES_TABLE_NAME + " ("; - createDatabase += Messages._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"; - createDatabase += Messages.FROM + " VARCHAR(255),"; - createDatabase += Messages.MESSAGE_ID + " VARCHAR(255),"; - createDatabase += Messages.TO + " VARCHAR(255),"; - createDatabase += Messages.TYPE + " VARCHAR(255),"; - createDatabase += Messages.SUBJECT + " VARCHAR(255),"; - createDatabase += Messages.BODY + " LONGTEXT,"; - createDatabase += Messages.THREAD + " VARCHAR(255),"; - createDatabase += Messages.EXTRAS + " VARCHAR(255),"; - createDatabase += Messages.IS_RECEIVE + " BOOLEAN,"; - createDatabase += Messages.DATE_RECEIVE + " DATE,"; - createDatabase += Messages.DATE_READ + "DATE"; - createDatabase += ");"; - try { - db.execSQL(createDatabase); - } catch (SQLException e) { - Log.e(TAG, "CREATE DB PROBLEM"); - } + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + int count; + SQLiteDatabase db = mDbHelper.getWritableDatabase(); + switch (sUriMatcher.match(uri)) { + case MESSAGES: + count = db.update(MESSAGES_TABLE_NAME, values, selection, selectionArgs); + break; + + default: + throw new IllegalArgumentException("Unknown URI " + uri); + } + mContext.getContentResolver().notifyChange(uri, null); + return count; + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + int count; + SQLiteDatabase db = mDbHelper.getWritableDatabase(); + switch (sUriMatcher.match(uri)) { + case MESSAGES: + count = db.delete(MESSAGES_TABLE_NAME, selection, selectionArgs); + break; + + default: + throw new IllegalArgumentException("Unknown URI " + uri); + } + mContext.getContentResolver().notifyChange(uri, null); + return count; } @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion - + ", which will destroy all old data"); - db.execSQL("DROP TABLE IF EXISTS " + MESSAGES_TABLE_NAME); - onCreate(db); + public String getType(Uri uri) { + switch (sUriMatcher.match(uri)) { + case MESSAGES: + return Messages.CONTENT_TYPE; + default: + throw new IllegalArgumentException("Unknown URI " + uri); + } } - } + + private class DatabaseHelper extends SQLiteOpenHelper { - static { - sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); - sUriMatcher.addURI(AUTHORITY, MESSAGES_TABLE_NAME, MESSAGES); + DatabaseHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + Log.e(TAG, "ConStructeur"); + } - messagesProjectionMap = new HashMap(); - messagesProjectionMap.put(Messages._ID, Messages._ID); - messagesProjectionMap.put(Messages.FROM, Messages.FROM); - messagesProjectionMap.put(Messages.MESSAGE_ID, Messages.MESSAGE_ID); - messagesProjectionMap.put(Messages.TO, Messages.TO); - messagesProjectionMap.put(Messages.TYPE, Messages.TYPE); - messagesProjectionMap.put(Messages.SUBJECT, Messages.SUBJECT); - messagesProjectionMap.put(Messages.BODY, Messages.BODY); - messagesProjectionMap.put(Messages.THREAD, Messages.THREAD); - messagesProjectionMap.put(Messages.EXTRAS, Messages.EXTRAS); - messagesProjectionMap.put(Messages.IS_RECEIVE, Messages.IS_RECEIVE); - messagesProjectionMap.put(Messages.DATE_RECEIVE, Messages.IS_RECEIVE); - messagesProjectionMap.put(Messages.DATE_READ, Messages.DATE_READ); - } + @Override + public void onCreate(SQLiteDatabase db) { + Log.e(TAG, "onCreate"); + String createDatabase = "CREATE TABLE " + MESSAGES_TABLE_NAME + " ("; + createDatabase += Messages._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"; + createDatabase += Messages.FROM + " VARCHAR(255),"; + createDatabase += Messages.MESSAGE_ID + " VARCHAR(255),"; + createDatabase += Messages.TO + " VARCHAR(255),"; + createDatabase += Messages.TYPE + " VARCHAR(255),"; + createDatabase += Messages.SUBJECT + " VARCHAR(255),"; + createDatabase += Messages.BODY + " LONGTEXT,"; + createDatabase += Messages.THREAD + " VARCHAR(255),"; + createDatabase += Messages.EXTRAS + " VARCHAR(255),"; + createDatabase += Messages.IS_RECEIVE + " BOOLEAN,"; + createDatabase += Messages.DATE_RECEIVE + " DATE,"; + createDatabase += Messages.DATE_READ + " DATE"; + createDatabase += ");"; + try { + db.execSQL(createDatabase); + } catch (SQLException e) { + Log.e(TAG, "CREATE DB PROBLEM", e); + } + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion + + ", which will destroy all old data"); + db.execSQL("DROP TABLE IF EXISTS " + MESSAGES_TABLE_NAME); + onCreate(db); + } + } + + static { + sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); + sUriMatcher.addURI(AUTHORITY, MESSAGES_TABLE_NAME, MESSAGES); + + messagesProjectionMap = new HashMap(); + messagesProjectionMap.put(Messages._ID, Messages._ID); + messagesProjectionMap.put(Messages.FROM, Messages.FROM); + messagesProjectionMap.put(Messages.MESSAGE_ID, Messages.MESSAGE_ID); + messagesProjectionMap.put(Messages.TO, Messages.TO); + messagesProjectionMap.put(Messages.TYPE, Messages.TYPE); + messagesProjectionMap.put(Messages.SUBJECT, Messages.SUBJECT); + messagesProjectionMap.put(Messages.BODY, Messages.BODY); + messagesProjectionMap.put(Messages.THREAD, Messages.THREAD); + messagesProjectionMap.put(Messages.EXTRAS, Messages.EXTRAS); + messagesProjectionMap.put(Messages.IS_RECEIVE, Messages.IS_RECEIVE); + messagesProjectionMap.put(Messages.DATE_RECEIVE, Messages.DATE_RECEIVE); + messagesProjectionMap.put(Messages.DATE_READ, Messages.DATE_READ); + } } diff -r ac9461be2bd7 -r c067ee9a604c src/com/beem/project/beem/providers/Messages.java --- a/src/com/beem/project/beem/providers/Messages.java Mon Aug 22 22:43:19 2011 +0200 +++ b/src/com/beem/project/beem/providers/Messages.java Fri Oct 14 18:57:07 2011 +0200 @@ -16,17 +16,17 @@ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.beem.project.beem.provider.messages"; public static final String _ID = "_id"; - public static final String FROM = "FROM"; - public static final String MESSAGE_ID = "MESSAGE_ID"; - public static final String TO = "TO"; - public static final String TYPE = "TYPE"; - public static final String SUBJECT = "SUBJECT"; - public static final String BODY = "BODY"; - public static final String THREAD = "THREAD"; - public static final String EXTRAS = "EXTRAS"; - public static final String IS_RECEIVE = "IS_RECEIVE"; - public static final String DATE_RECEIVE = "DATE_RECEIVE"; - public static final String DATE_READ = "DATE_READ"; + public static final String FROM = "_FROM"; + public static final String MESSAGE_ID = "_MESSAGE_ID"; + public static final String TO = "_TO"; + public static final String TYPE = "_TYPE"; + public static final String SUBJECT = "_SUBJECT"; + public static final String BODY = "_BODY"; + public static final String THREAD = "_THREAD"; + public static final String EXTRAS = "_EXTRAS"; + public static final String IS_RECEIVE = "_IS_RECEIVE"; + public static final String DATE_RECEIVE = "_DATE_RECEIVE"; + public static final String DATE_READ = "_DATE_READ"; } diff -r ac9461be2bd7 -r c067ee9a604c src/com/beem/project/beem/service/BeemChatManager.java --- a/src/com/beem/project/beem/service/BeemChatManager.java Mon Aug 22 22:43:19 2011 +0200 +++ b/src/com/beem/project/beem/service/BeemChatManager.java Fri Oct 14 18:57:07 2011 +0200 @@ -40,11 +40,13 @@ Flavien Astraud, November 26, 2009 Head of the EIP Laboratory. -*/ + */ package com.beem.project.beem.service; import java.io.File; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -55,6 +57,7 @@ import android.app.Notification; import android.app.PendingIntent; +import android.content.ContentValues; import android.content.Intent; import android.content.SharedPreferences; import android.os.Environment; @@ -65,6 +68,8 @@ import com.beem.project.beem.BeemApplication; import com.beem.project.beem.BeemService; +import com.beem.project.beem.providers.MessageProvider; +import com.beem.project.beem.providers.Messages; import com.beem.project.beem.service.aidl.IChat; import com.beem.project.beem.service.aidl.IChatManager; import com.beem.project.beem.service.aidl.IChatManagerListener; @@ -77,248 +82,263 @@ */ public class BeemChatManager extends IChatManager.Stub { - private static final String TAG = "BeemChatManager"; - private final ChatManager mAdaptee; - private final Map mChats = new HashMap(); - private final ChatListener mChatListener = new ChatListener(); - private final RemoteCallbackList mRemoteChatCreationListeners = - new RemoteCallbackList(); - private final BeemService mService; - - /** - * Constructor. - * @param chatManager the smack ChatManager to adapt - * @param service the service which runs the chat manager - */ - public BeemChatManager(final ChatManager chatManager, final BeemService service) { - mService = service; - mAdaptee = chatManager; - mAdaptee.addChatListener(mChatListener); - } - - @Override - public void addChatCreationListener(IChatManagerListener listener) throws RemoteException { - if (listener != null) - mRemoteChatCreationListeners.register(listener); - } - - /** - * Create a chat session. - * @param contact the contact you want to chat with - * @param listener listener to use for chat events on this chat session - * @return the chat session - */ - @Override - public IChat createChat(Contact contact, IMessageListener listener) { - String jid = contact.getJIDWithRes(); - Log.d(TAG, "Get chat key1 = "); - - return createChat(jid, listener); - } - - /** - * Create a chat session. - * @param jid the jid of the contact you want to chat with - * @param listener listener to use for chat events on this chat session - * @return the chat session - */ - public IChat createChat(String jid, IMessageListener listener) { - String key = jid; - ChatAdapter result; - Log.d(TAG, "Get chat key2 = "); - if (mChats.containsKey(key)) { - result = mChats.get(key); - result.addMessageListener(listener); - return result; - } - Chat c = mAdaptee.createChat(key, null); - // maybe a little probleme of thread synchronization - // if so use an HashTable instead of a HashMap for mChats - result = getChat(c); - result.addMessageListener(listener); - return result; - } - - /** - * {@inheritDoc} - */ - @Override - public void destroyChat(IChat chat) throws RemoteException { - // Can't remove it. otherwise we will lose all futur message in this chat - // chat.removeMessageListener(mChatListener); - if (chat == null) - return; - deleteChatNotification(chat); - mChats.remove(chat.getParticipant().getJID()); - } - - /** - * {@inheritDoc} - */ - @Override - public void deleteChatNotification(IChat chat) { - try { - mService.deleteNotification(chat.getParticipant().getJID().hashCode()); - } catch (RemoteException e) { - Log.v(TAG, "Remote exception ", e); - } - } - - /** - * Get an existing ChatAdapter or create it if necessary. - * @param chat The real instance of smack chat - * @return a chat adapter register in the manager - */ - private ChatAdapter getChat(Chat chat) { - String key = chat.getParticipant(); - if (mChats.containsKey(key)) { - return mChats.get(key); - } - ChatAdapter res = new ChatAdapter(chat); - boolean history = PreferenceManager.getDefaultSharedPreferences(mService.getBaseContext()).getBoolean( - "settings_key_history", false); - String accountUser = PreferenceManager.getDefaultSharedPreferences(mService.getBaseContext()).getString( - BeemApplication.ACCOUNT_USERNAME_KEY, ""); - String historyPath = PreferenceManager.getDefaultSharedPreferences(mService.getBaseContext()).getString( - BeemApplication.CHAT_HISTORY_KEY, ""); - if ("".equals(historyPath)) historyPath = "/Android/data/com.beem.project.beem/chat/"; - res.setHistory(history); - res.setAccountUser(accountUser); - res.setHistoryPath(new File(Environment.getExternalStorageDirectory(), historyPath)); - Log.d(TAG, "getChat put " + key); - mChats.put(key, res); - return res; - } - - @Override - public ChatAdapter getChat(Contact contact) { - String key = contact.getJIDWithRes(); - return mChats.get(key); - } - - /** - * This methods permits to retrieve the list of contacts who have an opened chat session with us. - * @return An List containing Contact instances. - * @throws RemoteException If a Binder remote-invocation error occurred. - */ - public List getOpenedChatList() throws RemoteException { - List openedChats = new ArrayList(); - IRoster mRoster = mService.getBind().getRoster(); - - for (ChatAdapter chat : mChats.values()) { - if (chat.getMessages().size() > 0) { - Contact t = mRoster.getContact(chat.getParticipant().getJID()); - if (t == null) - t = new Contact(chat.getParticipant().getJID()); - openedChats.add(t); - } - } - return openedChats; - } - - /** - * {@inheritDoc} - */ - @Override - public void removeChatCreationListener(IChatManagerListener listener) throws RemoteException { - if (listener != null) - mRemoteChatCreationListeners.unregister(listener); - } - - /** - * A listener for all the chat creation event that happens on the connection. - * @author darisk - */ - private class ChatListener extends IMessageListener.Stub implements ChatManagerListener { + private static final String TAG = "BeemChatManager"; + private final ChatManager mAdaptee; + private final Map mChats = new HashMap(); + private final ChatListener mChatListener = new ChatListener(); + private final RemoteCallbackList mRemoteChatCreationListeners = new RemoteCallbackList(); + private final BeemService mService; /** * Constructor. + * @param chatManager the smack ChatManager to adapt + * @param service the service which runs the chat manager */ - public ChatListener() { + public BeemChatManager(final ChatManager chatManager, final BeemService service) { + mService = service; + mAdaptee = chatManager; + mAdaptee.addChatListener(mChatListener); + } + + @Override + public void addChatCreationListener(IChatManagerListener listener) throws RemoteException { + if (listener != null) + mRemoteChatCreationListeners.register(listener); + } + + /** + * Create a chat session. + * @param contact the contact you want to chat with + * @param listener listener to use for chat events on this chat session + * @return the chat session + */ + @Override + public IChat createChat(Contact contact, IMessageListener listener) { + String jid = contact.getJIDWithRes(); + Log.d(TAG, "Get chat key1 = "); + + return createChat(jid, listener); + } + + /** + * Create a chat session. + * @param jid the jid of the contact you want to chat with + * @param listener listener to use for chat events on this chat session + * @return the chat session + */ + public IChat createChat(String jid, IMessageListener listener) { + String key = jid; + ChatAdapter result; + Log.d(TAG, "Get chat key2 = "); + if (mChats.containsKey(key)) { + result = mChats.get(key); + result.addMessageListener(listener); + return result; + } + Chat c = mAdaptee.createChat(key, null); + // maybe a little probleme of thread synchronization + // if so use an HashTable instead of a HashMap for mChats + result = getChat(c); + result.addMessageListener(listener); + return result; + } + + /** + * {@inheritDoc} + */ + @Override + public void destroyChat(IChat chat) throws RemoteException { + // Can't remove it. otherwise we will lose all futur message in this chat + // chat.removeMessageListener(mChatListener); + if (chat == null) + return; + deleteChatNotification(chat); + mChats.remove(chat.getParticipant().getJID()); } /** * {@inheritDoc} */ @Override - public void chatCreated(Chat chat, boolean locally) { - IChat newchat = getChat(chat); - Log.d(TAG, "Chat" + chat.toString() + " created locally " + locally + "with " + chat.getParticipant()); - try { - newchat.addMessageListener(mChatListener); - final int n = mRemoteChatCreationListeners.beginBroadcast(); - - for (int i = 0; i < n; i++) { - IChatManagerListener listener = mRemoteChatCreationListeners.getBroadcastItem(i); - listener.chatCreated(newchat, locally); + public void deleteChatNotification(IChat chat) { + try { + mService.deleteNotification(chat.getParticipant().getJID().hashCode()); + } catch (RemoteException e) { + Log.v(TAG, "Remote exception ", e); } - mRemoteChatCreationListeners.finishBroadcast(); - } catch (RemoteException e) { - // The RemoteCallbackList will take care of removing the - // dead listeners. - Log.w(TAG, " Error while triggering remote connection listeners in chat creation", e); - } } /** - * Create the PendingIntent to launch our activity if the user select this chat notification. - * @param chat A ChatAdapter instance - * @return A Chat activity PendingIntent + * Get an existing ChatAdapter or create it if necessary. + * @param chat The real instance of smack chat + * @return a chat adapter register in the manager */ - private PendingIntent makeChatIntent(IChat chat) { - Intent chatIntent = new Intent(mService, com.beem.project.beem.ui.Chat.class); - chatIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP - | Intent.FLAG_ACTIVITY_NEW_TASK); - try { - chatIntent.setData(chat.getParticipant().toUri()); - } catch (RemoteException e) { - Log.e(TAG, e.getMessage()); - } - PendingIntent contentIntent = PendingIntent.getActivity(mService, 0, chatIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - return contentIntent; + private ChatAdapter getChat(Chat chat) { + String key = chat.getParticipant(); + if (mChats.containsKey(key)) { + return mChats.get(key); + } + ChatAdapter res = new ChatAdapter(chat); + boolean history = PreferenceManager.getDefaultSharedPreferences(mService.getBaseContext()).getBoolean( + "settings_key_history", false); + String accountUser = PreferenceManager.getDefaultSharedPreferences(mService.getBaseContext()).getString( + BeemApplication.ACCOUNT_USERNAME_KEY, ""); + String historyPath = PreferenceManager.getDefaultSharedPreferences(mService.getBaseContext()).getString( + BeemApplication.CHAT_HISTORY_KEY, ""); + if ("".equals(historyPath)) + historyPath = "/Android/data/com.beem.project.beem/chat/"; + res.setHistory(history); + res.setAccountUser(accountUser); + res.setHistoryPath(new File(Environment.getExternalStorageDirectory(), historyPath)); + Log.d(TAG, "getChat put " + key); + mChats.put(key, res); + return res; + } + + @Override + public ChatAdapter getChat(Contact contact) { + String key = contact.getJIDWithRes(); + return mChats.get(key); } /** - * Set a notification of a new chat. - * @param chat The chat to access by the notification - * @param msgBody the body of the new message + * This methods permits to retrieve the list of contacts who have an opened chat session with us. + * @return An List containing Contact instances. + * @throws RemoteException If a Binder remote-invocation error occurred. */ - private void notifyNewChat(IChat chat, String msgBody) { - SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(mService); - try { - CharSequence tickerText = mService.getBind().getRoster().getContact(chat.getParticipant().getJID()) - .getName(); - Notification notification = new Notification(android.R.drawable.stat_notify_chat, tickerText, System - .currentTimeMillis()); - notification.flags = Notification.FLAG_AUTO_CANCEL; - notification.setLatestEventInfo(mService, tickerText, msgBody, makeChatIntent(chat)); - mService.sendNotification(chat.getParticipant().getJID().hashCode(), notification); - } catch (RemoteException e) { - Log.e(TAG, e.getMessage()); - } + public List getOpenedChatList() throws RemoteException { + List openedChats = new ArrayList(); + IRoster mRoster = mService.getBind().getRoster(); + + for (ChatAdapter chat : mChats.values()) { + if (chat.getMessages().size() > 0) { + Contact t = mRoster.getContact(chat.getParticipant().getJID()); + if (t == null) + t = new Contact(chat.getParticipant().getJID()); + openedChats.add(t); + } + } + return openedChats; } /** * {@inheritDoc} */ @Override - public void processMessage(final IChat chat, Message message) { - try { - String body = message.getBody(); - if (!chat.isOpen() && body != null) { - if (chat instanceof ChatAdapter) { - mChats.put(chat.getParticipant().getJID(), (ChatAdapter) chat); - } - notifyNewChat(chat, body); - } - } catch (RemoteException e) { - Log.e(TAG, e.getMessage()); - } + public void removeChatCreationListener(IChatManagerListener listener) throws RemoteException { + if (listener != null) + mRemoteChatCreationListeners.unregister(listener); } - @Override - public void stateChanged(final IChat chat) { + /** + * A listener for all the chat creation event that happens on the connection. + * @author darisk + */ + private class ChatListener extends IMessageListener.Stub implements ChatManagerListener { + + /** + * Constructor. + */ + public ChatListener() { + } + + /** + * {@inheritDoc} + */ + @Override + public void chatCreated(Chat chat, boolean locally) { + IChat newchat = getChat(chat); + Log.d(TAG, "Chat" + chat.toString() + " created locally " + locally + "with " + chat.getParticipant()); + try { + newchat.addMessageListener(mChatListener); + final int n = mRemoteChatCreationListeners.beginBroadcast(); + + for (int i = 0; i < n; i++) { + IChatManagerListener listener = mRemoteChatCreationListeners.getBroadcastItem(i); + listener.chatCreated(newchat, locally); + } + mRemoteChatCreationListeners.finishBroadcast(); + } catch (RemoteException e) { + // The RemoteCallbackList will take care of removing the + // dead listeners. + Log.w(TAG, " Error while triggering remote connection listeners in chat creation", e); + } + } + + /** + * Create the PendingIntent to launch our activity if the user select this chat notification. + * @param chat A ChatAdapter instance + * @return A Chat activity PendingIntent + */ + private PendingIntent makeChatIntent(IChat chat) { + Intent chatIntent = new Intent(mService, com.beem.project.beem.ui.Chat.class); + chatIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP + | Intent.FLAG_ACTIVITY_NEW_TASK); + try { + chatIntent.setData(chat.getParticipant().toUri()); + } catch (RemoteException e) { + Log.e(TAG, e.getMessage()); + } + PendingIntent contentIntent = PendingIntent.getActivity(mService, 0, chatIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + return contentIntent; + } + + /** + * Set a notification of a new chat. + * @param chat The chat to access by the notification + * @param msgBody the body of the new message + */ + private void notifyNewChat(IChat chat, String msgBody) { + SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(mService); + try { + CharSequence tickerText = mService.getBind().getRoster().getContact(chat.getParticipant().getJID()) + .getName(); + Notification notification = new Notification(android.R.drawable.stat_notify_chat, tickerText, System + .currentTimeMillis()); + notification.flags = Notification.FLAG_AUTO_CANCEL; + notification.setLatestEventInfo(mService, tickerText, msgBody, makeChatIntent(chat)); + mService.sendNotification(chat.getParticipant().getJID().hashCode(), notification); + } catch (RemoteException e) { + Log.e(TAG, e.getMessage()); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void processMessage(final IChat chat, Message message) { + try { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + // note that we don't have to add an id as our table set id as autoincrement + ContentValues values = new ContentValues(); + values.put(Messages.FROM, message.getFrom()); + values.put(Messages.MESSAGE_ID, "message id"); + values.put(Messages.TO, message.getTo()); + values.put(Messages.TYPE, message.getType()); + values.put(Messages.SUBJECT, "SUBJECT"); + values.put(Messages.BODY, message.getBody()); + values.put(Messages.THREAD, "THREAD"); + values.put(Messages.EXTRAS, "EXTRAS"); + values.put(Messages.IS_RECEIVE, true); + values.put(Messages.DATE_RECEIVE, dateFormat.format(new Date())); + values.put(Messages.DATE_READ, dateFormat.format(message.getTimestamp())); + mService.getContentResolver().insert(Messages.CONTENT_URI, values); + String body = message.getBody(); + if (!chat.isOpen() && body != null) { + if (chat instanceof ChatAdapter) { + mChats.put(chat.getParticipant().getJID(), (ChatAdapter) chat); + } + notifyNewChat(chat, body); + } + } catch (RemoteException e) { + Log.e(TAG, e.getMessage()); + } + } + + @Override + public void stateChanged(final IChat chat) { + } } - } } diff -r ac9461be2bd7 -r c067ee9a604c src/com/beem/project/beem/service/ChatAdapter.java --- a/src/com/beem/project/beem/service/ChatAdapter.java Mon Aug 22 22:43:19 2011 +0200 +++ b/src/com/beem/project/beem/service/ChatAdapter.java Fri Oct 14 18:57:07 2011 +0200 @@ -40,7 +40,7 @@ Flavien Astraud, November 26, 2009 Head of the EIP Laboratory. -*/ + */ package com.beem.project.beem.service; import java.io.File; @@ -56,14 +56,11 @@ import org.jivesoftware.smackx.ChatState; import org.jivesoftware.smackx.ChatStateListener; -import android.content.ContentValues; import android.os.Environment; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.util.Log; -import com.beem.project.beem.providers.MessageProvider; -import com.beem.project.beem.providers.Messages; import com.beem.project.beem.service.aidl.IChat; import com.beem.project.beem.service.aidl.IMessageListener; @@ -72,269 +69,264 @@ * @author darisk */ public class ChatAdapter extends IChat.Stub { - private static final int HISTORY_MAX_SIZE = 50; - private static final String TAG = "ChatAdapter"; - - private final Chat mAdaptee; - private final Contact mParticipant; - private String mState; - private boolean mIsOpen; - private final List mMessages; - private final RemoteCallbackList mRemoteListeners = new RemoteCallbackList(); - private final MsgListener mMsgListener = new MsgListener(); - private boolean mIsHistory; - private File mHistoryPath; - private String mAccountUser; - - /** - * Constructor. - * @param chat The chat to adapt - */ - public ChatAdapter(final Chat chat) { - mAdaptee = chat; - mParticipant = new Contact(chat.getParticipant()); - mMessages = new LinkedList(); - mAdaptee.addMessageListener(mMsgListener); - } - - /** - * {@inheritDoc} - */ - @Override - public Contact getParticipant() throws RemoteException { - return mParticipant; - } - - /** - * {@inheritDoc} - */ - @Override - public void sendMessage(com.beem.project.beem.service.Message message) throws RemoteException { - org.jivesoftware.smack.packet.Message send = new org.jivesoftware.smack.packet.Message(); - send.setTo(message.getTo()); - send.setBody(message.getBody()); - send.setThread(message.getThread()); - send.setSubject(message.getSubject()); - send.setType(org.jivesoftware.smack.packet.Message.Type.chat); - // TODO gerer les messages contenant des XMPPError - // send.set - try { - mAdaptee.sendMessage(send); - mMessages.add(message); - } catch (XMPPException e) { - e.printStackTrace(); - } - String state = Environment.getExternalStorageState(); - if (mIsHistory && Environment.MEDIA_MOUNTED.equals(state)) - saveHistory(message, mAccountUser); - } - - /** - * {@inheritDoc} - */ - @Override - public void addMessageListener(IMessageListener listen) { - if (listen != null) - mRemoteListeners.register(listen); - } - - /** - * {@inheritDoc} - */ - @Override - public void removeMessageListener(IMessageListener listen) { - if (listen != null) { - mRemoteListeners.unregister(listen); - } - } - - /** - * {@inheritDoc} - */ - @Override - public String getState() throws RemoteException { - return mState; - } - - /** - * {@inheritDoc} - */ - @Override - public void setState(String state) throws RemoteException { - mState = state; - } - - /** - * Get the adaptee for the Chat. - * @return The real chat object - */ - public Chat getAdaptee() { - return mAdaptee; - } - - /** - * {@inheritDoc} - */ - @Override - public void setOpen(boolean isOpen) { - this.mIsOpen = isOpen; - } + private static final int HISTORY_MAX_SIZE = 50; + private static final String TAG = "ChatAdapter"; - /** - * {@inheritDoc} - */ - @Override - public boolean isOpen() { - return mIsOpen; - } - - /** - * {@inheritDoc} - */ - @Override - public List getMessages() throws RemoteException { - return Collections.unmodifiableList(mMessages); - } - - /** - * Add a message in the chat history. - * @param msg the message to add - */ - void addMessage(Message msg) { - if (mMessages.size() == HISTORY_MAX_SIZE) - mMessages.remove(0); - MessageProvider mp = new MessageProvider(); - ContentValues contentValue = new ContentValues(); - // note that we don't have to add an id as our table set id as autoincrement - //contentValue.put(Messages.FROM, msg.getFrom()); - Log.e(TAG, "xxxxxxxxxxxxxxMESSAGExxxxxxxxxxxxxxxxxxx"); - contentValue.put(Messages.BODY, msg.getBody()); - mp.insert(Messages.CONTENT_URI, contentValue); - mMessages.add(msg); - if (!"".equals(msg.getBody()) && msg.getBody() != null) { - String state = Environment.getExternalStorageState(); - if (mIsHistory && Environment.MEDIA_MOUNTED.equals(state)) - saveHistory(msg, msg.getFrom()); - } - } + private final Chat mAdaptee; + private final Contact mParticipant; + private String mState; + private boolean mIsOpen; + private final List mMessages; + private final RemoteCallbackList mRemoteListeners = new RemoteCallbackList(); + private final MsgListener mMsgListener = new MsgListener(); + private boolean mIsHistory; + private File mHistoryPath; + private String mAccountUser; - /** - * Save message in SDCard. - * @param msg the message receive - * @param contactName the name of the contact - */ - public void saveHistory(Message msg, String contactName) { - File path = getHistoryPath(); - File filepath; - if (contactName.equals(msg.getFrom())) - filepath = new File(path, StringUtils.parseBareAddress(contactName)); - else - filepath = new File(path, StringUtils.parseBareAddress(msg.getTo())); - path.mkdirs(); - try { - FileWriter file = new FileWriter(filepath, true); - String log = msg.getTimestamp() + " " + contactName + " " + msg.getBody() - + System.getProperty("line.separator"); - file.write(log); - file.close(); - } catch (IOException e) { - Log.e(TAG, "Error writing chat history", e); - } - } - - /** - * set History enable/disable. - * @param isHisory history state - */ - public void setHistory(boolean isHisory) { - this.mIsHistory = isHisory; - } - - /** - * get History state. - * @return mIsHistory - */ - public boolean getHistory() { - return mIsHistory; - } - - /** - * Set Account user name. - * @param accountUser user name - */ - public void setAccountUser(String accountUser) { - mAccountUser = accountUser; - } - - /** - * get Account user name. - * @return mAccountUser - */ - public String getAccountUser() { - return mAccountUser; - } - - /** - * set History path. - * @param historyPath history path - */ - public void setHistoryPath(File historyPath) { - this.mHistoryPath = historyPath; - } - - /** - * get History path. - * @return mHistoryPath; - */ - public File getHistoryPath() { - return mHistoryPath; - } - - /** - * Listener. - */ - private class MsgListener implements ChatStateListener { /** * Constructor. + * @param chat The chat to adapt */ - public MsgListener() { + public ChatAdapter(final Chat chat) { + mAdaptee = chat; + mParticipant = new Contact(chat.getParticipant()); + mMessages = new LinkedList(); + mAdaptee.addMessageListener(mMsgListener); + } + + /** + * {@inheritDoc} + */ + @Override + public Contact getParticipant() throws RemoteException { + return mParticipant; + } + + /** + * {@inheritDoc} + */ + @Override + public void sendMessage(com.beem.project.beem.service.Message message) throws RemoteException { + org.jivesoftware.smack.packet.Message send = new org.jivesoftware.smack.packet.Message(); + send.setTo(message.getTo()); + send.setBody(message.getBody()); + send.setThread(message.getThread()); + send.setSubject(message.getSubject()); + send.setType(org.jivesoftware.smack.packet.Message.Type.chat); + // TODO gerer les messages contenant des XMPPError + // send.set + try { + mAdaptee.sendMessage(send); + mMessages.add(message); + } catch (XMPPException e) { + e.printStackTrace(); + } + String state = Environment.getExternalStorageState(); + if (mIsHistory && Environment.MEDIA_MOUNTED.equals(state)) + saveHistory(message, mAccountUser); } + /** + * {@inheritDoc} + */ @Override - public void processMessage(Chat chat, org.jivesoftware.smack.packet.Message message) { - Message msg = new Message(message); - //TODO add que les message pas de type errors - ChatAdapter.this.addMessage(msg); - final int n = mRemoteListeners.beginBroadcast(); - for (int i = 0; i < n; i++) { - IMessageListener listener = mRemoteListeners.getBroadcastItem(i); - try { - if (listener != null) - listener.processMessage(ChatAdapter.this, msg); - } catch (RemoteException e) { - Log.w(TAG, "Error while diffusing message to listener", e); + public void addMessageListener(IMessageListener listen) { + if (listen != null) + mRemoteListeners.register(listen); + } + + /** + * {@inheritDoc} + */ + @Override + public void removeMessageListener(IMessageListener listen) { + if (listen != null) { + mRemoteListeners.unregister(listen); } - } - mRemoteListeners.finishBroadcast(); + } + + /** + * {@inheritDoc} + */ + @Override + public String getState() throws RemoteException { + return mState; + } + + /** + * {@inheritDoc} + */ + @Override + public void setState(String state) throws RemoteException { + mState = state; + } + + /** + * Get the adaptee for the Chat. + * @return The real chat object + */ + public Chat getAdaptee() { + return mAdaptee; + } + + /** + * {@inheritDoc} + */ + @Override + public void setOpen(boolean isOpen) { + this.mIsOpen = isOpen; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isOpen() { + return mIsOpen; } /** * {@inheritDoc} */ @Override - public void stateChanged(Chat chat, ChatState state) { - mState = state.name(); - final int n = mRemoteListeners.beginBroadcast(); + public List getMessages() throws RemoteException { + return Collections.unmodifiableList(mMessages); + } - for (int i = 0; i < n; i++) { - IMessageListener listener = mRemoteListeners.getBroadcastItem(i); + /** + * Add a message in the chat history. + * @param msg the message to add + */ + void addMessage(Message msg) { + if (mMessages.size() == HISTORY_MAX_SIZE) + mMessages.remove(0); + // note that we don't have to add an id as our table set id as autoincrement + //contentValue.put(Messages.FROM, msg.getFrom()); + mMessages.add(msg); + if (!"".equals(msg.getBody()) && msg.getBody() != null) { + String state = Environment.getExternalStorageState(); + if (mIsHistory && Environment.MEDIA_MOUNTED.equals(state)) + saveHistory(msg, msg.getFrom()); + } + } + + /** + * Save message in SDCard. + * @param msg the message receive + * @param contactName the name of the contact + */ + public void saveHistory(Message msg, String contactName) { + File path = getHistoryPath(); + File filepath; + if (contactName.equals(msg.getFrom())) + filepath = new File(path, StringUtils.parseBareAddress(contactName)); + else + filepath = new File(path, StringUtils.parseBareAddress(msg.getTo())); + path.mkdirs(); try { - listener.stateChanged(ChatAdapter.this); - } catch (RemoteException e) { - Log.w(TAG, e.getMessage()); + FileWriter file = new FileWriter(filepath, true); + String log = msg.getTimestamp() + " " + contactName + " " + msg.getBody() + + System.getProperty("line.separator"); + file.write(log); + file.close(); + } catch (IOException e) { + Log.e(TAG, "Error writing chat history", e); } - } - mRemoteListeners.finishBroadcast(); + } + + /** + * set History enable/disable. + * @param isHisory history state + */ + public void setHistory(boolean isHisory) { + this.mIsHistory = isHisory; + } + + /** + * get History state. + * @return mIsHistory + */ + public boolean getHistory() { + return mIsHistory; + } + + /** + * Set Account user name. + * @param accountUser user name + */ + public void setAccountUser(String accountUser) { + mAccountUser = accountUser; + } + + /** + * get Account user name. + * @return mAccountUser + */ + public String getAccountUser() { + return mAccountUser; + } + + /** + * set History path. + * @param historyPath history path + */ + public void setHistoryPath(File historyPath) { + this.mHistoryPath = historyPath; + } + + /** + * get History path. + * @return mHistoryPath; + */ + public File getHistoryPath() { + return mHistoryPath; } - } + + /** + * Listener. + */ + private class MsgListener implements ChatStateListener { + /** + * Constructor. + */ + public MsgListener() { + } + + @Override + public void processMessage(Chat chat, org.jivesoftware.smack.packet.Message message) { + Message msg = new Message(message); + //TODO add que les message pas de type errors + ChatAdapter.this.addMessage(msg); + final int n = mRemoteListeners.beginBroadcast(); + for (int i = 0; i < n; i++) { + IMessageListener listener = mRemoteListeners.getBroadcastItem(i); + try { + if (listener != null) + listener.processMessage(ChatAdapter.this, msg); + } catch (RemoteException e) { + Log.w(TAG, "Error while diffusing message to listener", e); + } + } + mRemoteListeners.finishBroadcast(); + } + + /** + * {@inheritDoc} + */ + @Override + public void stateChanged(Chat chat, ChatState state) { + mState = state.name(); + final int n = mRemoteListeners.beginBroadcast(); + + for (int i = 0; i < n; i++) { + IMessageListener listener = mRemoteListeners.getBroadcastItem(i); + try { + listener.stateChanged(ChatAdapter.this); + } catch (RemoteException e) { + Log.w(TAG, e.getMessage()); + } + } + mRemoteListeners.finishBroadcast(); + } + } } diff -r ac9461be2bd7 -r c067ee9a604c src/com/beem/project/beem/service/XmppConnectionAdapter.java --- a/src/com/beem/project/beem/service/XmppConnectionAdapter.java Mon Aug 22 22:43:19 2011 +0200 +++ b/src/com/beem/project/beem/service/XmppConnectionAdapter.java Fri Oct 14 18:57:07 2011 +0200 @@ -91,624 +91,625 @@ */ public class XmppConnectionAdapter extends IXmppConnection.Stub { - /** - * Beem connection closed Intent name. - */ - - private static final int SMACK_PRIORITY_MIN = -128; - private static final int SMACK_PRIORITY_MAX = 128; - private static final String TAG = "XMPPConnectionAdapter"; - private final XMPPConnection mAdaptee; - private IChatManager mChatManager; - private final String mLogin; - private final String mPassword; - private String mResource; - private String mErrorMsg; - private RosterAdapter mRoster; - private int mPreviousPriority; - private int mPreviousMode; - private String mPreviousStatus; - private PrivacyListManagerAdapter mPrivacyListManager; - private ChatStateManager mChatStateManager; - private final BeemService mService; - private BeemApplication mApplication; - private AvatarManager mAvatarManager; - private PepSubManager mPepManager; - private SharedPreferences mPref; - private final RemoteCallbackList mRemoteConnListeners = new RemoteCallbackList(); - private final SubscribePacketListener mSubscribePacketListener = new SubscribePacketListener(); - - private final ConnexionListenerAdapter mConListener = new ConnexionListenerAdapter(); - - /** - * Constructor. - * @param config Configuration to use in order to connect - * @param login login to use on connect - * @param password password to use on connect - * @param service the background service associated with the connection. - */ - public XmppConnectionAdapter(final ConnectionConfiguration config, final String login, final String password, - final BeemService service) { - this(new XMPPConnection(config), login, password, service); - } - - /** - * Constructor. - * @param serviceName name of the service to connect to - * @param login login to use on connect - * @param password password to use on connect - * @param service the background service associated with the connection. - */ - public XmppConnectionAdapter(final String serviceName, final String login, final String password, - final BeemService service) { - this(new XMPPConnection(serviceName), login, password, service); - } - - /** - * Constructor. - * @param con The connection to adapt - * @param login The login to use - * @param password The password to use - * @param service the background service associated with the connection. - */ - public XmppConnectionAdapter(final XMPPConnection con, final String login, final String password, - final BeemService service) { - mAdaptee = con; - PrivacyListManager.getInstanceFor(mAdaptee); - mLogin = StringUtils.parseName(login); - - mPassword = password; - mService = service; - Context ctx = mService.getApplicationContext(); - if (ctx instanceof BeemApplication) { - mApplication = (BeemApplication) ctx; - } - mPref = mService.getServicePreference(login); // login is the jid - try { - mPreviousPriority = Integer.parseInt(mPref.getString("settings_key_priority", "0")); - } catch (NumberFormatException ex) { - mPreviousPriority = 0; - } - mResource = mPref.getString("settings_key_resource", "BEEM"); - } - - /** - * {@inheritDoc} - */ - @Override - public void addConnectionListener(IBeemConnectionListener listen) throws RemoteException { - if (listen != null) - mRemoteConnListeners.register(listen); - } + /** + * Beem connection closed Intent name. + */ - @Override - public boolean connect() throws RemoteException { - if (mAdaptee.isConnected()) - return true; - else { - try { - mAdaptee.connect(); - mAdaptee.addConnectionListener(mConListener); - return true; - } catch (XMPPException e) { - Log.e(TAG, "Error while connecting", e); - 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")); - mErrorMsg = str; - } catch (NullPointerException e2) { - if (!"".equals(e.getMessage())) - mErrorMsg = e.getMessage(); - else - mErrorMsg = e.toString(); - } - } - return false; - } - } - - @Override - public boolean login() throws RemoteException { - if (mAdaptee.isAuthenticated()) - return true; - if (!mAdaptee.isConnected()) - return false; - try { - - this.initFeatures(); // pour declarer les features xmpp qu'on - // supporte - - PacketFilter filter = new PacketFilter() { - - @Override - public boolean accept(Packet packet) { - if (packet instanceof Presence) { - Presence pres = (Presence) packet; - if (pres.getType() == Presence.Type.subscribe) - return true; - } - return false; - } - }; + private static final int SMACK_PRIORITY_MIN = -128; + private static final int SMACK_PRIORITY_MAX = 128; + private static final String TAG = "XMPPConnectionAdapter"; + private final XMPPConnection mAdaptee; + private IChatManager mChatManager; + private final String mLogin; + private final String mPassword; + private String mResource; + private String mErrorMsg; + private RosterAdapter mRoster; + private int mPreviousPriority; + private int mPreviousMode; + private String mPreviousStatus; + private PrivacyListManagerAdapter mPrivacyListManager; + private ChatStateManager mChatStateManager; + private final BeemService mService; + private BeemApplication mApplication; + private AvatarManager mAvatarManager; + private PepSubManager mPepManager; + private SharedPreferences mPref; + private final RemoteCallbackList mRemoteConnListeners = new RemoteCallbackList(); + private final SubscribePacketListener mSubscribePacketListener = new SubscribePacketListener(); - mAdaptee.addPacketListener(mSubscribePacketListener, filter); - Log.e(TAG, mLogin + mPassword + mResource); - mAdaptee.login(mLogin, mPassword, mResource); - mChatManager = new BeemChatManager(mAdaptee.getChatManager(), mService); - //nikita: I commented this line because of the logs provided in http://www.beem-project.com/issues/321 - //Also, since the privacylistmanager isn't finished and used, it will be safer to not initialize it - //mPrivacyListManager = new PrivacyListManagerAdapter(PrivacyListManager.getInstanceFor(mAdaptee)); - mService.initJingle(mAdaptee); - discoverServerFeatures(); - - mRoster = new RosterAdapter(mAdaptee.getRoster(), mService, mAvatarManager); - mApplication.setConnected(true); - int mode = mPref.getInt(BeemApplication.STATUS_KEY, 0); - String status = mPref.getString(BeemApplication.STATUS_TEXT_KEY, ""); - changeStatus(mode, status); - return true; - } catch (XMPPException e) { - Log.e(TAG, "Error while connecting", e); - mErrorMsg = mService.getString(R.string.error_login_authentication); - return false; - } - } - - /** - * {@inheritDoc} - */ - @Override - public final void connectAsync() throws RemoteException { - if (mAdaptee.isConnected() || mAdaptee.isAuthenticated()) - return; - Thread t = new Thread(new Runnable() { - - @Override - public void run() { - try { - connectSync(); - } catch (RemoteException e) { - Log.e(TAG, "Error while connecting asynchronously", e); - } - } - }); - t.start(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean connectSync() throws RemoteException { - if (connect()) - return login(); - return false; - } + private final ConnexionListenerAdapter mConListener = new ConnexionListenerAdapter(); - /** - * {@inheritDoc} - */ - @Override - public void changeStatusAndPriority(int status, String msg, int priority) { - Presence pres = new Presence(Presence.Type.available); - String m; - if (msg != null) - m = msg; - else - m = mPreviousStatus; - pres.setStatus(m); - mPreviousStatus = m; - Presence.Mode mode = Status.getPresenceModeFromStatus(status); - if (mode != null) { - pres.setMode(mode); - mPreviousMode = status; - } else { - pres.setMode(Status.getPresenceModeFromStatus(mPreviousMode)); + /** + * Constructor. + * @param config Configuration to use in order to connect + * @param login login to use on connect + * @param password password to use on connect + * @param service the background service associated with the connection. + */ + public XmppConnectionAdapter(final ConnectionConfiguration config, final String login, final String password, + final BeemService service) { + this(new XMPPConnection(config), login, password, service); } - int p = priority; - if (priority < SMACK_PRIORITY_MIN) - p = SMACK_PRIORITY_MIN; - if (priority > SMACK_PRIORITY_MAX) - p = SMACK_PRIORITY_MAX; - mPreviousPriority = p; - pres.setPriority(p); - mAdaptee.sendPacket(pres); - updateNotification(m); - } - - /** - * {@inheritDoc} - */ - @Override - public void changeStatus(int status, String msg) { - changeStatusAndPriority(status, msg, mPreviousPriority); - } - - /** - * Get the AvatarManager of this connection. - * @return the AvatarManager or null if there is not - */ - public AvatarManager getAvatarManager() { - return mAvatarManager; - } - /** - * get the previous status. - * @return previous status. - */ - public String getPreviousStatus() { - return mPreviousStatus; - } - - /** - * get the previous mode. - * @return previous mode. - */ - public int getPreviousMode() { - return mPreviousMode; - } - - /** - * Update the notification for the Beem status. - * @param text the text to display. - */ - private void updateNotification(String text) { - Notification mStatusNotification; - mStatusNotification = new Notification(com.beem.project.beem.R.drawable.beem_status_icon, text, System - .currentTimeMillis()); - mStatusNotification.defaults = Notification.DEFAULT_LIGHTS; - mStatusNotification.flags = Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; - - mStatusNotification.setLatestEventInfo(mService, "Beem Status", text, PendingIntent.getActivity(mService, 0, - new Intent(mService, ChangeStatus.class), 0)); - // bypass the preferences for notification - mService.getNotificationManager().notify(BeemService.NOTIFICATION_STATUS_ID, mStatusNotification); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean disconnect() { - if (mAdaptee != null && mAdaptee.isConnected()) - mAdaptee.disconnect(); - return true; - } - - /** - * Get the Smack XmppConnection. - * @return Smack XmppConnection - */ - public XMPPConnection getAdaptee() { - return mAdaptee; - } - - /** - * {@inheritDoc} - */ - @Override - public IChatManager getChatManager() throws RemoteException { - return mChatManager; - } + /** + * Constructor. + * @param serviceName name of the service to connect to + * @param login login to use on connect + * @param password password to use on connect + * @param service the background service associated with the connection. + */ + public XmppConnectionAdapter(final String serviceName, final String login, final String password, + final BeemService service) { + this(new XMPPConnection(serviceName), login, password, service); + } - /** - * {@inheritDoc} - */ - @Override - public IRoster getRoster() throws RemoteException { - if (mRoster != null) - return mRoster; - Roster adap = mAdaptee.getRoster(); - if (adap == null) - return null; - mRoster = new RosterAdapter(adap, mService, mAvatarManager); - return mRoster; - } - - /** - * Returns true if currently authenticated by successfully calling the login method. - * @return true when successfully authenticated - */ - public boolean isAuthentificated() { - return mAdaptee.isAuthenticated(); - } - - /** - * {@inheritDoc} - */ - @Override - public void removeConnectionListener(IBeemConnectionListener listen) throws RemoteException { - if (listen != null) - mRemoteConnListeners.unregister(listen); - } + /** + * Constructor. + * @param con The connection to adapt + * @param login The login to use + * @param password The password to use + * @param service the background service associated with the connection. + */ + public XmppConnectionAdapter(final XMPPConnection con, final String login, final String password, + final BeemService service) { + mAdaptee = con; + PrivacyListManager.getInstanceFor(mAdaptee); + mLogin = StringUtils.parseName(login); - /** - * PrivacyListManagerAdapter mutator. - * @param privacyListManager the privacy list manager - */ - public void setPrivacyListManager(PrivacyListManagerAdapter privacyListManager) { - this.mPrivacyListManager = privacyListManager; - } - - /** - * PrivacyListManagerAdapter accessor. - * @return the mPrivacyList - */ - public PrivacyListManagerAdapter getPrivacyListManager() { - return mPrivacyListManager; - } - - /** - * {@inheritDoc} - */ - @Override - public String getErrorMessage() { - return mErrorMsg; - } - - public void handleMessage(android.os.Message msg) { - Bundle b = (Bundle) msg.obj; - switch (msg.what) { - - default: - Log.w(TAG, "Unknown message " + msg); + mPassword = password; + mService = service; + Context ctx = mService.getApplicationContext(); + if (ctx instanceof BeemApplication) { + mApplication = (BeemApplication) ctx; + } + mPref = mService.getServicePreference(login); // login is the jid + try { + mPreviousPriority = Integer.parseInt(mPref.getString("settings_key_priority", "0")); + } catch (NumberFormatException ex) { + mPreviousPriority = 0; + } + mResource = mPref.getString("settings_key_resource", "BEEM"); } - } - - /** - * Initialize the features provided by beem. - */ - private void initFeatures() { - ServiceDiscoveryManager.setIdentityName("Beem"); - ServiceDiscoveryManager.setIdentityType("phone"); - ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(mAdaptee); - if (sdm == null) - sdm = new ServiceDiscoveryManager(mAdaptee); - - sdm.addFeature("http://jabber.org/protocol/disco#info"); - //nikita: must be uncommented when the feature will be enabled - //sdm.addFeature("jabber:iq:privacy"); - sdm.addFeature("http://jabber.org/protocol/caps"); - sdm.addFeature("urn:xmpp:avatar:metadata"); - sdm.addFeature("urn:xmpp:avatar:metadata+notify"); - sdm.addFeature("urn:xmpp:avatar:data"); - sdm.addFeature("http://jabber.org/protocol/nick"); - sdm.addFeature("http://jabber.org/protocol/nick+notify"); - - mChatStateManager = ChatStateManager.getInstance(mAdaptee); - BeemCapsManager caps = new BeemCapsManager(sdm, mAdaptee, mService); - caps.setNode("http://www.beem-project.com"); - } - - /** - * Discover the features provided by the server. - */ - private void discoverServerFeatures() { - try { - // jid et server - ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(mAdaptee); - DiscoverInfo info = sdm.discoverInfo(mAdaptee.getServiceName()); - Iterator it = info.getIdentities(); - while (it.hasNext()) { - DiscoverInfo.Identity identity = it.next(); - if ("pubsub".equals(identity.getCategory()) && "pep".equals(identity.getType())) { - initPEP(); - } - } - } catch (XMPPException e) { - // No Pep - } - } - - /** - * Initialize PEP. - */ - private void initPEP() { - // Enable pep sending - // API 8 - // mService.getExternalCacheDir() - mPepManager = new PepSubManager(mAdaptee); - AvatarCache avatarCache = new BeemAvatarCache(mService); - mAvatarManager = new AvatarManager(mAdaptee, mPepManager, avatarCache, true); - } - - /** - * Listener for XMPP connection events. It will calls the remote listeners for connection events. - * @author darisk - */ - private class ConnexionListenerAdapter implements ConnectionListener { /** - * Defaut constructor. + * {@inheritDoc} + */ + @Override + public void addConnectionListener(IBeemConnectionListener listen) throws RemoteException { + if (listen != null) + mRemoteConnListeners.register(listen); + } + + @Override + public boolean connect() throws RemoteException { + if (mAdaptee.isConnected()) + return true; + else { + try { + mAdaptee.connect(); + mAdaptee.addConnectionListener(mConListener); + return true; + } catch (XMPPException e) { + Log.e(TAG, "Error while connecting", e); + 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")); + mErrorMsg = str; + } catch (NullPointerException e2) { + if (!"".equals(e.getMessage())) + mErrorMsg = e.getMessage(); + else + mErrorMsg = e.toString(); + } + } + return false; + } + } + + @Override + public boolean login() throws RemoteException { + if (mAdaptee.isAuthenticated()) + return true; + if (!mAdaptee.isConnected()) + return false; + try { + + this.initFeatures(); // pour declarer les features xmpp qu'on + // supporte + + PacketFilter filter = new PacketFilter() { + + @Override + public boolean accept(Packet packet) { + if (packet instanceof Presence) { + Presence pres = (Presence) packet; + if (pres.getType() == Presence.Type.subscribe) + return true; + } + return false; + } + }; + + mAdaptee.addPacketListener(mSubscribePacketListener, filter); + Log.e(TAG, mLogin + mPassword + mResource); + mAdaptee.login(mLogin, mPassword, mResource); + mChatManager = new BeemChatManager(mAdaptee.getChatManager(), mService); + //nikita: I commented this line because of the logs provided in http://www.beem-project.com/issues/321 + //Also, since the privacylistmanager isn't finished and used, it will be safer to not initialize it + //mPrivacyListManager = new PrivacyListManagerAdapter(PrivacyListManager.getInstanceFor(mAdaptee)); + mService.initJingle(mAdaptee); + discoverServerFeatures(); + + mRoster = new RosterAdapter(mAdaptee.getRoster(), mService, mAvatarManager); + mApplication.setConnected(true); + int mode = mPref.getInt(BeemApplication.STATUS_KEY, 0); + String status = mPref.getString(BeemApplication.STATUS_TEXT_KEY, ""); + changeStatus(mode, status); + return true; + } catch (XMPPException e) { + Log.e(TAG, "Error while connecting", e); + mErrorMsg = mService.getString(R.string.error_login_authentication); + return false; + } + } + + /** + * {@inheritDoc} + */ + @Override + public final void connectAsync() throws RemoteException { + if (mAdaptee.isConnected() || mAdaptee.isAuthenticated()) + return; + Thread t = new Thread(new Runnable() { + + @Override + public void run() { + try { + connectSync(); + } catch (RemoteException e) { + Log.e(TAG, "Error while connecting asynchronously", e); + } + } + }); + t.start(); + } + + /** + * {@inheritDoc} */ - public ConnexionListenerAdapter() { + @Override + public boolean connectSync() throws RemoteException { + if (connect()) + return login(); + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public void changeStatusAndPriority(int status, String msg, int priority) { + Presence pres = new Presence(Presence.Type.available); + String m; + if (msg != null) + m = msg; + else + m = mPreviousStatus; + pres.setStatus(m); + mPreviousStatus = m; + Presence.Mode mode = Status.getPresenceModeFromStatus(status); + if (mode != null) { + pres.setMode(mode); + mPreviousMode = status; + } else { + pres.setMode(Status.getPresenceModeFromStatus(mPreviousMode)); + } + int p = priority; + if (priority < SMACK_PRIORITY_MIN) + p = SMACK_PRIORITY_MIN; + if (priority > SMACK_PRIORITY_MAX) + p = SMACK_PRIORITY_MAX; + mPreviousPriority = p; + pres.setPriority(p); + mAdaptee.sendPacket(pres); + updateNotification(m); + } + + /** + * {@inheritDoc} + */ + @Override + public void changeStatus(int status, String msg) { + changeStatusAndPriority(status, msg, mPreviousPriority); + } + + /** + * Get the AvatarManager of this connection. + * @return the AvatarManager or null if there is not + */ + public AvatarManager getAvatarManager() { + return mAvatarManager; + } + + /** + * get the previous status. + * @return previous status. + */ + public String getPreviousStatus() { + return mPreviousStatus; + } + + /** + * get the previous mode. + * @return previous mode. + */ + public int getPreviousMode() { + return mPreviousMode; + } + + /** + * Update the notification for the Beem status. + * @param text the text to display. + */ + private void updateNotification(String text) { +// Notification mStatusNotification; +// mStatusNotification = new Notification(com.beem.project.beem.R.drawable.beem_status_icon, text, System +// .currentTimeMillis()); +// mStatusNotification.defaults = Notification.DEFAULT_LIGHTS; +// mStatusNotification.flags = Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT; +// +// mStatusNotification.setLatestEventInfo(mService, "Beem Status", text, PendingIntent.getActivity(mService, 0, +// new Intent(mService, ChangeStatus.class), 0)); +// // bypass the preferences for notification +// mService.getNotificationManager().notify(BeemService.NOTIFICATION_STATUS_ID, mStatusNotification); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean disconnect() { + if (mAdaptee != null && mAdaptee.isConnected()) + mAdaptee.disconnect(); + return true; + } + + /** + * Get the Smack XmppConnection. + * @return Smack XmppConnection + */ + public XMPPConnection getAdaptee() { + return mAdaptee; + } + + /** + * {@inheritDoc} + */ + @Override + public IChatManager getChatManager() throws RemoteException { + return mChatManager; } /** * {@inheritDoc} */ @Override - public void connectionClosed() { - Log.d(TAG, "closing connection"); - mRoster = null; - Intent intent = new Intent(BeemBroadcastReceiver.BEEM_CONNECTION_CLOSED); - intent.putExtra("message", mService.getString(R.string.BeemBroadcastReceiverDisconnect)); - intent.putExtra("normally", true); - mService.sendBroadcast(intent); - mService.stopSelf(); - mApplication.setConnected(false); + public IRoster getRoster() throws RemoteException { + if (mRoster != null) + return mRoster; + Roster adap = mAdaptee.getRoster(); + if (adap == null) + return null; + mRoster = new RosterAdapter(adap, mService, mAvatarManager); + return mRoster; + } + + /** + * Returns true if currently authenticated by successfully calling the login method. + * @return true when successfully authenticated + */ + public boolean isAuthentificated() { + return mAdaptee.isAuthenticated(); } /** * {@inheritDoc} */ @Override - public void connectionClosedOnError(Exception exception) { - Log.d(TAG, "connectionClosedOnError"); - mRoster = null; - Intent intent = new Intent(BeemBroadcastReceiver.BEEM_CONNECTION_CLOSED); - intent.putExtra("message", exception.getMessage()); - mService.sendBroadcast(intent); - mService.stopSelf(); - mApplication.setConnected(false); + public void removeConnectionListener(IBeemConnectionListener listen) throws RemoteException { + if (listen != null) + mRemoteConnListeners.unregister(listen); } /** - * Connection failed callback. - * @param errorMsg smack failure message + * PrivacyListManagerAdapter mutator. + * @param privacyListManager the privacy list manager */ - public void connectionFailed(String errorMsg) { - Log.d(TAG, "Connection Failed"); - final int n = mRemoteConnListeners.beginBroadcast(); - - for (int i = 0; i < n; i++) { - IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i); - try { - if (listener != null) - listener.connectionFailed(errorMsg); - } catch (RemoteException e) { - // The RemoteCallbackList will take care of removing the - // dead listeners. - Log.w(TAG, "Error while triggering remote connection listeners", e); - } - } - mRemoteConnListeners.finishBroadcast(); - mService.stopSelf(); - mApplication.setConnected(false); + public void setPrivacyListManager(PrivacyListManagerAdapter privacyListManager) { + this.mPrivacyListManager = privacyListManager; } /** - * {@inheritDoc} + * PrivacyListManagerAdapter accessor. + * @return the mPrivacyList */ - @Override - public void reconnectingIn(int arg0) { - Log.d(TAG, "reconnectingIn"); - final int n = mRemoteConnListeners.beginBroadcast(); - - for (int i = 0; i < n; i++) { - IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i); - try { - if (listener != null) - listener.reconnectingIn(arg0); - } catch (RemoteException e) { - // The RemoteCallbackList will take care of removing the - // dead listeners. - Log.w(TAG, "Error while triggering remote connection listeners", e); - } - } - mRemoteConnListeners.finishBroadcast(); + public PrivacyListManagerAdapter getPrivacyListManager() { + return mPrivacyListManager; } /** * {@inheritDoc} */ @Override - public void reconnectionFailed(Exception arg0) { - Log.d(TAG, "reconnectionFailed"); - final int r = mRemoteConnListeners.beginBroadcast(); + public String getErrorMessage() { + return mErrorMsg; + } + + public void handleMessage(android.os.Message msg) { + Log.e(TAG, "HANDLEMESSAGE"); + Bundle b = (Bundle) msg.obj; + switch (msg.what) { + + default: + Log.w(TAG, "Unknown message " + msg); + } + } - for (int i = 0; i < r; i++) { - IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i); + /** + * Initialize the features provided by beem. + */ + private void initFeatures() { + ServiceDiscoveryManager.setIdentityName("Beem"); + ServiceDiscoveryManager.setIdentityType("phone"); + ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(mAdaptee); + if (sdm == null) + sdm = new ServiceDiscoveryManager(mAdaptee); + + sdm.addFeature("http://jabber.org/protocol/disco#info"); + //nikita: must be uncommented when the feature will be enabled + //sdm.addFeature("jabber:iq:privacy"); + sdm.addFeature("http://jabber.org/protocol/caps"); + sdm.addFeature("urn:xmpp:avatar:metadata"); + sdm.addFeature("urn:xmpp:avatar:metadata+notify"); + sdm.addFeature("urn:xmpp:avatar:data"); + sdm.addFeature("http://jabber.org/protocol/nick"); + sdm.addFeature("http://jabber.org/protocol/nick+notify"); + + mChatStateManager = ChatStateManager.getInstance(mAdaptee); + BeemCapsManager caps = new BeemCapsManager(sdm, mAdaptee, mService); + caps.setNode("http://www.beem-project.com"); + } + + /** + * Discover the features provided by the server. + */ + private void discoverServerFeatures() { try { - if (listener != null) - listener.reconnectionFailed(); - } catch (RemoteException e) { - // The RemoteCallbackList will take care of removing the - // dead listeners. - Log.w(TAG, "Error while triggering remote connection listeners", e); + // jid et server + ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(mAdaptee); + DiscoverInfo info = sdm.discoverInfo(mAdaptee.getServiceName()); + Iterator it = info.getIdentities(); + while (it.hasNext()) { + DiscoverInfo.Identity identity = it.next(); + if ("pubsub".equals(identity.getCategory()) && "pep".equals(identity.getType())) { + initPEP(); + } + } + } catch (XMPPException e) { + // No Pep } - } - mRemoteConnListeners.finishBroadcast(); + } + + /** + * Initialize PEP. + */ + private void initPEP() { + // Enable pep sending + // API 8 + // mService.getExternalCacheDir() + mPepManager = new PepSubManager(mAdaptee); + AvatarCache avatarCache = new BeemAvatarCache(mService); + mAvatarManager = new AvatarManager(mAdaptee, mPepManager, avatarCache, true); } /** - * {@inheritDoc} + * Listener for XMPP connection events. It will calls the remote listeners for connection events. + * @author darisk */ - @Override - public void reconnectionSuccessful() { - Log.d(TAG, "reconnectionSuccessful"); - mApplication.setConnected(true); - PacketFilter filter = new PacketFilter() { + private class ConnexionListenerAdapter implements ConnectionListener { + + /** + * Defaut constructor. + */ + public ConnexionListenerAdapter() { + } + + /** + * {@inheritDoc} + */ + @Override + public void connectionClosed() { + Log.d(TAG, "closing connection"); + mRoster = null; + Intent intent = new Intent(BeemBroadcastReceiver.BEEM_CONNECTION_CLOSED); + intent.putExtra("message", mService.getString(R.string.BeemBroadcastReceiverDisconnect)); + intent.putExtra("normally", true); + mService.sendBroadcast(intent); + mService.stopSelf(); + mApplication.setConnected(false); + } + /** + * {@inheritDoc} + */ + @Override + public void connectionClosedOnError(Exception exception) { + Log.d(TAG, "connectionClosedOnError"); + mRoster = null; + Intent intent = new Intent(BeemBroadcastReceiver.BEEM_CONNECTION_CLOSED); + intent.putExtra("message", exception.getMessage()); + mService.sendBroadcast(intent); + mService.stopSelf(); + mApplication.setConnected(false); + } + + /** + * Connection failed callback. + * @param errorMsg smack failure message + */ + public void connectionFailed(String errorMsg) { + Log.d(TAG, "Connection Failed"); + final int n = mRemoteConnListeners.beginBroadcast(); + + for (int i = 0; i < n; i++) { + IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i); + try { + if (listener != null) + listener.connectionFailed(errorMsg); + } catch (RemoteException e) { + // The RemoteCallbackList will take care of removing the + // dead listeners. + Log.w(TAG, "Error while triggering remote connection listeners", e); + } + } + mRemoteConnListeners.finishBroadcast(); + mService.stopSelf(); + mApplication.setConnected(false); + } + + /** + * {@inheritDoc} + */ @Override - public boolean accept(Packet packet) { - if (packet instanceof Presence) { - Presence pres = (Presence) packet; - if (pres.getType() == Presence.Type.subscribe) - return true; - } - return false; + public void reconnectingIn(int arg0) { + Log.d(TAG, "reconnectingIn"); + final int n = mRemoteConnListeners.beginBroadcast(); + + for (int i = 0; i < n; i++) { + IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i); + try { + if (listener != null) + listener.reconnectingIn(arg0); + } catch (RemoteException e) { + // The RemoteCallbackList will take care of removing the + // dead listeners. + Log.w(TAG, "Error while triggering remote connection listeners", e); + } + } + mRemoteConnListeners.finishBroadcast(); + } + + /** + * {@inheritDoc} + */ + @Override + public void reconnectionFailed(Exception arg0) { + Log.d(TAG, "reconnectionFailed"); + final int r = mRemoteConnListeners.beginBroadcast(); + + for (int i = 0; i < r; i++) { + IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i); + try { + if (listener != null) + listener.reconnectionFailed(); + } catch (RemoteException e) { + // The RemoteCallbackList will take care of removing the + // dead listeners. + Log.w(TAG, "Error while triggering remote connection listeners", e); + } + } + mRemoteConnListeners.finishBroadcast(); } - }; + + /** + * {@inheritDoc} + */ + @Override + public void reconnectionSuccessful() { + Log.d(TAG, "reconnectionSuccessful"); + mApplication.setConnected(true); + PacketFilter filter = new PacketFilter() { + + @Override + public boolean accept(Packet packet) { + if (packet instanceof Presence) { + Presence pres = (Presence) packet; + if (pres.getType() == Presence.Type.subscribe) + return true; + } + return false; + } + }; + + mAdaptee.addPacketListener(new PacketListener() { - mAdaptee.addPacketListener(new PacketListener() { + @Override + public void processPacket(Packet packet) { + String from = packet.getFrom(); + Notification notif = new Notification(android.R.drawable.stat_notify_more, mService.getString( + 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); + notif.setLatestEventInfo(mService, from, mService + .getString(R.string.AcceptContactRequestFrom, from), PendingIntent.getActivity(mService, 0, + intent, PendingIntent.FLAG_ONE_SHOT)); + int id = packet.hashCode(); + mService.sendNotification(id, notif); + } + }, filter); + + final int n = mRemoteConnListeners.beginBroadcast(); + + for (int i = 0; i < n; i++) { + IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i); + try { + if (listener != null) + listener.reconnectionSuccessful(); + } catch (RemoteException e) { + // The RemoteCallbackList will take care of removing the + // dead listeners. + Log.w(TAG, "Error while triggering remote connection listeners", e); + } + } + mRemoteConnListeners.finishBroadcast(); + } + } + + /** + * This PacketListener will set a notification when you got a subscribtion request. + * @author Da Risk + */ + private class SubscribePacketListener implements PacketListener { + + /** + * Constructor. + */ + public SubscribePacketListener() { + } @Override public void processPacket(Packet packet) { - String from = packet.getFrom(); - Notification notif = new Notification(android.R.drawable.stat_notify_more, mService.getString( - 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); - notif.setLatestEventInfo(mService, from, mService - .getString(R.string.AcceptContactRequestFrom, from), PendingIntent.getActivity(mService, 0, - intent, PendingIntent.FLAG_ONE_SHOT)); - int id = packet.hashCode(); - mService.sendNotification(id, notif); + if (!(packet instanceof Presence)) + return; + Presence p = (Presence) packet; + if (p.getType() != Presence.Type.subscribe) + return; + String from = p.getFrom(); + Notification notification = new Notification(android.R.drawable.stat_notify_more, mService.getString( + R.string.AcceptContactRequest, from), System.currentTimeMillis()); + 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, + intent, PendingIntent.FLAG_ONE_SHOT)); + int id = p.hashCode(); + mService.sendNotification(id, notification); } - }, filter); - - final int n = mRemoteConnListeners.beginBroadcast(); - - for (int i = 0; i < n; i++) { - IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i); - try { - if (listener != null) - listener.reconnectionSuccessful(); - } catch (RemoteException e) { - // The RemoteCallbackList will take care of removing the - // dead listeners. - Log.w(TAG, "Error while triggering remote connection listeners", e); - } - } - mRemoteConnListeners.finishBroadcast(); - } - } - - /** - * This PacketListener will set a notification when you got a subscribtion request. - * @author Da Risk - */ - private class SubscribePacketListener implements PacketListener { - - /** - * Constructor. - */ - public SubscribePacketListener() { } - @Override - public void processPacket(Packet packet) { - if (!(packet instanceof Presence)) - return; - Presence p = (Presence) packet; - if (p.getType() != Presence.Type.subscribe) - return; - String from = p.getFrom(); - Notification notification = new Notification(android.R.drawable.stat_notify_more, mService.getString( - R.string.AcceptContactRequest, from), System.currentTimeMillis()); - 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, - intent, PendingIntent.FLAG_ONE_SHOT)); - int id = p.hashCode(); - mService.sendNotification(id, notification); - } - } - } diff -r ac9461be2bd7 -r c067ee9a604c src/com/beem/project/beem/ui/Chat.java --- a/src/com/beem/project/beem/ui/Chat.java Mon Aug 22 22:43:19 2011 +0200 +++ b/src/com/beem/project/beem/ui/Chat.java Fri Oct 14 18:57:07 2011 +0200 @@ -43,930 +43,80 @@ */ package com.beem.project.beem.ui; -import java.io.IOException; -import java.io.InputStream; -import java.text.DateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.jivesoftware.smack.packet.Presence.Mode; -import org.jivesoftware.smack.util.StringUtils; - import android.app.Activity; -import android.app.Dialog; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.ServiceConnection; import android.content.SharedPreferences; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Color; -import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.net.Uri; import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.RemoteException; import android.preference.PreferenceManager; -import android.provider.Contacts; -import android.provider.ContactsContract; -import android.provider.ContactsContract.RawContacts.Entity; -import android.text.util.Linkify; import android.util.Log; import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; -import android.view.View.OnClickListener; import android.view.View.OnKeyListener; -import android.widget.BaseAdapter; -import android.widget.Button; -import android.widget.EditText; import android.widget.ImageView; -import android.widget.ListView; import android.widget.TextView; import com.beem.project.beem.R; -import com.beem.project.beem.providers.AvatarProvider; -import com.beem.project.beem.service.Contact; -import com.beem.project.beem.service.Message; -import com.beem.project.beem.service.PresenceAdapter; -import com.beem.project.beem.service.aidl.IBeemRosterListener; -import com.beem.project.beem.service.aidl.IChat; -import com.beem.project.beem.service.aidl.IChatManager; -import com.beem.project.beem.service.aidl.IChatManagerListener; -import com.beem.project.beem.service.aidl.IMessageListener; -import com.beem.project.beem.service.aidl.IRoster; -import com.beem.project.beem.service.aidl.IXmppFacade; -import com.beem.project.beem.ui.dialogs.builders.ChatList; -import com.beem.project.beem.utils.BeemBroadcastReceiver; -import com.beem.project.beem.utils.Status; /** - * This class represents an activity which allows the user to chat with his/her contacts. - * @author Jean-Manuel Da Silva + * The chat activity for communication with 1 contact. + * + * @author Vincent V. */ public class Chat extends Activity implements OnKeyListener { - private static final String TAG = "Chat"; - private static final Intent SERVICE_INTENT = new Intent(); - static { - SERVICE_INTENT.setComponent(new ComponentName("com.beem.project.beem", "com.beem.project.beem.BeemService")); - } - private Handler mHandler = new Handler(); - - private IRoster mRoster; - private Contact mContact; - - private TextView mContactNameTextView; - private TextView mContactStatusMsgTextView; - private TextView mContactChatState; - private ImageView mContactStatusIcon; - private LayerDrawable mAvatarStatusDrawable; - private ListView mMessagesListView; - private EditText mInputField; - private Button mSendButton; - private final Map mStatusIconsMap = new HashMap(); - - private final List mListMessages = new ArrayList(); - - private IChat mChat; - private IChatManager mChatManager; - private final IMessageListener mMessageListener = new OnMessageListener(); - private final IChatManagerListener mChatManagerListener = new ChatManagerListener(); - private MessagesListAdapter mMessagesListAdapter = new MessagesListAdapter(); - - private final ServiceConnection mConn = new BeemServiceConnection(); - private final BeemBroadcastReceiver mBroadcastReceiver = new BeemBroadcastReceiver(); - private final BeemRosterListener mBeemRosterListener = new BeemRosterListener(); - private IXmppFacade mXmppFacade; - private String mCurrentAvatarId; - private boolean mBinded; - private boolean mCompact; - - /** - * Constructor. - */ - public Chat() { - super(); - } - - /** - * {@inheritDoc}. - */ - @Override - protected void onCreate(Bundle savedBundle) { - super.onCreate(savedBundle); - this.registerReceiver(mBroadcastReceiver, new IntentFilter(BeemBroadcastReceiver.BEEM_CONNECTION_CLOSED)); - SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); - mCompact = settings.getBoolean("settings_chat_compact_key", false); - // UI - if (!mCompact) { - setContentView(R.layout.chat); - mContactNameTextView = (TextView) findViewById(R.id.chat_contact_name); - mContactStatusMsgTextView = (TextView) findViewById(R.id.chat_contact_status_msg); - mContactChatState = (TextView) findViewById(R.id.chat_contact_chat_state); - mContactStatusIcon = (ImageView) findViewById(R.id.chat_contact_status_icon); - mAvatarStatusDrawable = (LayerDrawable) mContactStatusIcon.getDrawable(); - mAvatarStatusDrawable.setLayerInset(1, 36, 36, 0, 0); - } else { - setContentView(R.layout.chat_compact); - } - mMessagesListView = (ListView) findViewById(R.id.chat_messages); - mMessagesListView.setAdapter(mMessagesListAdapter); - mInputField = (EditText) findViewById(R.id.chat_input); - mInputField.setOnKeyListener(this); - mInputField.requestFocus(); - mSendButton = (Button) findViewById(R.id.chat_send_message); - mSendButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - sendMessage(); - } - }); - prepareIconsStatus(); - } - - @Override - protected void onResume() { - super.onResume(); - // When coming from account contact - //TODO : get account from jid - //TODO : if multi account propose select - Uri contactURI = getIntent().getData(); - String jid = contactURI.getPathSegments().get(0); - mContact = new Contact(jid); - if (!mBinded) { - bindService(SERVICE_INTENT, mConn, BIND_AUTO_CREATE); - mBinded = true; - } - } - - /** - * {@inheritDoc}. - */ - @Override - protected void onDestroy() { - super.onDestroy(); - this.unregisterReceiver(mBroadcastReceiver); - } - - /** - * {@inheritDoc}. - */ - @Override - protected void onPause() { - super.onPause(); - try { - if (mChat != null) { - mChat.setOpen(false); - mChat.removeMessageListener(mMessageListener); - } - if (mRoster != null) - mRoster.removeRosterListener(mBeemRosterListener); - if (mChatManager != null) - mChatManager.removeChatCreationListener(mChatManagerListener); - } catch (RemoteException e) { - Log.e(TAG, e.getMessage()); - } - if (mBinded) { - unbindService(mConn); - mBinded = false; - } - mXmppFacade = null; - mRoster = null; - mChat = null; - mChatManager = null; - } - - /** - * {@inheritDoc}. - */ - @Override - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - setIntent(intent); - } - - /** - * {@inheritDoc}. - */ - @Override - protected void onSaveInstanceState(Bundle savedInstanceState) { - super.onSaveInstanceState(savedInstanceState); - } - - /** - * {@inheritDoc}. - */ - @Override - protected void onRestoreInstanceState(Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); - } - - /** - * {@inheritDoc}. - */ - @Override - public final boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.chat, menu); - return true; - } - - /** - * {@inheritDoc}. - */ - @Override - public final boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.chat_menu_contacts_list: - Intent contactListIntent = new Intent(this, ContactList.class); - contactListIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP); - startActivity(contactListIntent); - break; - case R.id.chat_menu_change_chat: - try { - final List openedChats = mChatManager.getOpenedChatList(); - Log.d(TAG, "opened chats = " + openedChats); - Dialog chatList = new ChatList(Chat.this, openedChats).create(); - chatList.show(); - } catch (RemoteException e) { - Log.e(TAG, e.getMessage()); - } - break; - case R.id.chat_menu_close_chat: - try { - mChatManager.destroyChat(mChat); - } catch (RemoteException e) { - Log.e(TAG, e.getMessage()); - } - this.finish(); - break; - default: - return false; - } - return true; - } - - /** - * Change the displayed chat. - * @param contact the targeted contact of the new chat - * @throws RemoteException If a Binder remote-invocation error occurred. - */ - private void changeCurrentChat(Contact contact) throws RemoteException { - if (mChat != null) { - mChat.setOpen(false); - mChat.removeMessageListener(mMessageListener); - } - mChat = mChatManager.getChat(contact); - if (mChat != null) { - mChat.setOpen(true); - mChat.addMessageListener(mMessageListener); - mChatManager.deleteChatNotification(mChat); - } - mContact = mRoster.getContact(contact.getJID()); - String res = contact.getSelectedRes(); - if (mContact == null) - mContact = contact; - if (!"".equals(res)) { - mContact.setSelectedRes(res); - } - updateContactInformations(); - updateContactStatusIcon(); - - playRegisteredTranscript(); - } - - /** - * Get all messages from the current chat and refresh the activity with them. - * @throws RemoteException If a Binder remote-invocation error occurred. - */ - private void playRegisteredTranscript() throws RemoteException { - mListMessages.clear(); - if (mChat != null) { - List msgList = convertMessagesList(mChat.getMessages()); - mListMessages.addAll(msgList); - mMessagesListAdapter.notifyDataSetChanged(); - } - } - - /** - * Convert a list of Message coming from the service to a list of MessageText that can be displayed in UI. - * @param chatMessages the list of Message - * @return a list of message that can be displayed. - */ - private List convertMessagesList(List chatMessages) { - List result = new ArrayList(chatMessages.size()); - String remoteName = mContact.getName(); - String localName = getString(R.string.chat_self); - MessageText lastMessage = null; - - for (Message m : chatMessages) { - String name = remoteName; - String fromBareJid = StringUtils.parseBareAddress(m.getFrom()); - if (m.getType() == Message.MSG_TYPE_ERROR) { - lastMessage = null; - result.add(new MessageText(fromBareJid, name, m.getBody(), true, m.getTimestamp())); - } else if (m.getType() == Message.MSG_TYPE_CHAT) { - if (fromBareJid == null) { //nofrom or from == yours - name = localName; - fromBareJid = ""; - } - - if (m.getBody() != null) { - if (lastMessage == null || !fromBareJid.equals(lastMessage.getBareJid())) { - lastMessage = new MessageText(fromBareJid, name, m.getBody(), false, m.getTimestamp()); - result.add(lastMessage); - } else { - lastMessage.setMessage(lastMessage.getMessage().concat("\n" + m.getBody())); - } - } - } - } - return result; - } - - /** - * {@inheritDoc}. - */ - private final class BeemServiceConnection implements ServiceConnection { + private static final String TAG = "Chat"; + private String mjid; /** * Constructor. */ - public BeemServiceConnection() { - } - - /** - * {@inheritDoc}. - */ - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - mXmppFacade = IXmppFacade.Stub.asInterface(service); - try { - mRoster = mXmppFacade.getRoster(); - if (mRoster != null) - mRoster.addRosterListener(mBeemRosterListener); - mChatManager = mXmppFacade.getChatManager(); - if (mChatManager != null) { - mChatManager.addChatCreationListener(mChatManagerListener); - changeCurrentChat(mContact); - } - } catch (RemoteException e) { - Log.e(TAG, e.getMessage()); - } - } - - /** - * {@inheritDoc}. - */ - @Override - public void onServiceDisconnected(ComponentName name) { - mXmppFacade = null; - try { - mRoster.removeRosterListener(mBeemRosterListener); - mChatManager.removeChatCreationListener(mChatManagerListener); - } catch (RemoteException e) { - Log.e(TAG, e.getMessage()); - } - } - } - - /** - * {@inheritDoc}. - */ - private class BeemRosterListener extends IBeemRosterListener.Stub { - - /** - * Constructor. - */ - public BeemRosterListener() { - } - - /** - * {@inheritDoc}. - */ - @Override - public void onEntriesAdded(List addresses) throws RemoteException { - } - - /** - * {@inheritDoc}. - */ - @Override - public void onEntriesDeleted(List addresses) throws RemoteException { - } - - /** - * {@inheritDoc}. - */ - @Override - public void onEntriesUpdated(List addresses) throws RemoteException { + public Chat() { + super(); } /** * {@inheritDoc}. */ @Override - public void onPresenceChanged(final PresenceAdapter presence) throws RemoteException { - if (mContact.getJID().equals(StringUtils.parseBareAddress(presence.getFrom()))) { - mHandler.post(new Runnable() { - @Override - public void run() { - mContact.setStatus(presence.getStatus()); - mContact.setMsgState(presence.getStatusText()); - updateContactInformations(); - updateContactStatusIcon(); - } - }); - } - } - } - - /** - * {@inheritDoc}. - */ - private class OnMessageListener extends IMessageListener.Stub { - - /** - * Constructor. - */ - public OnMessageListener() { - } - - /** - * {@inheritDoc}. - */ - @Override - public void processMessage(IChat chat, final Message msg) throws RemoteException { - final String fromBareJid = StringUtils.parseBareAddress(msg.getFrom()); - - if (mContact.getJID().equals(fromBareJid)) { - mHandler.post(new Runnable() { - - @Override - public void run() { - if (msg.getType() == Message.MSG_TYPE_ERROR) { - mListMessages.add(new MessageText(fromBareJid, mContact.getName(), msg.getBody(), true, msg - .getTimestamp())); - mMessagesListAdapter.notifyDataSetChanged(); - } else if (msg.getBody() != null) { - MessageText lastMessage = null; - if (mListMessages.size() != 0) - lastMessage = mListMessages.get(mListMessages.size() - 1); - - if (lastMessage != null && lastMessage.getBareJid().equals(fromBareJid)) { - lastMessage.setMessage(lastMessage.getMessage().concat("\n" + msg.getBody())); - lastMessage.setTimestamp(msg.getTimestamp()); - mListMessages.set(mListMessages.size() - 1, lastMessage); - } else if (msg.getBody() != null) - mListMessages.add(new MessageText(fromBareJid, mContact.getName(), msg.getBody(), - false, msg.getTimestamp())); - mMessagesListAdapter.notifyDataSetChanged(); - } - } - }); - } - } - - /** - * {@inheritDoc}. - */ - @Override - public void stateChanged(IChat chat) throws RemoteException { - final String state = chat.getState(); - mHandler.post(new Runnable() { - @Override - public void run() { - String text = null; - if ("active".equals(state)) { - text = Chat.this.getString(R.string.chat_state_active); - } else if ("composing".equals(state)) { - text = Chat.this.getString(R.string.chat_state_composing); - } else if ("gone".equals(state)) { - text = Chat.this.getString(R.string.chat_state_gone); - } else if ("inactive".equals(state)) { - text = Chat.this.getString(R.string.chat_state_inactive); - } else if ("paused".equals(state)) { - text = Chat.this.getString(R.string.chat_state_active); - } - if (!mCompact) - mContactChatState.setText(text); + protected void onCreate(Bundle savedBundle) { + super.onCreate(savedBundle); + // TODO : get account from jid. if multi account propose select + // Intent { act=android.intent.action.SENDTO dat=imto://jabber/jid + // cmp=com.beem.project.beem/.ui.Chat } + Uri contactURI = getIntent().getData(); + mjid = contactURI.getPathSegments().get(0); + + SharedPreferences settings = PreferenceManager + .getDefaultSharedPreferences(this); + boolean isCompact = settings.getBoolean("settings_chat_compact_key", + false); + // UI + if (!isCompact) { + setNormalView(); + } else { + setContentView(R.layout.chat_compact); } - }); - - } - } - /** - * Update the contact informations. - */ - private void updateContactInformations() { - // Check for a contact name update - String name = mContact.getName(); - String res = mContact.getSelectedRes(); - if (!"".equals(res)) - name += "(" + res + ")"; - if (!mCompact) { - if (!(mContactNameTextView.getText().toString().equals(name))) - mContactNameTextView.setText(name); - //Check for a contact status message update - if (!(mContactStatusMsgTextView.getText().toString().equals(mContact.getMsgState()))) { - mContactStatusMsgTextView.setText(mContact.getMsgState()); - Linkify.addLinks(mContactStatusMsgTextView, Linkify.WEB_URLS); - } - } else { - Mode m = Status.getPresenceModeFromStatus(mContact.getStatus()); - if (m == null) - setTitle(getString(R.string.chat_name) + " " + name + " (" - + getString(R.string.contact_status_msg_offline) + ")"); - else - setTitle(getString(R.string.chat_name) + " " + name + " (" + m.name() + ")"); - } - } - - /** - * Update the contact status icon. - */ - private void updateContactStatusIcon() { - if (mCompact) - return; - String id = mContact.getAvatarId(); - if (id == null) - id = ""; - Log.d(TAG, "update contact icon : " + id); - if (!id.equals(mCurrentAvatarId)) { - Drawable avatar = getAvatarDrawable(mContact.getAvatarId()); - mAvatarStatusDrawable.setDrawableByLayerId(R.id.avatar, avatar); - mCurrentAvatarId = id; - } - mContactStatusIcon.setImageLevel(mContact.getStatus()); - } - - /** - * Get a Drawable containing the avatar icon. - * @param avatarId the avatar id to retrieve or null to get default - * @return a Drawable - */ - private Drawable getAvatarDrawable(String avatarId) { - Drawable avatarDrawable = null; - if (avatarId != null) { - Uri uri = AvatarProvider.CONTENT_URI.buildUpon().appendPath(avatarId).build(); - InputStream in = null; - try { - try { - in = getContentResolver().openInputStream(uri); - avatarDrawable = Drawable.createFromStream(in, avatarId); - } finally { - if (in != null) - in.close(); - } - } catch (IOException e) { - Log.w(TAG, "Error while setting the avatar", e); - } - } - if (avatarDrawable == null) - avatarDrawable = getResources().getDrawable(R.drawable.beem_launcher_icon_silver); - return avatarDrawable; - } - - /** - * Prepare the status icons map. - */ - private void prepareIconsStatus() { - mStatusIconsMap.put(Status.CONTACT_STATUS_AVAILABLE, BitmapFactory.decodeResource(getResources(), - android.R.drawable.presence_online)); - mStatusIconsMap.put(Status.CONTACT_STATUS_AVAILABLE_FOR_CHAT, BitmapFactory.decodeResource(getResources(), - android.R.drawable.presence_online)); - mStatusIconsMap.put(Status.CONTACT_STATUS_AWAY, BitmapFactory.decodeResource(getResources(), - android.R.drawable.presence_away)); - mStatusIconsMap.put(Status.CONTACT_STATUS_BUSY, BitmapFactory.decodeResource(getResources(), - android.R.drawable.presence_busy)); - mStatusIconsMap.put(Status.CONTACT_STATUS_DISCONNECT, BitmapFactory.decodeResource(getResources(), - android.R.drawable.presence_offline)); - mStatusIconsMap.put(Status.CONTACT_STATUS_UNAVAILABLE, BitmapFactory.decodeResource(getResources(), - R.drawable.status_requested)); - } - - /** - * {@inheritDoc}. - */ - private class MessagesListAdapter extends BaseAdapter { - - /** - * Constructor. - */ - public MessagesListAdapter() { - } - - /** - * Returns the number of messages contained in the messages list. - * @return The number of messages contained in the messages list. - */ - @Override - public int getCount() { - return mListMessages.size(); - } - - /** - * Return an item from the messages list that is positioned at the position passed by parameter. - * @param position The position of the requested item. - * @return The item from the messages list at the requested position. - */ - @Override - public Object getItem(int position) { - return mListMessages.get(position); - } - - /** - * Return the id of an item from the messages list that is positioned at the position passed by parameter. - * @param position The position of the requested item. - * @return The id of an item from the messages list at the requested position. - */ - @Override - public long getItemId(int position) { - return position; } - /** - * Return the view of an item from the messages list. - * @param position The position of the requested item. - * @param convertView The old view to reuse if possible. - * @param parent The parent that this view will eventually be attached to. - * @return A View corresponding to the data at the specified position. - */ - public View getView(int position, View convertView, ViewGroup parent) { - View sv; - if (convertView == null) { - LayoutInflater inflater = Chat.this.getLayoutInflater(); - sv = inflater.inflate(R.layout.chat_msg_row, null); - } else { - sv = convertView; - } - DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM); - MessageText msg = mListMessages.get(position); - TextView msgName = (TextView) sv.findViewById(R.id.chatmessagename); - msgName.setText(msg.getName()); - msgName.setTextColor(Color.WHITE); - msgName.setError(null); - TextView msgText = (TextView) sv.findViewById(R.id.chatmessagetext); - msgText.setText(msg.getMessage()); - registerForContextMenu(msgText); - TextView msgDate = (TextView) sv.findViewById(R.id.chatmessagedate); - String date = df.format(msg.getTimestamp()); - msgDate.setText(date); - if (msg.isError()) { - String err = getString(R.string.chat_error); - msgName.setText(err); - msgName.setTextColor(Color.RED); - msgName.setError(err); - } - return sv; - } - } - - /** - * Class which simplify an Xmpp text message. - * @author Jean-Manuel Da Silva - */ - private class MessageText { - private String mBareJid; - private String mName; - private String mMessage; - private boolean mIsError; - private Date mTimestamp; - - /** - * Constructor. - * @param bareJid A String containing the bare JID of the message's author. - * @param name A String containing the name of the message's author. - * @param message A String containing the message. - */ - public MessageText(final String bareJid, final String name, final String message) { - mBareJid = bareJid; - mName = name; - mMessage = message; - mIsError = false; - } - - /** - * Constructor. - * @param bareJid A String containing the bare JID of the message's author. - * @param name A String containing the name of the message's author. - * @param message A String containing the message. - * @param isError if the message is an error message. - */ - public MessageText(final String bareJid, final String name, final String message, final boolean isError) { - mBareJid = bareJid; - mName = name; - mMessage = message; - mIsError = isError; - } - - /** - * Constructor. - * @param bareJid A String containing the bare JID of the message's author. - * @param name A String containing the name of the message's author. - * @param message A String containing the message. - * @param isError if the message is an error message. - * @param date the time of the message. - */ - public MessageText(final String bareJid, final String name, final String message, final boolean isError, - Date date) { - mBareJid = bareJid; - mName = name; - mMessage = message; - mIsError = isError; - mTimestamp = date; - } - - /** - * JID attribute accessor. - * @return A String containing the bare JID of the message's author. - */ - public String getBareJid() { - return mBareJid; - } - - /** - * Name attribute accessor. - * @return A String containing the name of the message's author. - */ - public String getName() { - return mName; - } + private void setNormalView() { + Log.d(TAG, "Jid : " + mjid); + setContentView(R.layout.chat); + TextView ContactNameTextView = (TextView) findViewById(R.id.chat_contact_name); + ContactNameTextView.setText(mjid); + TextView ContactStatusMsgTextView = (TextView) findViewById(R.id.chat_contact_status_msg); + TextView ContactChatStateTextView = (TextView) findViewById(R.id.chat_contact_chat_state); + ImageView ContactStatusIcon = (ImageView) findViewById(R.id.chat_contact_status_icon); + LayerDrawable AvatarStatusDrawable = (LayerDrawable) ContactStatusIcon + .getDrawable(); + AvatarStatusDrawable.setLayerInset(1, 36, 36, 0, 0); - /** - * Message attribute accessor. - * @return A String containing the message. - */ - public String getMessage() { - return mMessage; - } - - /** - * JID attribute mutator. - * @param bareJid A String containing the author's bare JID of the message. - */ - @SuppressWarnings("unused") - public void setBareJid(String bareJid) { - mBareJid = bareJid; - } - - /** - * Name attribute mutator. - * @param name A String containing the author's name of the message. - */ - @SuppressWarnings("unused") - public void setName(String name) { - mName = name; - } - - /** - * Message attribute mutator. - * @param message A String containing a message. - */ - public void setMessage(String message) { - mMessage = message; - } - - /** - * Get the message type. - * @return true if the message is an error message. - */ - public boolean isError() { - return mIsError; - } - - /** - * Set the Date of the message. - * @param date date of the message. - */ - public void setTimestamp(Date date) { - mTimestamp = date; - } - - /** - * Get the Date of the message. - * @return if it is a delayed message get the date the message was sended. - */ - public Date getTimestamp() { - return mTimestamp; - } - - } - - /** - * {@inheritDoc}. - */ - @Override - public boolean onKey(View v, int keyCode, KeyEvent event) { - if (event.getAction() == KeyEvent.ACTION_DOWN) { - switch (keyCode) { - case KeyEvent.KEYCODE_ENTER: - sendMessage(); - return true; - default: - return false; - } - } - return false; - } - - /** - * Send an XMPP message. - */ - private void sendMessage() { - final String inputContent = mInputField.getText().toString(); - - if (!"".equals(inputContent)) { - Message msgToSend = new Message(mContact.getJIDWithRes(), Message.MSG_TYPE_CHAT); - msgToSend.setBody(inputContent); - - try { - if (mChat == null) { - mChat = mChatManager.createChat(mContact, mMessageListener); - mChat.setOpen(true); - } - mChat.sendMessage(msgToSend); - } catch (RemoteException e) { - Log.e(TAG, e.getMessage()); - } - - final String self = getString(R.string.chat_self); - MessageText lastMessage = null; - if (mListMessages.size() != 0) - lastMessage = mListMessages.get(mListMessages.size() - 1); - - if (lastMessage != null && lastMessage.getName().equals(self)) { - lastMessage.setMessage(lastMessage.getMessage().concat("\n" + inputContent)); - lastMessage.setTimestamp(new Date()); - } else - mListMessages.add(new MessageText(self, self, inputContent, false, new Date())); - mMessagesListAdapter.notifyDataSetChanged(); - mInputField.setText(null); - } - } - - /** - * This class is in charge of getting the new chat in the activity if someone talk to you. - */ - private class ChatManagerListener extends IChatManagerListener.Stub { - - /** - * Constructor. - */ - public ChatManagerListener() { } @Override - public void chatCreated(IChat chat, boolean locally) { - if (locally) - return; - try { - String contactJid = mContact.getJIDWithRes(); - String chatJid = chat.getParticipant().getJIDWithRes(); - if (chatJid.equals(contactJid)) { - // This should not be happened but to be sure - if (mChat != null) { - mChat.setOpen(false); - mChat.removeMessageListener(mMessageListener); - } - mChat = chat; - mChat.setOpen(true); - mChat.addMessageListener(mMessageListener); - mChatManager.deleteChatNotification(mChat); - } - } catch (RemoteException ex) { - Log.e(TAG, "A remote exception occurs during the creation of a chat", ex); - } + public boolean onKey(View v, int keyCode, KeyEvent event) { + return false; } - } - - public class MyReceiver extends BroadcastReceiver { - - @Override - public void onReceive(Context context, Intent intent) { - Context c = getApplicationContext(); - Intent sendIntent = new Intent(); - if (intent.getAction().equals(Intent.ACTION_SENDTO)) { - sendIntent.setClass(c, Chat.class); - context.startActivity(sendIntent); - } - } - } } diff -r ac9461be2bd7 -r c067ee9a604c src/com/beem/project/beem/ui/ContactList.java --- a/src/com/beem/project/beem/ui/ContactList.java Mon Aug 22 22:43:19 2011 +0200 +++ b/src/com/beem/project/beem/ui/ContactList.java Fri Oct 14 18:57:07 2011 +0200 @@ -42,11 +42,9 @@ */ package com.beem.project.beem.ui; -import java.util.ArrayList; +import java.net.URI; import java.util.Comparator; -import java.util.HashMap; import java.util.List; -import java.util.Map; import android.app.Activity; import android.app.Dialog; @@ -55,8 +53,8 @@ import android.content.Intent; import android.content.SharedPreferences; import android.database.Cursor; +import android.net.Uri; import android.os.Bundle; -import android.os.Handler; import android.os.RemoteException; import android.preference.PreferenceManager; import android.provider.ContactsContract; @@ -89,455 +87,492 @@ import com.beem.project.beem.ui.dialogs.builders.ChatList; import com.beem.project.beem.ui.dialogs.builders.DeleteContact; import com.beem.project.beem.ui.dialogs.builders.ResendSubscription; -import com.beem.project.beem.utils.BeemBroadcastReceiver; /** * The contact list activity displays the roster of the user. + * + * @author Vincent V. */ public class ContactList extends Activity { - private static final Intent SERVICE_INTENT = new Intent(); - static { - SERVICE_INTENT.setComponent(new ComponentName("com.beem.project.beem", "com.beem.project.beem.BeemService")); - } - - private static final String SETTINGS_HIDDEN_CONTACT = "settings_key_hidden_contact"; - private static final String TAG = "ContactList"; - - /** - * Map containing a list of the different contacts of a given group. Each list is a @{link SortedList} so there is - * no need to sort it again. - */ - - private final BeemContactListOnClick mOnContactClick = new BeemContactListOnClick(); - - private final ComparatorContactListByStatusAndName mComparator = new ComparatorContactListByStatusAndName(); - private List mListContact; - private String mSelectedGroup; - private IRoster mRoster; - private Contact mSelectedContact; - private IXmppFacade mXmppFacade; - private IChatManager mChatManager; - private SharedPreferences mSettings; - private LayoutInflater mInflater; - private BeemBanner mAdapterBanner; - private BeemContactList mAdapterContactList; - private boolean mBinded; - - private String mAccountName; - - /** - * Constructor. - */ - public ContactList() { - } - - @Override - protected void onCreate(Bundle saveBundle) { - super.onCreate(saveBundle); - mSettings = PreferenceManager.getDefaultSharedPreferences(this); - setContentView(R.layout.contactlist); - - mInflater = getLayoutInflater(); - mAccountName = getIntent().getExtras().getString(BeemIntent.EXTRA_ACCOUNT); - - //Get Groups list - final Cursor cursorGroup = getContentResolver().query(ContactsContract.Groups.CONTENT_URI, - new String[] { ContactsContract.Groups._ID, ContactsContract.Groups.TITLE }, ContactsContract.Groups.ACCOUNT_NAME + "=?", new String[] {mAccountName}, null); - mAdapterBanner = new BeemBanner(this, R.layout.contactlist_group, cursorGroup, - new String[] { ContactsContract.Groups.TITLE }, new int[] { R.id.contactlist_group }); - - //Get Contacts list - //TODO: Get contact list by account - final Cursor cursorContact = getContentResolver().query( - ContactsContract.Contacts.CONTENT_URI, - new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, - ContactsContract.Contacts.CONTACT_STATUS }, null, null, null); - //TODO: GetAvatar + Presence - mAdapterContactList = new BeemContactList(this, R.layout.contactlistcontact, cursorContact, new String[] { - ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, - ContactsContract.Contacts.CONTACT_STATUS }, new int[] { R.id.avatar, R.id.contactlistpseudo, - R.id.contactlistmsgperso }); - - ListView listView = (ListView) findViewById(R.id.contactlist); - listView.setOnItemClickListener(mOnContactClick); - registerForContextMenu(listView); - listView.setAdapter(mAdapterContactList); - Log.e(TAG, "ONCREATE"); - } - - @Override - protected void onResume() { - super.onResume(); - if (!mSettings.getBoolean("settings_key_hide_groups", false)) - showGroups(); - else - hideGroups(); - } - - @Override - public final boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.contact_list, menu); - return true; - } - - @Override - public final boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.contact_list_menu_settings: - Intent i = new Intent(this, Settings.class); - i.putExtra("account_name", mAccountName); - startActivity(i); - return true; - case R.id.contact_list_menu_add_contact: - startActivity(new Intent(ContactList.this, AddContact.class)); - return true; - case R.id.menu_change_status: - startActivity(new Intent(ContactList.this, ChangeStatus.class)); - return true; - case R.id.contact_list_menu_chatlist: - List openedChats; - try { - openedChats = mChatManager.getOpenedChatList(); - Log.d(TAG, "opened chats = " + openedChats); - Dialog chatList = new ChatList(ContactList.this, openedChats).create(); - chatList.show(); - } catch (RemoteException e) { - e.printStackTrace(); - } - return true; - case R.id.menu_disconnect: - stopService(SERVICE_INTENT); - finish(); - default: - return false; - } - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { - super.onCreateContextMenu(menu, v, menuInfo); - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.contactlist_context, menu); - AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; - Contact c = mListContact.get(info.position); - try { - mSelectedContact = mRoster.getContact(c.getJID()); - } catch (RemoteException e) { - e.printStackTrace(); - } - menu.setHeaderTitle(mSelectedContact.getJID()); - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - Intent in; - boolean result; - if (mSelectedContact != null) { - switch (item.getItemId()) { - case R.id.contact_list_context_menu_chat_item: - List res = mSelectedContact.getMRes(); - if (res.isEmpty()) { - result = false; - break; - } - for (String resv : res) { - in = new Intent(this, Chat.class); - in.setData(mSelectedContact.toUri(resv)); - item.getSubMenu().add(resv).setIntent(in); - } - result = true; - break; - case R.id.contact_list_context_menu_call_item: - try { - mXmppFacade.call(mSelectedContact.getJID() + "/psi"); - result = true; - } catch (RemoteException e) { - e.printStackTrace(); - } - result = true; - break; - case R.id.contact_list_context_menu_user_info: - item.getSubMenu().setHeaderTitle(mSelectedContact.getJID()); - result = true; - break; - case R.id.contact_list_context_menu_userinfo_alias: - Dialog alias = new Alias(ContactList.this, mRoster, mSelectedContact).create(); - alias.show(); - result = true; - break; - case R.id.contact_list_context_menu_userinfo_group: - in = new Intent(this, GroupList.class); - in.putExtra("contact", mSelectedContact); - startActivity(in); - result = true; - break; - case R.id.contact_list_context_menu_userinfo_subscription: - Dialog subscription = new ResendSubscription(ContactList.this, mXmppFacade, mSelectedContact) - .create(); - subscription.show(); - result = true; - break; - case R.id.contact_list_context_menu_userinfo_block: - result = true; - break; - case R.id.contact_list_context_menu_userinfo_delete: - Dialog delete = new DeleteContact(ContactList.this, mRoster, mSelectedContact).create(); - delete.show(); - result = true; - break; - default: - result = super.onContextItemSelected(item); - break; - } - return result; - } - return super.onContextItemSelected(item); - } - - /** - * Build and display the contact list. - * @param group name of the contact list. - */ - private void buildContactList(String group) { - - } - - /** - * Show the groups view. - */ - private void showGroups() { - - ViewStub stub = (ViewStub) findViewById(R.id.contactlist_stub); - if (stub != null) { - View v = stub.inflate(); - Gallery g = (Gallery) v.findViewById(R.id.contactlist_banner); - g.setOnItemClickListener(new OnItemClickGroupName()); - g.setAdapter(mAdapterBanner); - g.setSelection(0); - } else { - ((LinearLayout) findViewById(R.id.contactlist_groupstub)).setVisibility(View.VISIBLE); - Gallery g = (Gallery) findViewById(R.id.contactlist_banner); - g.setSelection(0); - } - } - - /** - * Hide the groups view. - */ - private void hideGroups() { - View v = findViewById(R.id.contactlist_groupstub); - if (v != null) - v.setVisibility(View.GONE); - } - - /** - * Adapter contact list. - */ - private static class BeemContactList extends SimpleCursorAdapter implements Filterable { - - private Context mContext; - private int mLayout; - - public BeemContactList(Context context, int layout, Cursor c, String[] from, int[] to) { - super(context, layout, c, from, to); - mContext = context; - mLayout = layout; + private static final Intent SERVICE_INTENT = new Intent(); + static { + SERVICE_INTENT.setComponent(new ComponentName("com.beem.project.beem", + "com.beem.project.beem.BeemService")); } - @Override - public View newView(Context context, Cursor cursor, ViewGroup parent) { - final LayoutInflater inflater = LayoutInflater.from(mContext); - return inflater.inflate(mLayout, parent, false); - } - - @Override - public void bindView(View view, Context context, Cursor cursor) { - String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME)); - TextView nameText = (TextView) view.findViewById(R.id.contactlistpseudo); - if (nameText != null) { - nameText.setText(name); - } - - String msgStatus = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.CONTACT_STATUS)); - TextView msgStatusText = (TextView) view.findViewById(R.id.contactlistmsgperso); - if (msgStatusText != null) { - msgStatusText.setText(msgStatus); - } - - // ImageView img = (ImageView) view.findViewById(R.id.avatar); - // String avatarId = curContact.getAvatarId(); - // int contactStatus = curContact.getStatus(); - // Drawable avatar = getAvatarStatusDrawable(avatarId); - // img.setImageDrawable(avatar); - // img.setImageLevel(contactStatus); - } - - // @Override - // public Filter getFilter() { - // return mFilter; - // } - - /** - * Get a LayerDrawable containing the avatar and the status icon. The status icon will change with the level of - * the drawable. - * @param avatarId the avatar id to retrieve or null to get default - * @return a LayerDrawable - */ - // private Drawable getAvatarStatusDrawable(String avatarId) { - // Drawable avatarDrawable = null; - // if (avatarId != null) { - // Uri uri = AvatarProvider.CONTENT_URI.buildUpon().appendPath(avatarId).build(); - // InputStream in = null; - // try { - // try { - // in = getContentResolver().openInputStream(uri); - // avatarDrawable = Drawable.createFromStream(in, avatarId); - // } finally { - // if (in != null) - // in.close(); - // } - // } catch (IOException e) { - // Log.w(TAG, "Error while setting the avatar", e); - // } - // } - // if (avatarDrawable == null) - // avatarDrawable = getResources().getDrawable(R.drawable.beem_launcher_icon_silver); - // LayerDrawable ld = (LayerDrawable) getResources().getDrawable(R.drawable.avatar_status); - // ld.setLayerInset(1, 36, 36, 0, 0); - // ld.setDrawableByLayerId(R.id.avatar, avatarDrawable); - // return ld; - // } + private static final String SETTINGS_HIDDEN_CONTACT = "settings_key_hidden_contact"; + private static final String TAG = "ContactList"; /** - * A Filter which select Contact to display by searching in ther Jid. + * Map containing a list of the different contacts of a given group. Each + * list is a @{link SortedList} so there is no need to sort it again. */ - // private class ContactFilter extends Filter { - // - // /** - // * Create a ContactFilter. - // */ - // public ContactFilter() { - // } - // - // @Override - // protected Filter.FilterResults performFiltering(CharSequence constraint) { - // Log.d(TAG, "performFiltering"); - // List result = mListContact; - // if (constraint.length() > 0) { - // result = new LinkedList(); - // for (Contact c : mContactOnGroup.get(mSelectedGroup)) { - // if (c.getJID().contains(constraint)) - // result.add(c); - // } - // } - // Filter.FilterResults fr = new Filter.FilterResults(); - // fr.values = result; - // fr.count = result.size(); - // return fr; - // } - // - // @Override - // protected void publishResults(CharSequence constraint, Filter.FilterResults results) { - // Log.d(TAG, "publishResults"); - // List contacts = (List) results.values; - // mListContact = contacts; - // notifyDataSetChanged(); - // } - // } - } - /** - * Adapter banner group list. - */ - private static class BeemBanner extends SimpleCursorAdapter { - - private Context mContext; - private int mLayout; - - public BeemBanner(Context context, int layout, Cursor c, String[] from, int[] to) { - super(context, layout, c, from, to); - mContext = context; - mLayout = layout; - } - - @Override - public View newView(Context context, Cursor cursor, ViewGroup parent) { - final LayoutInflater inflater = LayoutInflater.from(mContext); - return inflater.inflate(mLayout, parent, false); - } + private final BeemContactListOnClick mOnContactClick = new BeemContactListOnClick(); - @Override - public void bindView(View view, Context context, Cursor cursor) { - String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Groups.TITLE)); - TextView nameText = (TextView) view.findViewById(R.id.contactlist_group); - if (nameText != null) { - nameText.setText(name); - } - } - } - - /** - * Comparator Contact by status and name. - */ - private static class ComparatorContactListByStatusAndName implements Comparator { - /** - * Constructor. - */ - public ComparatorContactListByStatusAndName() { - } + private final ComparatorContactListByStatusAndName mComparator = new ComparatorContactListByStatusAndName(); + private IRoster mRoster; + private Contact mSelectedContact; + private IXmppFacade mXmppFacade; + private IChatManager mChatManager; + private SharedPreferences mSettings; + private BeemBanner mAdapterBanner; + private BeemContactList mAdapterContactList; - @Override - public int compare(T c1, T c2) { - if (((Contact) c1).getStatus() < ((Contact) c2).getStatus()) { - return 1; - } else if (((Contact) c1).getStatus() > ((Contact) c2).getStatus()) { - return -1; - } else - return ((Contact) c1).getName().compareToIgnoreCase(((Contact) c2).getName()); - } - } - - /** - * Event simple click on item of the contact list. - */ - private class BeemContactListOnClick implements OnItemClickListener { - /** - * Constructor. - */ - public BeemContactListOnClick() { - } - - /** - * {@inheritDoc} - */ - @Override - public void onItemClick(AdapterView arg0, View v, int pos, long lpos) { - Contact c = mListContact.get(pos); - Intent i = new Intent(ContactList.this, Chat.class); - i.setData(c.toUri()); - startActivity(i); - } - } - - /** - * Event simple click on middle group name. - */ - private class OnItemClickGroupName implements OnItemClickListener { + private String mAccountName; /** * Constructor. */ - public OnItemClickGroupName() { + public ContactList() { + } + + @Override + protected void onCreate(Bundle saveBundle) { + super.onCreate(saveBundle); + mSettings = PreferenceManager.getDefaultSharedPreferences(this); + setContentView(R.layout.contactlist); + + mAccountName = getIntent().getExtras().getString( + BeemIntent.EXTRA_ACCOUNT); + + // Get Groups list + final Cursor cursorGroup = getContentResolver().query( + ContactsContract.Groups.CONTENT_URI, + new String[] { ContactsContract.Groups._ID, + ContactsContract.Groups.TITLE }, + ContactsContract.Groups.ACCOUNT_NAME + "=?", + new String[] { mAccountName }, null); + mAdapterBanner = new BeemBanner(this, R.layout.contactlist_group, + cursorGroup, new String[] { ContactsContract.Groups.TITLE }, + new int[] { R.id.contactlist_group }); + + // Get Contacts list + // TODO: Get contact list by account + final Cursor cursorContact = getContentResolver().query( + ContactsContract.RawContacts.CONTENT_URI, + new String[] { ContactsContract.RawContacts._ID, + ContactsContract.RawContacts.SOURCE_ID }, + ContactsContract.RawContacts.ACCOUNT_NAME + "=?", + new String[] { mAccountName }, null); + // TODO: GetAvatar + Presence + mAdapterContactList = new BeemContactList(this, + R.layout.contactlistcontact, cursorContact, new String[] { + ContactsContract.RawContacts._ID, + ContactsContract.RawContacts.SOURCE_ID }, new int[] { + R.id.avatar, R.id.contactlistpseudo, + R.id.contactlistmsgperso }); + + ListView listView = (ListView) findViewById(R.id.contactlist); + listView.setOnItemClickListener(mOnContactClick); + registerForContextMenu(listView); + listView.setAdapter(mAdapterContactList); + Log.e(TAG, "ONCREATE"); + } + + @Override + protected void onResume() { + super.onResume(); + if (!mSettings.getBoolean("settings_key_hide_groups", false)) + showGroups(); + else + hideGroups(); + } + + @Override + public final boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.contact_list, menu); + return true; + } + + @Override + public final boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.contact_list_menu_settings: + Intent i = new Intent(this, Settings.class); + i.putExtra("account_name", mAccountName); + startActivity(i); + return true; + case R.id.contact_list_menu_add_contact: + startActivity(new Intent(ContactList.this, AddContact.class)); + return true; + case R.id.menu_change_status: + startActivity(new Intent(ContactList.this, ChangeStatus.class)); + return true; + case R.id.contact_list_menu_chatlist: + List openedChats; + try { + openedChats = mChatManager.getOpenedChatList(); + Log.d(TAG, "opened chats = " + openedChats); + Dialog chatList = new ChatList(ContactList.this, openedChats) + .create(); + chatList.show(); + } catch (RemoteException e) { + e.printStackTrace(); + } + return true; + case R.id.menu_disconnect: + stopService(SERVICE_INTENT); + finish(); + default: + return false; + } + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenu.ContextMenuInfo menuInfo) { + super.onCreateContextMenu(menu, v, menuInfo); + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.contactlist_context, menu); + AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; + // Contact c = new Contact(); + // try { + // mSelectedContact = mRoster.getContact(c.getJID()); + // } catch (RemoteException e) { + // e.printStackTrace(); + // } + // menu.setHeaderTitle(mSelectedContact.getJID()); } @Override - public void onItemClick(AdapterView arg0, View v, int i, long l) { - // String group = mListGroup.get(i); - // buildContactList(group); + public boolean onContextItemSelected(MenuItem item) { + Intent in; + boolean result; + if (mSelectedContact != null) { + switch (item.getItemId()) { + case R.id.contact_list_context_menu_chat_item: + List res = mSelectedContact.getMRes(); + if (res.isEmpty()) { + result = false; + break; + } + for (String resv : res) { + in = new Intent(this, Chat.class); + in.setData(mSelectedContact.toUri(resv)); + item.getSubMenu().add(resv).setIntent(in); + } + result = true; + break; + case R.id.contact_list_context_menu_call_item: + try { + mXmppFacade.call(mSelectedContact.getJID() + "/psi"); + result = true; + } catch (RemoteException e) { + e.printStackTrace(); + } + result = true; + break; + case R.id.contact_list_context_menu_user_info: + item.getSubMenu().setHeaderTitle(mSelectedContact.getJID()); + result = true; + break; + case R.id.contact_list_context_menu_userinfo_alias: + Dialog alias = new Alias(ContactList.this, mRoster, + mSelectedContact).create(); + alias.show(); + result = true; + break; + case R.id.contact_list_context_menu_userinfo_group: + in = new Intent(this, GroupList.class); + in.putExtra("contact", mSelectedContact); + startActivity(in); + result = true; + break; + case R.id.contact_list_context_menu_userinfo_subscription: + Dialog subscription = new ResendSubscription(ContactList.this, + mXmppFacade, mSelectedContact).create(); + subscription.show(); + result = true; + break; + case R.id.contact_list_context_menu_userinfo_block: + result = true; + break; + case R.id.contact_list_context_menu_userinfo_delete: + Dialog delete = new DeleteContact(ContactList.this, mRoster, + mSelectedContact).create(); + delete.show(); + result = true; + break; + default: + result = super.onContextItemSelected(item); + break; + } + return result; + } + return super.onContextItemSelected(item); + } + + /** + * Build and display the contact list. + * + * @param group + * name of the contact list. + */ + private void buildContactList(String group) { + + } + + /** + * Show the groups view. + */ + private void showGroups() { + + ViewStub stub = (ViewStub) findViewById(R.id.contactlist_stub); + if (stub != null) { + View v = stub.inflate(); + Gallery g = (Gallery) v.findViewById(R.id.contactlist_banner); + g.setOnItemClickListener(new OnItemClickGroupName()); + g.setAdapter(mAdapterBanner); + g.setSelection(0); + } else { + ((LinearLayout) findViewById(R.id.contactlist_groupstub)) + .setVisibility(View.VISIBLE); + Gallery g = (Gallery) findViewById(R.id.contactlist_banner); + g.setSelection(0); + } + } + + /** + * Hide the groups view. + */ + private void hideGroups() { + View v = findViewById(R.id.contactlist_groupstub); + if (v != null) + v.setVisibility(View.GONE); } - } + + /** + * Adapter contact list. + */ + private static class BeemContactList extends SimpleCursorAdapter implements + Filterable { + + private Context mContext; + private int mLayout; + + public BeemContactList(Context context, int layout, Cursor c, + String[] from, int[] to) { + super(context, layout, c, from, to); + mContext = context; + mLayout = layout; + } + + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + final LayoutInflater inflater = LayoutInflater.from(mContext); + return inflater.inflate(mLayout, parent, false); + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + String name = cursor.getString(cursor + .getColumnIndex(ContactsContract.RawContacts.SOURCE_ID)); + String jid = cursor.getString(cursor + .getColumnIndex(ContactsContract.RawContacts.SOURCE_ID)); + TextView nameText = (TextView) view + .findViewById(R.id.contactlistpseudo); + if (nameText != null) { + nameText.setText(name); + } + + // String msgStatus = cursor.getString(cursor + // .getColumnIndex(ContactsContract.Contacts.CONTACT_STATUS)); + // TextView msgStatusText = (TextView) view + // .findViewById(R.id.contactlistmsgperso); + // if (msgStatusText != null) { + // msgStatusText.setText(msgStatus); + // } + + view.setTag(jid); + + // ImageView img = (ImageView) view.findViewById(R.id.avatar); + // String avatarId = curContact.getAvatarId(); + // int contactStatus = curContact.getStatus(); + // Drawable avatar = getAvatarStatusDrawable(avatarId); + // img.setImageDrawable(avatar); + // img.setImageLevel(contactStatus); + } + + // @Override + // public Filter getFilter() { + // return mFilter; + // } + + /** + * Get a LayerDrawable containing the avatar and the status icon. The + * status icon will change with the level of the drawable. + * + * @param avatarId + * the avatar id to retrieve or null to get default + * @return a LayerDrawable + */ + // private Drawable getAvatarStatusDrawable(String avatarId) { + // Drawable avatarDrawable = null; + // if (avatarId != null) { + // Uri uri = + // AvatarProvider.CONTENT_URI.buildUpon().appendPath(avatarId).build(); + // InputStream in = null; + // try { + // try { + // in = getContentResolver().openInputStream(uri); + // avatarDrawable = Drawable.createFromStream(in, avatarId); + // } finally { + // if (in != null) + // in.close(); + // } + // } catch (IOException e) { + // Log.w(TAG, "Error while setting the avatar", e); + // } + // } + // if (avatarDrawable == null) + // avatarDrawable = + // getResources().getDrawable(R.drawable.beem_launcher_icon_silver); + // LayerDrawable ld = (LayerDrawable) + // getResources().getDrawable(R.drawable.avatar_status); + // ld.setLayerInset(1, 36, 36, 0, 0); + // ld.setDrawableByLayerId(R.id.avatar, avatarDrawable); + // return ld; + // } + + /** + * A Filter which select Contact to display by searching in ther Jid. + */ + // private class ContactFilter extends Filter { + // + // /** + // * Create a ContactFilter. + // */ + // public ContactFilter() { + // } + // + // @Override + // protected Filter.FilterResults performFiltering(CharSequence + // constraint) { + // Log.d(TAG, "performFiltering"); + // List result = mListContact; + // if (constraint.length() > 0) { + // result = new LinkedList(); + // for (Contact c : mContactOnGroup.get(mSelectedGroup)) { + // if (c.getJID().contains(constraint)) + // result.add(c); + // } + // } + // Filter.FilterResults fr = new Filter.FilterResults(); + // fr.values = result; + // fr.count = result.size(); + // return fr; + // } + // + // @Override + // protected void publishResults(CharSequence constraint, + // Filter.FilterResults results) { + // Log.d(TAG, "publishResults"); + // List contacts = (List) results.values; + // mListContact = contacts; + // notifyDataSetChanged(); + // } + // } + } + + /** + * Adapter banner group list. + */ + private static class BeemBanner extends SimpleCursorAdapter { + + private Context mContext; + private int mLayout; + + public BeemBanner(Context context, int layout, Cursor c, String[] from, + int[] to) { + super(context, layout, c, from, to); + mContext = context; + mLayout = layout; + } + + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + final LayoutInflater inflater = LayoutInflater.from(mContext); + return inflater.inflate(mLayout, parent, false); + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + String name = cursor.getString(cursor + .getColumnIndex(ContactsContract.Groups.TITLE)); + TextView nameText = (TextView) view + .findViewById(R.id.contactlist_group); + if (nameText != null) { + nameText.setText(name); + } + } + } + + /** + * Comparator Contact by status and name. + */ + private static class ComparatorContactListByStatusAndName implements + Comparator { + /** + * Constructor. + */ + public ComparatorContactListByStatusAndName() { + } + + @Override + public int compare(T c1, T c2) { + if (((Contact) c1).getStatus() < ((Contact) c2).getStatus()) { + return 1; + } else if (((Contact) c1).getStatus() > ((Contact) c2).getStatus()) { + return -1; + } else + return ((Contact) c1).getName().compareToIgnoreCase( + ((Contact) c2).getName()); + } + } + + /** + * Event simple click on item of the contact list. + */ + private class BeemContactListOnClick implements OnItemClickListener { + /** + * Constructor. + */ + public BeemContactListOnClick() { + } + + /** + * {@inheritDoc} + */ + @Override + public void onItemClick(AdapterView arg0, View v, int pos, long lpos) { + String jid = (String) v.getTag(); + Log.i(TAG, "OnClick Jid :" + jid); + Intent i = new Intent(ContactList.this, Chat.class); + i.setData(Uri.parse("imto://jabber/" + jid)); + startActivity(i); + } + } + + /** + * Event simple click on middle group name. + */ + private class OnItemClickGroupName implements OnItemClickListener { + + /** + * Constructor. + */ + public OnItemClickGroupName() { + } + + @Override + public void onItemClick(AdapterView arg0, View v, int i, long l) { + // String group = mListGroup.get(i); + // buildContactList(group); + } + } }