diff --git a/res/layout/dialog_contact_details.xml b/res/layout/dialog_contact_details.xml
index f52f7ba2d..00da4396f 100644
--- a/res/layout/dialog_contact_details.xml
+++ b/res/layout/dialog_contact_details.xml
@@ -7,23 +7,24 @@
-
+ android:scaleType="fitXY"/>
+ android:layout_alignParentTop="true"
+ android:paddingLeft="8dp">
@@ -51,8 +53,8 @@
android:textStyle="bold"
android:gravity="center_vertical"
android:layout_below="@+id/details_jidbox"
- android:layout_toRightOf="@id/details_contact_picture"
- android:paddingLeft="8dp"/>
+ android:layout_toRightOf="@id/details_contact_badge"
+ android:paddingLeft="16dp"/>
getContacts(Account account) {
List list = new ArrayList();
SQLiteDatabase db = this.getReadableDatabase();
- String args[] = {account.getUuid()};
- Cursor cursor = db.query(Contact.TABLENAME, null, Contact.ACCOUNT+"=?", args, null,
- null, null);
+ Cursor cursor;
+ if (account==null) {
+ cursor = db.query(Contact.TABLENAME, null, null, null, null,
+ null, null);
+ } else {
+ String args[] = {account.getUuid()};
+ cursor = db.query(Contact.TABLENAME, null, Contact.ACCOUNT+"=?", args, null,
+ null, null);
+ }
while (cursor.moveToNext()) {
list.add(Contact.fromCursor(cursor));
}
diff --git a/src/de/gultsch/chat/services/XmppConnectionService.java b/src/de/gultsch/chat/services/XmppConnectionService.java
index a1db28dde..55380c12c 100644
--- a/src/de/gultsch/chat/services/XmppConnectionService.java
+++ b/src/de/gultsch/chat/services/XmppConnectionService.java
@@ -13,6 +13,8 @@ import de.gultsch.chat.persistance.DatabaseBackend;
import de.gultsch.chat.ui.OnAccountListChangedListener;
import de.gultsch.chat.ui.OnConversationListChangedListener;
import de.gultsch.chat.ui.OnRosterFetchedListener;
+import de.gultsch.chat.utils.OnPhoneContactsLoadedListener;
+import de.gultsch.chat.utils.PhoneHelper;
import de.gultsch.chat.utils.UIHelper;
import de.gultsch.chat.xml.Element;
import de.gultsch.chat.xmpp.IqPacket;
@@ -76,7 +78,7 @@ public class XmppConnectionService extends Service {
status = Message.STATUS_SEND;
} else {
return; // massage has no body and is not carbon. just
- // skip
+ // skip
}
if (forwarded != null) {
Element message = forwarded.findChild("message");
@@ -258,98 +260,112 @@ public class XmppConnectionService extends Service {
public void updateRoster(final Account account,
final OnRosterFetchedListener listener) {
- final Hashtable phoneContacts = new Hashtable();
- final List contacts = new ArrayList();
+ PhoneHelper.loadPhoneContacts(this,
+ new OnPhoneContactsLoadedListener() {
- final String[] PROJECTION = new String[] {
- ContactsContract.Data.CONTACT_ID,
- ContactsContract.Data.DISPLAY_NAME,
- ContactsContract.Data.PHOTO_THUMBNAIL_URI,
- ContactsContract.CommonDataKinds.Im.DATA };
+ @Override
+ public void onPhoneContactsLoaded(
+ final Hashtable phoneContacts) {
+ IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
+ Element query = new Element("query");
+ query.setAttribute("xmlns", "jabber:iq:roster");
+ query.setAttribute("ver", "");
+ iqPacket.addChild(query);
+ connections.get(account).sendIqPacket(iqPacket,
+ new OnIqPacketReceived() {
- final String SELECTION = "(" + ContactsContract.Data.MIMETYPE + "=\""
- + ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE
- + "\") AND (" + ContactsContract.CommonDataKinds.Im.PROTOCOL
- + "=\"" + ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER
- + "\")";
+ @Override
+ public void onIqPacketReceived(
+ Account account, IqPacket packet) {
+ List contacts = new ArrayList();
+ Element roster = packet
+ .findChild("query");
+ if (roster != null) {
+ for (Element item : roster
+ .getChildren()) {
+ Contact contact;
+ String name = item
+ .getAttribute("name");
+ String jid = item
+ .getAttribute("jid");
+ if (phoneContacts
+ .containsKey(jid)) {
+ Bundle phoneContact = phoneContacts
+ .get(jid);
+ String systemAccount = phoneContact
+ .getInt("phoneid")
+ + "#"
+ + phoneContact
+ .getString("lookup");
+ contact = new Contact(
+ account,
+ phoneContact
+ .getString("displayname"),
+ jid,
+ phoneContact
+ .getString("photouri"));
+ contact.setSystemAccount(systemAccount);
+ } else {
+ if (name == null) {
+ name = jid.split("@")[0];
+ }
+ contact = new Contact(
+ account, name, jid,
+ null);
- CursorLoader mCursorLoader = new CursorLoader(this,
- ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, null,
- null);
- mCursorLoader.registerListener(0, new OnLoadCompleteListener() {
-
- @Override
- public void onLoadComplete(Loader arg0, Cursor cursor) {
- while (cursor.moveToNext()) {
- Bundle contact = new Bundle();
- contact.putInt("phoneid", cursor.getInt(cursor
- .getColumnIndex(ContactsContract.Data.CONTACT_ID)));
- contact.putString(
- "displayname",
- cursor.getString(cursor
- .getColumnIndex(ContactsContract.Data.DISPLAY_NAME)));
- contact.putString(
- "photouri",
- cursor.getString(cursor
- .getColumnIndex(ContactsContract.Data.PHOTO_THUMBNAIL_URI)));
- phoneContacts.put(
- cursor.getString(cursor
- .getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA)),
- contact);
- }
- IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
- Element query = new Element("query");
- query.setAttribute("xmlns", "jabber:iq:roster");
- query.setAttribute("ver", "");
- iqPacket.addChild(query);
- connections.get(account).sendIqPacket(iqPacket,
- new OnIqPacketReceived() {
-
- @Override
- public void onIqPacketReceived(Account account,
- IqPacket packet) {
- Element roster = packet.findChild("query");
- if (roster != null) {
- for (Element item : roster.getChildren()) {
- Contact contact;
- String name = item.getAttribute("name");
- String jid = item.getAttribute("jid");
- if (phoneContacts.containsKey(jid)) {
- Bundle phoneContact = phoneContacts
- .get(jid);
- contact = new Contact(
- account,
- phoneContact
- .getString("displayname"),
- jid,
- phoneContact
- .getString("photouri"));
- contact.setSystemAccount(phoneContact
- .getInt("phoneid"));
- } else {
- if (name == null) {
- name = jid.split("@")[0];
+ }
+ contact.setAccount(account);
+ contact.setSubscription(item
+ .getAttribute("subscription"));
+ contacts.add(contact);
+ }
+ databaseBackend
+ .mergeContacts(contacts);
+ if (listener != null) {
+ listener.onRosterFetched(contacts);
}
- contact = new Contact(account,
- name, jid, null);
-
}
- contact.setAccount(account);
- contact.setSubscription(item
- .getAttribute("subscription"));
- contacts.add(contact);
- }
- databaseBackend.mergeContacts(contacts);
- if (listener != null) {
- listener.onRosterFetched(contacts);
}
+ });
+
+ }
+ });
+ }
+
+ public void mergePhoneContactsWithRoster() {
+ PhoneHelper.loadPhoneContacts(this,
+ new OnPhoneContactsLoadedListener() {
+ @Override
+ public void onPhoneContactsLoaded(
+ Hashtable phoneContacts) {
+ List contacts = databaseBackend
+ .getContacts(null);
+ for (int i = 0; i < contacts.size(); ++i) {
+ Contact contact = contacts.get(i);
+ if (phoneContacts.containsKey(contact.getJid())) {
+ Bundle phoneContact = phoneContacts.get(contact
+ .getJid());
+ String systemAccount = phoneContact
+ .getInt("phoneid")
+ + "#"
+ + phoneContact.getString("lookup");
+ contact.setSystemAccount(systemAccount);
+ contact.setPhotoUri(phoneContact
+ .getString("photouri"));
+ contact.setDisplayName(phoneContact
+ .getString("displayname"));
+ databaseBackend.updateContact(contact);
+ } else {
+ if ((contact.getSystemAccount() != null)
+ || (contact.getProfilePhoto() != null)) {
+ contact.setSystemAccount(null);
+ contact.setPhotoUri(null);
+ databaseBackend.updateContact(contact);
}
}
- });
-
- }
- });
- mCursorLoader.startLoading();
+ }
+ }
+ });
}
public void addConversation(Conversation conversation) {
diff --git a/src/de/gultsch/chat/ui/ConversationActivity.java b/src/de/gultsch/chat/ui/ConversationActivity.java
index 37a988fba..c5c03b12c 100644
--- a/src/de/gultsch/chat/ui/ConversationActivity.java
+++ b/src/de/gultsch/chat/ui/ConversationActivity.java
@@ -37,6 +37,8 @@ public class ConversationActivity extends XmppActivity {
public static final String VIEW_CONVERSATION = "viewConversation";
public static final String CONVERSATION = "conversationUuid";
+
+ public static final int INSERT_CONTACT = 0x9889;
protected SlidingPaneLayout spl;
@@ -83,6 +85,7 @@ public class ConversationActivity extends XmppActivity {
});
}
};
+ private boolean contactInserted = false;
public List getConversationList() {
@@ -229,6 +232,8 @@ public class ConversationActivity extends XmppActivity {
if (this.getSelectedConversation()!=null) {
if (this.getSelectedConversation().getMode() == Conversation.MODE_MULTI) {
((MenuItem) menu.findItem(R.id.action_security)).setVisible(false);
+ ((MenuItem) menu.findItem(R.id.action_details)).setVisible(false);
+ ((MenuItem) menu.findItem(R.id.action_archive)).setTitle("Leave conference");
}
}
}
@@ -322,6 +327,13 @@ public class ConversationActivity extends XmppActivity {
@Override
void onBackendConnected() {
+
+ if (contactInserted) {
+ Log.d("xmppService","merge phone contacts with roster");
+ contactInserted = false;
+ xmppConnectionService.mergePhoneContactsWithRoster();
+ }
+
xmppConnectionService.setOnConversationListChangedListener(this.onConvChanged);
if (conversationList.size()==0) {
@@ -375,4 +387,11 @@ public class ConversationActivity extends XmppActivity {
}
}
}
+
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode==INSERT_CONTACT) {
+ Log.d("xmppService","contact inserted");
+ this.contactInserted = true;
+ }
+ }
}
diff --git a/src/de/gultsch/chat/ui/ConversationFragment.java b/src/de/gultsch/chat/ui/ConversationFragment.java
index 13e617fd7..204518696 100644
--- a/src/de/gultsch/chat/ui/ConversationFragment.java
+++ b/src/de/gultsch/chat/ui/ConversationFragment.java
@@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List;
import de.gultsch.chat.R;
+import de.gultsch.chat.entities.Contact;
import de.gultsch.chat.entities.Conversation;
import de.gultsch.chat.entities.Message;
import de.gultsch.chat.utils.UIHelper;
@@ -32,6 +33,7 @@ public class ConversationFragment extends Fragment {
protected LayoutInflater inflater;
protected List messageList = new ArrayList();
protected ArrayAdapter messageListAdapter;
+ protected Contact contact;
@Override
public View onCreateView(final LayoutInflater inflater,
@@ -40,7 +42,6 @@ public class ConversationFragment extends Fragment {
this.inflater = inflater;
-
final View view = inflater.inflate(R.layout.fragment_conversation,
container, false);
((ImageButton) view.findViewById(R.id.textSendButton))
diff --git a/src/de/gultsch/chat/ui/DialogContactDetails.java b/src/de/gultsch/chat/ui/DialogContactDetails.java
index 58e5f67fc..88bded870 100644
--- a/src/de/gultsch/chat/ui/DialogContactDetails.java
+++ b/src/de/gultsch/chat/ui/DialogContactDetails.java
@@ -7,12 +7,19 @@ import de.gultsch.chat.utils.UIHelper;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
+import android.provider.ContactsContract.CommonDataKinds;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Intents;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.View.OnClickListener;
import android.widget.CheckBox;
import android.widget.ImageView;
+import android.widget.QuickContactBadge;
import android.widget.TextView;
public class DialogContactDetails extends DialogFragment {
@@ -34,7 +41,8 @@ public class DialogContactDetails extends DialogFragment {
TextView status = (TextView) view.findViewById(R.id.details_contactstatus);
CheckBox send = (CheckBox) view.findViewById(R.id.details_send_presence);
CheckBox receive = (CheckBox) view.findViewById(R.id.details_receive_presence);
- ImageView contactPhoto = (ImageView) view.findViewById(R.id.details_contact_picture);
+ //ImageView contactPhoto = (ImageView) view.findViewById(R.id.details_contact_picture);
+ QuickContactBadge badge = (QuickContactBadge) view.findViewById(R.id.details_contact_badge);
boolean subscriptionSend = false;
boolean subscriptionReceive = false;
@@ -84,11 +92,35 @@ public class DialogContactDetails extends DialogFragment {
receive.setChecked(subscriptionReceive);
contactJid.setText(contact.getJid());
accountJid.setText(contact.getAccount().getJid());
+
+ UIHelper.prepareContactBadge(getActivity(), badge, contact);
- if (contact.getProfilePhoto()!=null) {
- contactPhoto.setImageURI(Uri.parse(contact.getProfilePhoto()));
- } else {
- contactPhoto.setImageBitmap(UIHelper.getUnknownContactPicture(contact.getDisplayName(), 300));
+ if (contact.getSystemAccount()==null) {
+ final DialogContactDetails details = this;
+ badge.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle("Add to contacts");
+ builder.setMessage("Do you want to add "+contact.getJid()+" to your contact list?");
+ builder.setNegativeButton("Cancel", null);
+ builder.setPositiveButton("Add", new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
+ intent.setType(Contacts.CONTENT_ITEM_TYPE);
+ intent.putExtra(Intents.Insert.IM_HANDLE,contact.getJid());
+ intent.putExtra(Intents.Insert.IM_PROTOCOL,CommonDataKinds.Im.PROTOCOL_JABBER);
+ intent.putExtra("finishActivityOnSaveCompleted", true);
+ getActivity().startActivityForResult(intent,ConversationActivity.INSERT_CONTACT);
+ details.dismiss();
+ }
+ });
+ builder.create().show();
+ }
+ });
}
builder.setView(view);
diff --git a/src/de/gultsch/chat/utils/OnPhoneContactsLoadedListener.java b/src/de/gultsch/chat/utils/OnPhoneContactsLoadedListener.java
new file mode 100644
index 000000000..c4df4ac30
--- /dev/null
+++ b/src/de/gultsch/chat/utils/OnPhoneContactsLoadedListener.java
@@ -0,0 +1,9 @@
+package de.gultsch.chat.utils;
+
+import java.util.Hashtable;
+
+import android.os.Bundle;
+
+public interface OnPhoneContactsLoadedListener {
+ public void onPhoneContactsLoaded(Hashtable phoneContacts);
+}
diff --git a/src/de/gultsch/chat/utils/PhoneHelper.java b/src/de/gultsch/chat/utils/PhoneHelper.java
new file mode 100644
index 000000000..f1d491d6f
--- /dev/null
+++ b/src/de/gultsch/chat/utils/PhoneHelper.java
@@ -0,0 +1,65 @@
+package de.gultsch.chat.utils;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+
+import android.content.Context;
+import android.content.CursorLoader;
+import android.content.Loader;
+import android.content.Loader.OnLoadCompleteListener;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.provider.ContactsContract;
+
+public class PhoneHelper {
+
+ public static void loadPhoneContacts(Context context, final OnPhoneContactsLoadedListener listener) {
+ final Hashtable phoneContacts = new Hashtable();
+
+ final String[] PROJECTION = new String[] {
+ ContactsContract.Data._ID,
+ ContactsContract.Data.DISPLAY_NAME,
+ ContactsContract.Data.PHOTO_THUMBNAIL_URI,
+ ContactsContract.Data.LOOKUP_KEY,
+ ContactsContract.CommonDataKinds.Im.DATA };
+
+ final String SELECTION = "(" + ContactsContract.Data.MIMETYPE + "=\""
+ + ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE
+ + "\") AND (" + ContactsContract.CommonDataKinds.Im.PROTOCOL
+ + "=\"" + ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER
+ + "\")";
+
+ CursorLoader mCursorLoader = new CursorLoader(context,
+ ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, null,
+ null);
+ mCursorLoader.registerListener(0, new OnLoadCompleteListener() {
+
+ @Override
+ public void onLoadComplete(Loader arg0, Cursor cursor) {
+ while (cursor.moveToNext()) {
+ Bundle contact = new Bundle();
+ contact.putInt("phoneid", cursor.getInt(cursor
+ .getColumnIndex(ContactsContract.Data._ID)));
+ contact.putString(
+ "displayname",
+ cursor.getString(cursor
+ .getColumnIndex(ContactsContract.Data.DISPLAY_NAME)));
+ contact.putString(
+ "photouri",
+ cursor.getString(cursor
+ .getColumnIndex(ContactsContract.Data.PHOTO_THUMBNAIL_URI)));
+ contact.putString("lookup",cursor.getString(cursor
+ .getColumnIndex(ContactsContract.Data.LOOKUP_KEY)));
+ phoneContacts.put(
+ cursor.getString(cursor
+ .getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA)),
+ contact);
+ }
+ if (listener!=null) {
+ listener.onPhoneContactsLoaded(phoneContacts);
+ }
+ }
+ });
+ mCursorLoader.startLoading();
+ }
+}
diff --git a/src/de/gultsch/chat/utils/UIHelper.java b/src/de/gultsch/chat/utils/UIHelper.java
index b7ea5289e..75c916825 100644
--- a/src/de/gultsch/chat/utils/UIHelper.java
+++ b/src/de/gultsch/chat/utils/UIHelper.java
@@ -1,28 +1,43 @@
package de.gultsch.chat.utils;
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
import java.text.SimpleDateFormat;
import java.util.Date;
import de.gultsch.chat.R;
+import de.gultsch.chat.entities.Contact;
import de.gultsch.chat.entities.Conversation;
import de.gultsch.chat.ui.ConversationActivity;
+import android.app.Activity;
+import android.app.AlertDialog;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.net.Uri;
import android.preference.PreferenceManager;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Intents;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.QuickContactBadge;
public class UIHelper {
public static String readableTimeDifference(long time) {
@@ -70,44 +85,62 @@ public class UIHelper {
return bitmap;
}
-
- public static Notification getUnreadMessageNotification(Context context, Conversation conversation) {
-
- SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
- String ringtone = sharedPref.getString("notification_ringtone",null);
-
+
+ public static Notification getUnreadMessageNotification(Context context,
+ Conversation conversation) {
+
+ SharedPreferences sharedPref = PreferenceManager
+ .getDefaultSharedPreferences(context);
+ String ringtone = sharedPref.getString("notification_ringtone", null);
+
Resources res = context.getResources();
- NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);
- mBuilder.setLargeIcon(UIHelper.getUnknownContactPicture(conversation.getName(),(int) res.getDimension(android.R.dimen.notification_large_icon_width)));
+ NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
+ context);
+ mBuilder.setLargeIcon(UIHelper.getUnknownContactPicture(conversation
+ .getName(), (int) res
+ .getDimension(android.R.dimen.notification_large_icon_width)));
mBuilder.setContentTitle(conversation.getName());
mBuilder.setContentText(conversation.getLatestMessage());
mBuilder.setSmallIcon(R.drawable.notification);
mBuilder.setLights(0xffffffff, 2000, 4000);
- if (ringtone!=null) {
+ if (ringtone != null) {
mBuilder.setSound(Uri.parse(ringtone));
}
-
+
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(ConversationActivity.class);
-
- Intent viewConversationIntent = new Intent(context,ConversationActivity.class);
- viewConversationIntent.setAction(Intent.ACTION_VIEW);
- viewConversationIntent.putExtra(
- ConversationActivity.CONVERSATION,
- conversation.getUuid());
- viewConversationIntent
- .setType(ConversationActivity.VIEW_CONVERSATION);
-
- stackBuilder.addNextIntent(viewConversationIntent);
-
- PendingIntent resultPendingIntent =
- stackBuilder.getPendingIntent(
- 0,
- PendingIntent.FLAG_UPDATE_CURRENT
- );
-
+ Intent viewConversationIntent = new Intent(context,
+ ConversationActivity.class);
+ viewConversationIntent.setAction(Intent.ACTION_VIEW);
+ viewConversationIntent.putExtra(ConversationActivity.CONVERSATION,
+ conversation.getUuid());
+ viewConversationIntent.setType(ConversationActivity.VIEW_CONVERSATION);
+
+ stackBuilder.addNextIntent(viewConversationIntent);
+
+ PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
mBuilder.setContentIntent(resultPendingIntent);
return mBuilder.build();
}
+
+ public static void prepareContactBadge(final Activity activity,
+ QuickContactBadge badge, final Contact contact) {
+ if (contact.getSystemAccount()!=null) {
+ String[] systemAccount = contact.getSystemAccount().split("#");
+ long id = Long.parseLong(systemAccount[0]);
+ badge.assignContactUri(Contacts.getLookupUri(id, systemAccount[1]));
+
+ if (contact.getProfilePhoto() != null) {
+ badge.setImageURI(Uri.parse(contact.getProfilePhoto()));
+ } else {
+ badge.setImageBitmap(UIHelper.getUnknownContactPicture(contact.getDisplayName(), 400));
+ }
+ } else {
+ badge.setImageBitmap(UIHelper.getUnknownContactPicture(contact.getDisplayName(), 400));
+ }
+
+ }
}