--- a/res/layout/contactlist.xml Fri Mar 27 18:12:43 2009 +0100
+++ b/res/layout/contactlist.xml Wed Apr 01 19:24:05 2009 +0200
@@ -1,24 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <ImageView android:id="@+id/avatar"
- android:src="@drawable/avatar"
- android:paddingLeft="50sp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-
- <TextView android:id="@+id/textchild1"
- android:textSize="16sp"
- android:paddingLeft="100sp"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"/>
-
- <TextView android:id="@+id/textchild2"
- android:textSize="16sp"
- android:paddingLeft="100sp"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"/>
- </LinearLayout>
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <ExpandableListView android:id="@+id/android:list"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_weight="1" />
+
+ <TextView android:id="@+id/android:empty"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" android:text="Non connecte" />
+
+</LinearLayout>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/res/layout/contactlistcontact.xml Wed Apr 01 19:24:05 2009 +0200
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="50sp"
+ android:gravity="center_vertical" >
+
+ <ImageView android:id="@+id/avatar"
+ android:layout_width="70px"
+ android:layout_height="40sp" />
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="40sp">
+
+ <TextView android:id="@+id/textchild1"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="20sp" />
+
+ <TextView android:id="@+id/textchild2"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
--- a/res/layout/contactlistgroup.xml Fri Mar 27 18:12:43 2009 +0100
+++ b/res/layout/contactlistgroup.xml Wed Apr 01 19:24:05 2009 +0200
@@ -1,16 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="50sp"
+ android:paddingTop="5sp"
+ android:gravity="center_vertical">
- <TextView android:id="@+id/textgroup"
- android:height="50sp"
- android:textSize="20sp"
- android:textStyle="bold"
- android:paddingTop="10sp"
- android:paddingLeft="40sp"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" />
+ <TextView android:id="@+id/textgroup"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="40sp" />
- </LinearLayout>
+ <TextView android:id="@+id/rowText2"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+
+</LinearLayout>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/beem/project/beem/BeemApplication.java Wed Apr 01 19:24:05 2009 +0200
@@ -0,0 +1,124 @@
+/**
+ *
+ */
+package com.beem.project.beem;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import android.app.Activity;
+import android.app.Application;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+
+import com.beem.project.beem.service.aidl.IXMPPFacade;
+
+/**
+ * @author darisk
+ */
+public class BeemApplication extends Application {
+
+ private IXMPPFacade mFacade;
+
+ private Context mApplicationContext;
+ private Resources mPrivateResources;
+ private static BeemApplication mBeemApp;
+ private List<Message> mQueue = new LinkedList<Message>();
+ private boolean mIsConnected;
+
+ public static BeemApplication getApplication(Activity activity) {
+ if (mBeemApp == null) {
+ mBeemApp = new BeemApplication();
+ mBeemApp.mApplicationContext = activity.getApplication();
+ mBeemApp.mPrivateResources = activity.getResources();
+ mBeemApp.onCreate();
+ }
+ return mBeemApp;
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ // TODO Auto-generated method stub
+ super.onConfigurationChanged(newConfig);
+ }
+
+ @Override
+ public void onCreate() {
+ // TODO Auto-generated method stub
+ super.onCreate();
+ mFacade = null;
+ }
+
+ @Override
+ public void onLowMemory() {
+ // TODO Auto-generated method stub
+ super.onLowMemory();
+ }
+
+ @Override
+ public void onTerminate() {
+ // TODO Auto-generated method stub
+ super.onTerminate();
+ }
+
+ public synchronized void startBeemService() {
+ if (!mIsConnected) {
+ // Intent intent = new Intent(this, BeemService.class);
+ Intent intent = new Intent();
+ intent.setComponent(new ComponentName("com.beem.project.beem", "com.beem.project.beem.BeemService"));
+ mApplicationContext.startService(intent);
+ mApplicationContext.bindService(intent, mServConn, BIND_AUTO_CREATE);
+ mIsConnected = true;
+ }
+ }
+
+ private ServiceConnection mServConn = new ServiceConnection() {
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ mFacade = null;
+ mIsConnected = false;
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ // TODO Auto-generated method stub
+ mFacade = IXMPPFacade.Stub.asInterface(service);
+ synchronized (mQueue) {
+ for (Message msg : mQueue) {
+ msg.sendToTarget();
+ }
+ mQueue.clear();
+ }
+ }
+ };
+
+ public synchronized void stopBeemService() {
+ Intent intent = new Intent(this, BeemService.class);
+ mApplicationContext.unbindService(mServConn);
+ mApplicationContext.stopService(intent);
+ }
+
+ public IXMPPFacade getXmppFacade() {
+ return mFacade;
+ }
+
+ public void callWhenServiceConnected(Handler target, Runnable callback) {
+ Message msg = Message.obtain(target, callback);
+ if (!mIsConnected) {
+ msg.sendToTarget();
+ } else {
+ startBeemService();
+ synchronized (mQueue) {
+ mQueue.add(msg);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/beem/project/beem/provider/Beem.java Wed Apr 01 19:24:05 2009 +0200
@@ -0,0 +1,157 @@
+package com.beem.project.beem.provider;
+
+import android.net.Uri;
+import android.provider.BaseColumns;
+
+/**
+ * Convenience definitions for BEEM's providers
+ */
+public final class Beem {
+
+ public final static String AUTHORITY = "com.beem.project.provider";
+
+ public final static String DB_NAME = "beem.db";
+ public final static int DB_VERSION = 2;
+
+ public final static String USERS_TABLE_NAME = "users";
+ public final static String CONTACTS_TABLE_NAME = "contacts";
+
+ /**
+ * Constructor
+ */
+ private Beem() {}
+
+
+ /**
+ * Users table
+ */
+ public static final class Users implements BaseColumns {
+
+ /**
+ * The query used to create the table
+ */
+ public final static String QUERY_CREATE =
+ "CREATE TABLE " + Beem.USERS_TABLE_NAME + " ("
+ + Users._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ + Users.JUSERNAME + " TEXT,"
+ + Users.DATE_CREATED + " INTEGER,"
+ + Users.DATE_MODIFIED + " INTEGER"
+ + ");";
+
+ /**
+ * The content:// style URL for Contacts table
+ */
+ public final static Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/users");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of users.
+ */
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.beem.project.user";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} sub-directory of a single user.
+ */
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.beem.project.user";
+
+ /**
+ * The default sort order for this table
+ */
+ public final static String DEFAULT_SORT_ORDER = "_id ASC";
+
+ /**
+ * The Jabber username of the user
+ * <P>Type: TEXT</P>
+ */
+ public final static String JUSERNAME = "username";
+
+ /**
+ * The timestamp for when the user was created
+ * <P>Type: INTEGER (long from System.curentTimeMillis())</P>
+ */
+ public final static String DATE_CREATED = "created";
+
+ /**
+ * The timestamp for when the user was last modified
+ * <P>Type: INTEGER (long from System.curentTimeMillis())</P>
+ */
+ public final static String DATE_MODIFIED = "modified";
+ }
+
+
+ /**
+ * Contacts table
+ */
+ public static final class Contacts implements BaseColumns {
+
+ /**
+ * The query used to create the table
+ */
+ public final static String QUERY_CREATE =
+ "CREATE TABLE " + Beem.CONTACTS_TABLE_NAME + " ("
+ + Contacts._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ + Contacts.UID + " INTEGER, "
+ + Contacts.JID + " INTEGER,"
+ + Contacts.NICKNAME + " TEXT,"
+ + Contacts.ALIAS + " TEXT,"
+ + Contacts.DATE_CREATED + " INTEGER,"
+ + Contacts.DATE_MODIFIED + " INTEGER"
+ + ");";
+
+ /**
+ * The content:// style URL for Contacts table
+ */
+ public final static Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/contacts");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of contacts.
+ */
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.beem.project.contact";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} sub-directory of a single contact.
+ */
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.beem.project.contact";
+
+ /**
+ * The default sort order for this table
+ */
+ public final static String DEFAULT_SORT_ORDER = "nickname ASC";
+
+ /**
+ * The user id having the contact
+ * <P>Type: INTEGER</P>
+ */
+ public final static String UID = "uid";
+
+ /**
+ * The JabberID of the contact
+ * <P>Type: INTEGER</P>
+ */
+ public final static String JID = "jid";
+
+ /**
+ * The nickname of the contact
+ * <P>Type: TEXT</P>
+ */
+ public final static String NICKNAME = "nickname";
+
+ /**
+ * The alias of the contact
+ * <P>Type: TEXT</P>
+ */
+ public final static String ALIAS = "alias";
+
+ /**
+ * The timestamp for when the contact was created
+ * <P>Type: INTEGER (long from System.curentTimeMillis())</P>
+ */
+ public final static String DATE_CREATED = "created";
+
+ /**
+ * The timestamp for when the contact was last modified
+ * <P>Type: INTEGER (long from System.curentTimeMillis())</P>
+ */
+ public final static String DATE_MODIFIED = "modified";
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/beem/project/beem/provider/BeemDatabaseHelper.java Wed Apr 01 19:24:05 2009 +0200
@@ -0,0 +1,34 @@
+package com.beem.project.beem.provider;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+public class BeemDatabaseHelper extends SQLiteOpenHelper {
+
+ private String tag;
+ private String tableName;
+ private String creationQuery;
+
+ public BeemDatabaseHelper(Context context, String tag, String tableName, String creationQuery) {
+ super(context, Beem.DB_NAME, null, Beem.DB_VERSION);
+
+ this.tag = tag;
+ this.tableName = tableName;
+ this.creationQuery = creationQuery;
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL(this.creationQuery);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ Log.w(this.tag, "Upgrading database from version " + oldVersion + " to "
+ + newVersion + ", which will destroy all old data");
+ db.execSQL("DROP TABLE IF EXISTS " + this.tableName + ";");
+ onCreate(db);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/beem/project/beem/provider/ContactProvider.java Wed Apr 01 19:24:05 2009 +0200
@@ -0,0 +1,210 @@
+/**
+ *
+ */
+package com.beem.project.beem.provider;
+
+import java.util.HashMap;
+
+import android.content.ContentProvider;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.text.TextUtils;
+
+/**
+ * @author dasilvj
+ *
+ */
+public class ContactProvider extends ContentProvider {
+
+ private final static String TAG = "ContactProvider";
+
+ private static HashMap<String, String> sContactsProjectionMap;
+
+ private static final int CONTACTS = 1;
+ private static final int CONTACT_ID = 2;
+
+ private static final UriMatcher sUriMatcher;
+ private BeemDatabaseHelper mOpenHelper;
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ int count;
+
+ switch (sUriMatcher.match(uri)) {
+ case CONTACTS:
+ count = db.delete(Beem.CONTACTS_TABLE_NAME, selection, selectionArgs);
+ break;
+
+ case CONTACT_ID:
+ String contactId = uri.getPathSegments().get(1);
+ count = db.delete(Beem.CONTACTS_TABLE_NAME, Beem.Contacts._ID + "=" + contactId
+ + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);
+ break;
+
+ 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 CONTACTS:
+ return Beem.Contacts.CONTENT_TYPE;
+
+ case CONTACT_ID:
+ return Beem.Contacts.CONTENT_ITEM_TYPE;
+
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues initialValues) {
+ // Validate the requested uri
+ if (sUriMatcher.match(uri) != CONTACTS) {
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+
+ ContentValues values;
+ if (initialValues != null) {
+ values = new ContentValues(initialValues);
+ } else {
+ values = new ContentValues();
+ }
+
+ Long now = Long.valueOf(System.currentTimeMillis());
+
+ // Make sure that the fields are all set
+ if (values.containsKey(Beem.Contacts.UID) == false) {
+ // TODO :: Must check that the UID exists using UserProvider
+ throw new SQLException("No UID specified. Failed to insert row into " + uri);
+ }
+
+ if (values.containsKey(Beem.Contacts.JID) == false) {
+ values.put(Beem.Contacts.JID, "");
+ }
+
+ if (values.containsKey(Beem.Contacts.NICKNAME) == false) {
+ values.put(Beem.Contacts.JID, "");
+ }
+
+ if (values.containsKey(Beem.Contacts.ALIAS) == false) {
+ values.put(Beem.Contacts.JID, "");
+ }
+
+ if (values.containsKey(Beem.Contacts.DATE_CREATED) == false) {
+ values.put(Beem.Contacts.DATE_CREATED, now);
+ }
+
+ if (values.containsKey(Beem.Contacts.DATE_MODIFIED) == false) {
+ values.put(Beem.Contacts.DATE_MODIFIED, now);
+ }
+
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ long rowId = db.insert(Beem.CONTACTS_TABLE_NAME, Beem.Contacts._ID, values);
+ if (rowId > 0) {
+ Uri contactUri = ContentUris.withAppendedId(Beem.Contacts.CONTENT_URI, rowId);
+ getContext().getContentResolver().notifyChange(contactUri, null);
+ return contactUri;
+ }
+
+ throw new SQLException("Failed to insert row into " + uri);
+ }
+
+ @Override
+ public boolean onCreate() {
+ mOpenHelper = new BeemDatabaseHelper(getContext(), TAG, Beem.CONTACTS_TABLE_NAME, Beem.Contacts.QUERY_CREATE);
+ 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 CONTACTS:
+ qb.setTables(Beem.CONTACTS_TABLE_NAME);
+ qb.setProjectionMap(sContactsProjectionMap);
+ break;
+
+ case CONTACT_ID:
+ qb.setTables(Beem.USERS_TABLE_NAME);
+ qb.setProjectionMap(sContactsProjectionMap);
+ qb.appendWhere(Beem.Contacts._ID + "=" + uri.getPathSegments().get(1));
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+
+ // If no sort order is specified use the default
+ String orderBy;
+ if (TextUtils.isEmpty(sortOrder)) {
+ orderBy = Beem.Contacts.DEFAULT_SORT_ORDER;
+ } else {
+ orderBy = sortOrder;
+ }
+
+ // Get the database and run the query
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
+
+ // Tell the cursor what uri to watch, so it knows when its source data changes
+ c.setNotificationUri(getContext().getContentResolver(), uri);
+ return c;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection,
+ String[] selectionArgs) {
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ int count;
+
+ switch (sUriMatcher.match(uri)) {
+ case CONTACTS:
+ count = db.update(Beem.CONTACTS_TABLE_NAME, values, selection, selectionArgs);
+ break;
+
+ case CONTACT_ID:
+ String contactId = uri.getPathSegments().get(1);
+ count = db.update(Beem.CONTACTS_TABLE_NAME, values, Beem.Contacts._ID + "=" + contactId
+ + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+
+ getContext().getContentResolver().notifyChange(uri, null);
+ return count;
+ }
+
+ static {
+ sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+ sUriMatcher.addURI(Beem.AUTHORITY, "contacts", CONTACTS);
+ sUriMatcher.addURI(Beem.AUTHORITY, "contacts/#", CONTACT_ID);
+
+ sContactsProjectionMap = new HashMap<String, String>();
+ sContactsProjectionMap.put(Beem.Contacts._ID, Beem.Contacts._ID);
+ sContactsProjectionMap.put(Beem.Contacts.UID, Beem.Contacts.UID);
+ sContactsProjectionMap.put(Beem.Contacts.JID, Beem.Contacts.JID);
+ sContactsProjectionMap.put(Beem.Contacts.NICKNAME, Beem.Contacts.NICKNAME);
+ sContactsProjectionMap.put(Beem.Contacts.ALIAS, Beem.Contacts.ALIAS);
+ sContactsProjectionMap.put(Beem.Contacts.DATE_CREATED, Beem.Contacts.DATE_CREATED);
+ sContactsProjectionMap.put(Beem.Contacts.DATE_MODIFIED, Beem.Contacts.DATE_MODIFIED);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/beem/project/beem/provider/UserProvider.java Wed Apr 01 19:24:05 2009 +0200
@@ -0,0 +1,186 @@
+package com.beem.project.beem.provider;
+
+import java.util.HashMap;
+
+import android.content.ContentProvider;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.text.TextUtils;
+
+public class UserProvider extends ContentProvider {
+
+ private final static String TAG = "UserProvider";
+
+ private static HashMap<String, String> sUsersProjectionMap;
+
+ private static final int USERS = 1;
+ private static final int USER_ID = 2;
+
+ private static final UriMatcher sUriMatcher;
+ private BeemDatabaseHelper mOpenHelper;
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ int count;
+
+ switch (sUriMatcher.match(uri)) {
+ case USERS:
+ count = db.delete(Beem.USERS_TABLE_NAME, selection, selectionArgs);
+ break;
+
+ case USER_ID:
+ String userID = uri.getPathSegments().get(1);
+ count = db.delete(Beem.USERS_TABLE_NAME, Beem.Users._ID + "=" + userID
+ + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);
+ break;
+
+ 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 USERS:
+ return Beem.Users.CONTENT_TYPE;
+
+ case USER_ID:
+ return Beem.Users.CONTENT_ITEM_TYPE;
+
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues initialValues) {
+ // Validate the requested uri
+ if (sUriMatcher.match(uri) != USERS) {
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+
+ ContentValues values;
+ if (initialValues != null) {
+ values = new ContentValues(initialValues);
+ } else {
+ values = new ContentValues();
+ }
+
+ Long now = Long.valueOf(System.currentTimeMillis());
+
+ // Make sure that the fields are all set
+ if (values.containsKey(Beem.Users.JUSERNAME) == false) {
+ throw new SQLException("No JUSERNAME specified. Failed to insert row into " + uri);
+ }
+
+ if (values.containsKey(Beem.Users.DATE_CREATED) == false) {
+ values.put(Beem.Users.DATE_CREATED, now);
+ }
+
+ if (values.containsKey(Beem.Users.DATE_MODIFIED) == false) {
+ values.put(Beem.Users.DATE_MODIFIED, now);
+ }
+
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ long rowId = db.insert(Beem.USERS_TABLE_NAME, Beem.Users._ID, values);
+ if (rowId > 0) {
+ Uri userUri = ContentUris.withAppendedId(Beem.Users.CONTENT_URI, rowId);
+ getContext().getContentResolver().notifyChange(userUri, null);
+ return userUri;
+ }
+
+ throw new SQLException("Failed to insert row into " + uri);
+ }
+
+ @Override
+ public boolean onCreate() {
+ mOpenHelper = new BeemDatabaseHelper(getContext(), TAG, Beem.USERS_TABLE_NAME, Beem.Users.QUERY_CREATE);
+ 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 USERS:
+ qb.setTables(Beem.USERS_TABLE_NAME);
+ qb.setProjectionMap(sUsersProjectionMap);
+ break;
+
+ case USER_ID:
+ qb.setTables(Beem.USERS_TABLE_NAME);
+ qb.setProjectionMap(sUsersProjectionMap);
+ qb.appendWhere(Beem.Users._ID + "=" + uri.getPathSegments().get(1));
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+
+ // If no sort order is specified use the default
+ String orderBy;
+ if (TextUtils.isEmpty(sortOrder)) {
+ orderBy = Beem.Users.DEFAULT_SORT_ORDER;
+ } else {
+ orderBy = sortOrder;
+ }
+
+ // Get the database and run the query
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
+
+ // Tell the cursor what uri to watch, so it knows when its source data changes
+ c.setNotificationUri(getContext().getContentResolver(), uri);
+ return c;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection,
+ String[] selectionArgs) {
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ int count;
+
+ switch (sUriMatcher.match(uri)) {
+ case USERS:
+ count = db.update(Beem.USERS_TABLE_NAME, values, selection, selectionArgs);
+ break;
+
+ case USER_ID:
+ String userId = uri.getPathSegments().get(1);
+ count = db.update(Beem.USERS_TABLE_NAME, values, Beem.Users._ID + "=" + userId
+ + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+
+ getContext().getContentResolver().notifyChange(uri, null);
+ return count;
+ }
+
+ static {
+ sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+ sUriMatcher.addURI(Beem.AUTHORITY, "users", USERS);
+ sUriMatcher.addURI(Beem.AUTHORITY, "users/#", USER_ID);
+
+ sUsersProjectionMap = new HashMap<String, String>();
+ sUsersProjectionMap.put(Beem.Users._ID, Beem.Users._ID);
+ sUsersProjectionMap.put(Beem.Users.JUSERNAME, Beem.Users.JUSERNAME);
+ sUsersProjectionMap.put(Beem.Users.DATE_CREATED, Beem.Users.DATE_CREATED);
+ sUsersProjectionMap.put(Beem.Users.DATE_MODIFIED, Beem.Users.DATE_MODIFIED);
+ }
+}
--- a/src/com/beem/project/beem/ui/Beem.java Fri Mar 27 18:12:43 2009 +0100
+++ b/src/com/beem/project/beem/ui/Beem.java Wed Apr 01 19:24:05 2009 +0200
@@ -12,6 +12,7 @@
import android.view.View.OnClickListener;
import android.widget.Button;
+import com.beem.project.beem.BeemApplication;
import com.beem.project.beem.R;
/**
@@ -23,6 +24,7 @@
private BeemDialogSettings mDialog;
private Button mButton;
private Handler mHandler;
+ private BeemApplication mBeemApplication;
/**
* Default constructor.
@@ -40,6 +42,7 @@
@Override
public final void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mBeemApplication = BeemApplication.getApplication(this);
setContentView(R.layout.beem);
mSettings = getSharedPreferences(
getString(R.string.PreferenceFileName), MODE_PRIVATE);
@@ -52,7 +55,7 @@
if (mButton.getText() == getString(R.string.BeemCreateAccount))
mDialog.show();
else
- startActivity(new Intent(Beem.this, ContactList.class));
+ startActivity(new Intent(Beem.this, ContactList.class));
}
});
showJID();
--- a/src/com/beem/project/beem/ui/ContactList.java Fri Mar 27 18:12:43 2009 +0100
+++ b/src/com/beem/project/beem/ui/ContactList.java Wed Apr 01 19:24:05 2009 +0200
@@ -4,91 +4,154 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-
import android.app.ExpandableListActivity;
-import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
-import android.content.ServiceConnection;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import android.os.IBinder;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Log;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
+import android.widget.ImageView;
import android.widget.SimpleExpandableListAdapter;
-
-import com.beem.project.beem.BeemService;
+import android.widget.TextView;
+import com.beem.project.beem.BeemApplication;
import com.beem.project.beem.R;
+import com.beem.project.beem.service.Contact;
import com.beem.project.beem.service.aidl.IXMPPFacade;
public class ContactList extends ExpandableListActivity {
+ private static final String TAG = "CONTACTLIST_ACT";
private IXMPPFacade mService = null;
+ private Handler mHandler;
+ private BeemApplication mBeemApplication;
+
+ @Override
+ public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
+ startActivity(new Intent(this, SendIM.class));
+ return true;
+
+ };
@Override
public void onCreate(Bundle saveBundle) {
super.onCreate(saveBundle);
- bindService(new Intent(this, BeemService.class), mConnection,
- BIND_AUTO_CREATE | BIND_DEBUG_UNBIND);
- showContactList();
+ mHandler = new Handler();
+ mBeemApplication = BeemApplication.getApplication(this);
+
}
@Override
- public boolean onChildClick(ExpandableListView parent,
- View v, int groupPosition, int childPosition, long id) {
- startActivity(new Intent(this, SendIM.class));
- return true;
+ public void onStart() {
+ super.onStart();
+ mBeemApplication.startBeemService();
+ mBeemApplication.callWhenServiceConnected(mHandler, new Runnable() {
+ @Override
+ public void run() {
+ mService = mBeemApplication.getXmppFacade();
+ try {
+ showContactList(mService.getRoster().getContactList(), mService.getRoster().getContactList());
+ } catch (RemoteException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
- };
+ }
+ });
+ }
- private void showContactList() {
+ private void showContactList(List<Contact> listGroup, List<Contact> listContact) {
ExpandableListAdapter Adapter;
-
List<Map<String, String>> groupData = new ArrayList<Map<String, String>>();
List<List<Map<String, String>>> childData = new ArrayList<List<Map<String, String>>>();
- for (int i = 0; i < 2; i++) {
+ if (listGroup.size() == 0)
+ listGroup.add(new Contact());
+ for (int i = 0; i < listGroup.size(); i++) {
Map<String, String> curGroupMap = new HashMap<String, String>();
+
groupData.add(curGroupMap);
- curGroupMap.put("NAME", "Group " + i);
+ curGroupMap.put("NAME", "Default");
List<Map<String, String>> children = new ArrayList<Map<String, String>>();
- for (int j = 0; j < 5; j++) {
+ for (int j = 0; j < listContact.size(); ++j) {
Map<String, String> curChildMap = new HashMap<String, String>();
children.add(curChildMap);
- curChildMap.put("NAME CHILD", "Child " + j);
+ curChildMap.put("NAME_CHILD", listContact.get(j).getJID());
curChildMap.put("MSG", "Taper votre message perso");
}
childData.add(children);
}
- Adapter = new SimpleExpandableListAdapter(this, groupData,
- R.layout.contactlistgroup, new String[] { "NAME" },
- new int[] { R.id.textgroup }, childData, R.layout.contactlist,
- new String[] { "NAME CHILD", "MSG" }, new int[] {
- R.id.textchild1, R.id.textchild2 });
+ Adapter = new ContactExpandableListAdapter(this, groupData, R.layout.contactlistgroup, new String[] { "NAME" },
+ new int[] { R.id.textgroup }, childData, R.layout.contactlistcontact, new String[] { "NAME_CHILD", "MSG" },
+ new int[] { R.id.textchild1, R.id.textchild2, R.id.avatar });
setListAdapter(Adapter);
}
- private ServiceConnection mConnection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- mService = IXMPPFacade.Stub.asInterface(service);
- /*
- * mService.getGroupList(); mService.getContactList();
- */
- showContactList();
+ /**
+ * A simple adapter which allows you to bind data to specific Views defined within the layout of an Expandable Lists
+ * children (Implement getGroupView() to define the layout of parents)
+ */
+ public class ContactExpandableListAdapter extends SimpleExpandableListAdapter {
+
+ private List<? extends List<? extends Map<String, ?>>> mChildData;
+ private String[] mChildFrom;
+ private int[] mChildTo;
+
+ public ContactExpandableListAdapter(Context context, List<? extends Map<String, ?>> groupData, int groupLayout,
+ String[] groupFrom, int[] groupTo, List<? extends List<? extends Map<String, ?>>> childData,
+ int childLayout, String[] childFrom, int[] childTo) {
+ super(context, groupData, groupLayout, groupFrom, groupTo, childData, childLayout, childFrom, childTo);
+
+ mChildData = childData;
+ mChildFrom = childFrom;
+ mChildTo = childTo;
+
}
@Override
- public void onServiceDisconnected(ComponentName name) {
+ public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView,
+ ViewGroup parent) {
+
+ View v;
+ if (convertView == null) {
+ v = newChildView(isLastChild, parent);
+ } else {
+ v = convertView;
+ }
+ bindView(v, mChildData.get(groupPosition).get(childPosition), mChildFrom, mChildTo, groupPosition,
+ childPosition);
+ return v;
}
- };
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- unbindService(mConnection);
+ // This method binds my data to the Views specified in the child
+ // xmllayout
+ private void bindView(View view, Map<String, ?> data, String[] from, int[] to, int groupPosition,
+ int childPosition) {
+ // Apply TextViews
+ TextView v1 = (TextView) view.findViewById(to[0]);
+ if (v1 != null) {
+ Log.i("CONTACT LIST 1", (String) data.get(from[0]) + " " + to[0]);
+ v1.setText((String) data.get(from[0]));
+ }
+ TextView v2 = (TextView) view.findViewById(to[1]);
+ if (v2 != null) {
+ Log.i("CONTACT LIST 2", (String) data.get(from[1]) + " " + to[1]);
+ v2.setText((String) data.get(from[1]));
+ }
+ // Apply ImageView
+ ImageView imgV = (ImageView) view.findViewById(to[2]);
+ if (imgV != null) {
+ Drawable avatar = (Drawable) getResources().getDrawable(R.drawable.avatar);
+ imgV.setImageDrawable(avatar);
+ }
+ }
}
}