From 9cd5a67ec51dee4d436384329a9a062373eee3fc Mon Sep 17 00:00:00 2001 From: Jake McGinty Date: Thu, 6 Feb 2014 18:06:23 -0800 Subject: [PATCH] directory changes to use number instead of token, group ui progress --- .../textsecure/directory/Directory.java | 102 +++++----- .../textsecure/push/ContactDetails.java | 31 +++ .../textsecure/push/ContactNumberDetails.java | 42 +++++ .../textsecure/push/ContactTokenDetails.java | 24 +-- .../textsecure/util/DirectoryUtil.java | 33 ++++ res/layout/group_create_activity.xml | 42 ++--- .../push_contact_selection_list_item.xml | 12 +- res/layout/push_recipients_panel.xml | 30 +++ .../securesms/GroupCreateActivity.java | 89 ++++++--- .../PushContactSelectionActivity.java | 1 + .../PushContactSelectionListFragment.java | 44 +++-- .../securesms/RoutingActivity.java | 3 + .../components/PushRecipientsPanel.java | 177 ++++++++++++++++++ .../securesms/contacts/ContactAccessor.java | 26 +++ .../contacts/PushFilterCursorWrapper.java | 106 ----------- .../securesms/gcm/GcmIntentService.java | 7 +- .../service/DirectoryRefreshService.java | 22 +-- .../service/RegistrationService.java | 13 +- .../transport/UniversalTransport.java | 21 +-- .../securesms/util/DirectoryHelper.java | 43 +++++ src/org/thoughtcrime/securesms/util/Util.java | 33 ---- 21 files changed, 583 insertions(+), 318 deletions(-) create mode 100644 library/src/org/whispersystems/textsecure/push/ContactDetails.java create mode 100644 library/src/org/whispersystems/textsecure/push/ContactNumberDetails.java create mode 100644 library/src/org/whispersystems/textsecure/util/DirectoryUtil.java create mode 100644 res/layout/push_recipients_panel.xml create mode 100644 src/org/thoughtcrime/securesms/components/PushRecipientsPanel.java delete mode 100644 src/org/thoughtcrime/securesms/contacts/PushFilterCursorWrapper.java create mode 100644 src/org/thoughtcrime/securesms/util/DirectoryHelper.java diff --git a/library/src/org/whispersystems/textsecure/directory/Directory.java b/library/src/org/whispersystems/textsecure/directory/Directory.java index fea88a58cdf..989051b51e3 100644 --- a/library/src/org/whispersystems/textsecure/directory/Directory.java +++ b/library/src/org/whispersystems/textsecure/directory/Directory.java @@ -7,39 +7,41 @@ import android.database.sqlite.SQLiteOpenHelper; import android.net.Uri; import android.provider.ContactsContract.CommonDataKinds.Phone; +import android.telephony.TelephonyManager; import android.util.Log; -import org.whispersystems.textsecure.push.ContactTokenDetails; -import org.whispersystems.textsecure.util.Base64; +import org.whispersystems.textsecure.push.ContactNumberDetails; +import org.whispersystems.textsecure.util.DirectoryUtil; import org.whispersystems.textsecure.util.InvalidNumberException; import org.whispersystems.textsecure.util.PhoneNumberFormatter; -import org.whispersystems.textsecure.util.Util; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; public class Directory { + private static final int INTRODUCED_CHANGE_FROM_TOKEN_TO_E164_NUMBER = 2; + private static final int DATABASE_VERSION = 2; + private static final String DATABASE_NAME = "whisper_directory.db"; - private static final int DATABASE_VERSION = 1; private static final String TABLE_NAME = "directory"; private static final String ID = "_id"; - private static final String TOKEN = "token"; + private static final String NUMBER = "number"; private static final String REGISTERED = "registered"; private static final String RELAY = "relay"; private static final String SUPPORTS_SMS = "supports_sms"; private static final String TIMESTAMP = "timestamp"; private static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "(" + ID + " INTEGER PRIMARY KEY, " + - TOKEN + " TEXT UNIQUE, " + - REGISTERED + " INTEGER, " + - RELAY + " TEXT, " + - SUPPORTS_SMS + " INTEGER, " + - TIMESTAMP + " INTEGER);"; + NUMBER + " TEXT UNIQUE, " + + REGISTERED + " INTEGER, " + + RELAY + " TEXT, " + + SUPPORTS_SMS + " INTEGER, " + + TIMESTAMP + " INTEGER);"; private static final Object instanceLock = new Object(); private static volatile Directory instance; @@ -60,7 +62,7 @@ public static Directory getInstance(Context context) { private final Context context; private Directory(Context context) { - this.context = context; + this.context = context; this.databaseHelper = new DatabaseHelper(context, DATABASE_NAME, null, DATABASE_VERSION); } @@ -69,14 +71,13 @@ public boolean isActiveNumber(String e164number) throws NotInDirectoryException return false; } - SQLiteDatabase db = databaseHelper.getReadableDatabase(); - String token = getToken(e164number); - Cursor cursor = null; + SQLiteDatabase db = databaseHelper.getReadableDatabase(); + Cursor cursor = null; try { cursor = db.query(TABLE_NAME, - new String[] {REGISTERED}, TOKEN + " = ?", - new String[] {token}, null, null, null); + new String[]{REGISTERED}, NUMBER + " = ?", + new String[] {e164number}, null, null, null); if (cursor != null && cursor.moveToFirst()) { return cursor.getInt(0) == 1; @@ -91,12 +92,11 @@ public boolean isActiveNumber(String e164number) throws NotInDirectoryException } public String getRelay(String e164number) { - String token = getToken(e164number); SQLiteDatabase database = databaseHelper.getReadableDatabase(); Cursor cursor = null; try { - cursor = database.query(TABLE_NAME, null, TOKEN + " = ?", new String[]{token}, null, null, null); + cursor = database.query(TABLE_NAME, null, NUMBER + " = ?", new String[]{e164number}, null, null, null); if (cursor != null && cursor.moveToFirst()) { return cursor.getString(cursor.getColumnIndexOrThrow(RELAY)); @@ -109,10 +109,10 @@ public String getRelay(String e164number) { } } - public void setToken(ContactTokenDetails token, boolean active) { + public void setNumber(ContactNumberDetails token, boolean active) { SQLiteDatabase db = databaseHelper.getWritableDatabase(); ContentValues values = new ContentValues(); - values.put(TOKEN, token.getToken()); + values.put(NUMBER, token.getNumber()); values.put(RELAY, token.getRelay()); values.put(REGISTERED, active ? 1 : 0); values.put(SUPPORTS_SMS, token.isSupportsSms() ? 1 : 0); @@ -120,16 +120,16 @@ public void setToken(ContactTokenDetails token, boolean active) { db.replace(TABLE_NAME, null, values); } - public void setTokens(List activeTokens, Collection inactiveTokens) { + public void setNumbers(List activeTokens, Collection inactiveTokens) { long timestamp = System.currentTimeMillis(); SQLiteDatabase db = databaseHelper.getWritableDatabase(); db.beginTransaction(); try { - for (ContactTokenDetails token : activeTokens) { + for (ContactNumberDetails token : activeTokens) { Log.w("Directory", "Adding active token: " + token); ContentValues values = new ContentValues(); - values.put(TOKEN, token.getToken()); + values.put(NUMBER, token.getNumber()); values.put(REGISTERED, 1); values.put(TIMESTAMP, timestamp); values.put(RELAY, token.getRelay()); @@ -139,7 +139,7 @@ public void setTokens(List activeTokens, Collection for (String token : inactiveTokens) { ContentValues values = new ContentValues(); - values.put(TOKEN, token); + values.put(NUMBER, token); values.put(REGISTERED, 0); values.put(TIMESTAMP, timestamp); db.replace(TABLE_NAME, null, values); @@ -151,21 +151,20 @@ public void setTokens(List activeTokens, Collection } } - public Set getPushEligibleContactTokens(String localNumber) { - Uri uri = Phone.CONTENT_URI; - Set results = new HashSet(); - Cursor cursor = null; + public Set getPushEligibleContactNumbers(String localNumber) { + final Uri uri = Phone.CONTENT_URI; + final Set results = new HashSet(); + Cursor cursor = null; try { cursor = context.getContentResolver().query(uri, new String[] {Phone.NUMBER}, null, null, null); while (cursor != null && cursor.moveToNext()) { - String rawNumber = cursor.getString(0); - + final String rawNumber = cursor.getString(0); if (rawNumber != null) { try { - String e164Number = PhoneNumberFormatter.formatNumber(rawNumber, localNumber); - results.add(getToken(e164Number)); + final String e164Number = PhoneNumberFormatter.formatNumber(rawNumber, localNumber); + results.add(e164Number); } catch (InvalidNumberException e) { Log.w("Directory", "Invalid number: " + rawNumber); } @@ -175,11 +174,14 @@ public Set getPushEligibleContactTokens(String localNumber) { if (cursor != null) cursor.close(); - cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, new String[] {TOKEN}, - null, null, null, null, null); + final SQLiteDatabase readableDb = databaseHelper.getReadableDatabase(); + if (readableDb != null) { + cursor = readableDb.query(TABLE_NAME, new String[]{NUMBER}, + null, null, null, null, null); - while (cursor != null && cursor.moveToNext()) { - results.add(cursor.getString(0)); + while (cursor != null && cursor.moveToNext()) { + results.add(cursor.getString(0)); + } } return results; @@ -189,13 +191,20 @@ public Set getPushEligibleContactTokens(String localNumber) { } } - public String getToken(String e164number) { + public List getActiveNumbers() { + final List results = new ArrayList(); + Cursor cursor = null; try { - MessageDigest digest = MessageDigest.getInstance("SHA1"); - byte[] token = Util.trim(digest.digest(e164number.getBytes()), 10); - return Base64.encodeBytesWithoutPadding(token); - } catch (NoSuchAlgorithmException e) { - throw new AssertionError(e); + cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, new String[]{NUMBER}, + REGISTERED + " = 1", null, null, null, null); + + while (cursor != null && cursor.moveToNext()) { + results.add(cursor.getString(0)); + } + return results; + } finally { + if (cursor != null) + cursor.close(); } } @@ -215,7 +224,10 @@ public void onCreate(SQLiteDatabase db) { @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - + if (oldVersion < INTRODUCED_CHANGE_FROM_TOKEN_TO_E164_NUMBER) { + db.execSQL("DROP TABLE directory;"); + onCreate(db); + } } } diff --git a/library/src/org/whispersystems/textsecure/push/ContactDetails.java b/library/src/org/whispersystems/textsecure/push/ContactDetails.java new file mode 100644 index 00000000000..9d05611a7cc --- /dev/null +++ b/library/src/org/whispersystems/textsecure/push/ContactDetails.java @@ -0,0 +1,31 @@ +package org.whispersystems.textsecure.push; + +import com.google.thoughtcrimegson.Gson; + +public abstract class ContactDetails { + + private String relay; + private boolean supportsSms; + + public ContactDetails() {} + + public ContactDetails(String relay) { + this.relay = relay; + } + + public String getRelay() { + return relay; + } + + public void setRelay(String relay) { + this.relay = relay; + } + + public boolean isSupportsSms() { + return supportsSms; + } + + public String toString() { + return new Gson().toJson(this); + } +} diff --git a/library/src/org/whispersystems/textsecure/push/ContactNumberDetails.java b/library/src/org/whispersystems/textsecure/push/ContactNumberDetails.java new file mode 100644 index 00000000000..ba4537b6e6a --- /dev/null +++ b/library/src/org/whispersystems/textsecure/push/ContactNumberDetails.java @@ -0,0 +1,42 @@ +package org.whispersystems.textsecure.push; + +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class ContactNumberDetails extends ContactDetails { + private static final String TAG = "ContactNumberDetails"; + + private String number; + + public ContactNumberDetails() { super(); } + + public ContactNumberDetails(String number) { + super(); + this.number = number; + } + + public ContactNumberDetails(String number, String relay) { + super(relay); + this.number = number; + } + + public String getNumber() { + return number; + } + + public static List fromContactTokenDetailsList(List contactTokenDetails, final Map tokenMap) { + if (contactTokenDetails == null || tokenMap == null) return null; + + List contactNumberDetails = new ArrayList(contactTokenDetails.size()); + for (ContactTokenDetails tokenDetails : contactTokenDetails) { + if (tokenMap.containsKey(tokenDetails.getToken())) + contactNumberDetails.add(new ContactNumberDetails(tokenMap.get(tokenDetails.getToken()), tokenDetails.getRelay())); + else + Log.w(TAG, "tokenMap was missing a contact."); + } + return contactNumberDetails; + } +} diff --git a/library/src/org/whispersystems/textsecure/push/ContactTokenDetails.java b/library/src/org/whispersystems/textsecure/push/ContactTokenDetails.java index 9611d7c1e58..12c9586b005 100644 --- a/library/src/org/whispersystems/textsecure/push/ContactTokenDetails.java +++ b/library/src/org/whispersystems/textsecure/push/ContactTokenDetails.java @@ -2,40 +2,24 @@ import com.google.thoughtcrimegson.Gson; -public class ContactTokenDetails { +public class ContactTokenDetails extends ContactDetails { private String token; - private String relay; - private boolean supportsSms; - public ContactTokenDetails() {} + public ContactTokenDetails() { super(); } public ContactTokenDetails(String token) { + super(); this.token = token; } public ContactTokenDetails(String token, String relay) { + super(relay); this.token = token; - this.relay = relay; } public String getToken() { return token; } - public String getRelay() { - return relay; - } - - public void setRelay(String relay) { - this.relay = relay; - } - - public boolean isSupportsSms() { - return supportsSms; - } - - public String toString() { - return new Gson().toJson(this); - } } diff --git a/library/src/org/whispersystems/textsecure/util/DirectoryUtil.java b/library/src/org/whispersystems/textsecure/util/DirectoryUtil.java new file mode 100644 index 00000000000..f5f59330f7c --- /dev/null +++ b/library/src/org/whispersystems/textsecure/util/DirectoryUtil.java @@ -0,0 +1,33 @@ +package org.whispersystems.textsecure.util; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +public class DirectoryUtil { + + public static String getDirectoryServerToken(String e164number) { + try { + MessageDigest digest = MessageDigest.getInstance("SHA1"); + byte[] token = Util.trim(digest.digest(e164number.getBytes()), 10); + return Base64.encodeBytesWithoutPadding(token); + } catch (NoSuchAlgorithmException e) { + throw new AssertionError(e); + } + } + + /** + * Get a mapping of directory server tokens to their requested number. + * @param e164numbers + * @return map with token as key, E164 number as value + */ + public static Map getDirectoryServerTokenMap(Collection e164numbers) { + final Map tokenMap = new HashMap(e164numbers.size()); + for (String number : e164numbers) { + tokenMap.put(getDirectoryServerToken(number), number); + } + return tokenMap; + } +} diff --git a/res/layout/group_create_activity.xml b/res/layout/group_create_activity.xml index b979bc128a5..235660839c5 100644 --- a/res/layout/group_create_activity.xml +++ b/res/layout/group_create_activity.xml @@ -6,36 +6,32 @@ android:layout_height="match_parent" android:padding="20dp"> - - - - + android:orientation="horizontal" + android:gravity="center_vertical" + android:layout_marginBottom="20dp" > + + + android:padding="10dp" + android:hint="Group name" + android:layout_gravity="center_vertical" /> + - - + + + + + + + + + + + \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/GroupCreateActivity.java b/src/org/thoughtcrime/securesms/GroupCreateActivity.java index d8ffe1b620f..afa4ed959d8 100644 --- a/src/org/thoughtcrime/securesms/GroupCreateActivity.java +++ b/src/org/thoughtcrime/securesms/GroupCreateActivity.java @@ -2,20 +2,18 @@ import android.app.Activity; import android.content.Intent; -import android.database.Cursor; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.net.Uri; import android.os.Bundle; -import android.provider.MediaStore; import android.util.Log; import android.view.View; +import android.widget.ImageView; import android.widget.ListView; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; +import org.thoughtcrime.securesms.components.PushRecipientsPanel; import org.thoughtcrime.securesms.contacts.ContactAccessor; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientFactory; @@ -28,7 +26,6 @@ import java.util.ArrayList; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Set; @@ -37,12 +34,17 @@ public class GroupCreateActivity extends PassphraseRequiredSherlockFragmentActivity { + private final static String TAG = "GroupCreateActivity"; + private final DynamicTheme dynamicTheme = new DynamicTheme(); private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); private static final int PICK_CONTACT = 1; - private static final int SELECT_PHOTO = 100; - private ListView lv; + private static final int PICK_AVATAR = 2; + + private ListView lv; + private PushRecipientsPanel recipientsPanel; + private ImageView avatar; private Set selectedContacts; @@ -69,7 +71,35 @@ public void onResume() { private void initializeResources() { lv = (ListView) findViewById(R.id.selected_contacts_list); lv.setAdapter(new SelectedRecipientsAdapter(this, android.R.id.text1, new ArrayList())); - (findViewById(R.id.add_people_button)).setOnClickListener(new AddRecipientButtonListener()); + + recipientsPanel = (PushRecipientsPanel) findViewById(R.id.recipients); + recipientsPanel.setPanelChangeListener(new PushRecipientsPanel.RecipientsPanelChangedListener() { + @Override + public void onRecipientsPanelUpdate(Recipients recipients) { + Log.i(TAG, "onRecipientsPanelUpdate received."); + if (recipients != null) { + selectedContacts.addAll(recipients.getRecipientsList()); + syncAdapterWithSelectedContacts(); + } + } + }); + (findViewById(R.id.contacts_button)).setOnClickListener(new AddRecipientButtonListener()); + + avatar = (ImageView) findViewById(R.id.avatar); + avatar.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT, null); + photoPickerIntent.setType("image/*"); + photoPickerIntent.putExtra("crop", "true"); + photoPickerIntent.putExtra("aspectX", 1); + photoPickerIntent.putExtra("aspectY", 1); + photoPickerIntent.putExtra("outputX", 256); + photoPickerIntent.putExtra("outputY", 256); + photoPickerIntent.putExtra("return-data", "true"); + startActivityForResult(photoPickerIntent, PICK_AVATAR); + } + }); } @Override @@ -103,6 +133,16 @@ public boolean onOptionsItemSelected(MenuItem item) { return false; } + private void syncAdapterWithSelectedContacts() { + SelectedRecipientsAdapter adapter = (SelectedRecipientsAdapter)lv.getAdapter(); + adapter.clear(); + for (Recipient contact : selectedContacts) { + adapter.add(contact); + Log.i("GroupCreateActivity", "Adding " + contact.getName() + "/" + contact.getNumber()); + } + adapter.notifyDataSetChanged(); + } + @Override public void onActivityResult(int reqCode, int resultCode, Intent data) { Log.w("ComposeMessageActivity", "onActivityResult called: " + resultCode + " , " + data); @@ -114,10 +154,13 @@ public void onActivityResult(int reqCode, int resultCode, Intent data) { switch (reqCode) { case PICK_CONTACT: List selected = data.getParcelableArrayListExtra("contacts"); + for (ContactData cdata : selected) { + Log.i("PushContactSelect", "selected report: " + cdata.name); + } for (ContactData contact : selected) { for (ContactAccessor.NumberData numberData : contact.numbers) { try { - Recipient recipient = RecipientFactory.getRecipientsFromString(this, numberData.number, true) + Recipient recipient = RecipientFactory.getRecipientsFromString(this, numberData.number, false) .getPrimaryRecipient(); if (!selectedContacts.contains(recipient)) { @@ -128,28 +171,14 @@ public void onActivityResult(int reqCode, int resultCode, Intent data) { } } } - - SelectedRecipientsAdapter adapter = (SelectedRecipientsAdapter)lv.getAdapter(); - adapter.clear(); - Iterator selectedContactsIter = selectedContacts.iterator(); - while (selectedContactsIter.hasNext()) { - adapter.add(selectedContactsIter.next()); - } + syncAdapterWithSelectedContacts(); break; - case SELECT_PHOTO: - if(resultCode == RESULT_OK){ - Uri selectedImage = data.getData(); - String[] filePathColumn = {MediaStore.Images.Media.DATA}; - - Cursor cursor = getContentResolver().query( - selectedImage, filePathColumn, null, null, null); - cursor.moveToFirst(); - - int columnIndex = cursor.getColumnIndex(filePathColumn[0]); - String filePath = cursor.getString(columnIndex); - cursor.close(); - - Bitmap selectedBitmap = BitmapFactory.decodeFile(filePath); + case PICK_AVATAR: + if(resultCode == RESULT_OK) { + Bitmap avatarBmp = data.getParcelableExtra("data"); + avatar.setImageBitmap(avatarBmp); + //Uri selectedImage = data.getData(); + //avatar.setImageURI(selectedImage); break; } } diff --git a/src/org/thoughtcrime/securesms/PushContactSelectionActivity.java b/src/org/thoughtcrime/securesms/PushContactSelectionActivity.java index 919202b83ec..5fc3d427b83 100644 --- a/src/org/thoughtcrime/securesms/PushContactSelectionActivity.java +++ b/src/org/thoughtcrime/securesms/PushContactSelectionActivity.java @@ -18,6 +18,7 @@ import android.content.Intent; import android.os.Bundle; +import android.util.Log; import org.thoughtcrime.securesms.contacts.ContactAccessor; import org.thoughtcrime.securesms.recipients.Recipients; diff --git a/src/org/thoughtcrime/securesms/PushContactSelectionListFragment.java b/src/org/thoughtcrime/securesms/PushContactSelectionListFragment.java index 916ab2b87c6..396d284ade9 100644 --- a/src/org/thoughtcrime/securesms/PushContactSelectionListFragment.java +++ b/src/org/thoughtcrime/securesms/PushContactSelectionListFragment.java @@ -21,6 +21,8 @@ import android.content.Context; import android.content.DialogInterface; import android.database.Cursor; +import android.database.MergeCursor; +import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; @@ -42,11 +44,7 @@ import org.thoughtcrime.securesms.contacts.ContactAccessor; import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData; import org.thoughtcrime.securesms.contacts.ContactAccessor.NumberData; -import org.thoughtcrime.securesms.contacts.PushFilterCursorWrapper; -import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.recipients.Recipients; -import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -105,7 +103,6 @@ public List getSelectedContacts() { return selected; } - private void handleUnselectAll() { selectedContacts.clear(); ((CursorAdapter)getListView().getAdapter()).notifyDataSetChanged(); @@ -188,19 +185,35 @@ public View newView(Context context, Cursor cursor, ViewGroup parent) { @Override public void bindView(View view, Context context, Cursor cursor) { - PushFilterCursorWrapper wrappedCursor = (PushFilterCursorWrapper) cursor; - boolean isPushUser = wrappedCursor.getPushCount() > wrappedCursor.getPosition(); + boolean isPushUser; + try { + isPushUser = (cursor.getInt(cursor.getColumnIndexOrThrow(ContactAccessor.PUSH_COLUMN)) > 0); + } catch (IllegalArgumentException iae) { + isPushUser = false; + } ContactData contactData = ContactAccessor.getInstance().getContactData(context, cursor); - ((ContactItemView)view).set(contactData, isPushUser); + PushContactData pushContactData = new PushContactData(contactData, isPushUser); + ((ContactItemView)view).set(pushContactData); + } + } + + private class PushContactData { + private final ContactData contactData; + private final boolean pushSupport; + public PushContactData(ContactData contactData, boolean pushSupport) { + this.contactData = contactData; + this.pushSupport = pushSupport; } } private class ContactItemView extends RelativeLayout { private ContactData contactData; + private boolean pushSupport; private CheckBox checkBox; private TextView name; private TextView number; private TextView label; + private View pushLabel; public ContactItemView(Context context) { super(context); @@ -211,6 +224,7 @@ public ContactItemView(Context context) { this.number = (TextView) findViewById(R.id.number); this.label = (TextView) findViewById(R.id.label); this.checkBox = (CheckBox) findViewById(R.id.check_box); + this.pushLabel = findViewById(R.id.push_support_label); } public void selected() { @@ -225,17 +239,18 @@ public void selected() { } } - public void set(ContactData contactData, boolean isPushUser) { - this.contactData = contactData; + public void set(PushContactData pushContactData) { + this.contactData = pushContactData.contactData; + this.pushSupport = pushContactData.pushSupport; - if (!isPushUser) { + if (!pushSupport) { this.name.setTextColor(0xa0000000); this.number.setTextColor(0xa0000000); - this.checkBox.setVisibility(View.GONE); + this.pushLabel.setBackgroundColor(0x99000000); } else { this.name.setTextColor(0xff000000); this.number.setTextColor(0xff000000); - this.checkBox.setVisibility(View.VISIBLE); + this.pushLabel.setBackgroundColor(0xff64a926); } if (selectedContacts.containsKey(contactData.id)) @@ -322,7 +337,8 @@ public Loader onCreateLoader(int arg0, Bundle arg1) { @Override public void onLoadFinished(Loader arg0, Cursor cursor) { - ((CursorAdapter) getListAdapter()).changeCursor(new PushFilterCursorWrapper(cursor, getActivity())); + Cursor pushCursor = ContactAccessor.getInstance().getCursorForContactsWithPush(getActivity()); + ((CursorAdapter) getListAdapter()).changeCursor(new MergeCursor(new Cursor[]{pushCursor,cursor})); } @Override diff --git a/src/org/thoughtcrime/securesms/RoutingActivity.java b/src/org/thoughtcrime/securesms/RoutingActivity.java index 536ac9e9813..8d03807af7e 100644 --- a/src/org/thoughtcrime/securesms/RoutingActivity.java +++ b/src/org/thoughtcrime/securesms/RoutingActivity.java @@ -9,6 +9,9 @@ import org.thoughtcrime.securesms.recipients.RecipientFormattingException; import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.service.ApplicationMigrationService; +import org.thoughtcrime.securesms.service.DirectoryRefreshListener; +import org.thoughtcrime.securesms.service.DirectoryRefreshService; +import org.thoughtcrime.securesms.util.DirectoryHelper; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.textsecure.crypto.MasterSecret; diff --git a/src/org/thoughtcrime/securesms/components/PushRecipientsPanel.java b/src/org/thoughtcrime/securesms/components/PushRecipientsPanel.java new file mode 100644 index 00000000000..3fd1fe87e7b --- /dev/null +++ b/src/org/thoughtcrime/securesms/components/PushRecipientsPanel.java @@ -0,0 +1,177 @@ +/** + * Copyright (C) 2011 Whisper Systems + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.thoughtcrime.securesms.components; + +import android.content.Context; +import android.os.Build; +import android.util.AttributeSet; +import android.util.Log; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.AdapterView; +import android.widget.AutoCompleteTextView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import org.thoughtcrime.securesms.R; +import org.thoughtcrime.securesms.contacts.ContactAccessor; +import org.thoughtcrime.securesms.contacts.RecipientsAdapter; +import org.thoughtcrime.securesms.contacts.RecipientsEditor; +import org.thoughtcrime.securesms.recipients.Recipient; +import org.thoughtcrime.securesms.recipients.RecipientFactory; +import org.thoughtcrime.securesms.recipients.RecipientFormattingException; +import org.thoughtcrime.securesms.recipients.Recipients; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +/** + * Panel component combining both an editable field with a button for + * a list-based contact selector. + * + * @author Moxie Marlinspike + */ +public class PushRecipientsPanel extends RelativeLayout { + private final String TAG = "PushRecipientsPanel"; + private RecipientsPanelChangedListener panelChangeListener; + + private RecipientsEditor recipientsText; + private View panel; + + private static final int RECIPIENTS_MAX_LENGTH = 312; + + public PushRecipientsPanel(Context context) { + super(context); + initialize(); + } + + public PushRecipientsPanel(Context context, AttributeSet attrs) { + super(context, attrs); + initialize(); + } + + public PushRecipientsPanel(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initialize(); + } + + public void addRecipient(String name, String number) { + Log.i(TAG, "addRecipient for " + name + "/" + number); + if (name != null) recipientsText.append(name + "< " + number + ">, "); + else recipientsText.append(number + ", "); + } + + public void addContacts(List contacts) { + for (ContactAccessor.ContactData contact : contacts) { + for (ContactAccessor.NumberData number : contact.numbers) { + addRecipient(contact.name, number.number); + } + } + } + + public void addRecipients(Recipients recipients) { + List recipientList = recipients.getRecipientsList(); + Iterator iterator = recipientList.iterator(); + + while (iterator.hasNext()) { + Recipient recipient = iterator.next(); + addRecipient(recipient.getName(), recipient.getNumber()); + } + } + + public Recipients getRecipients() throws RecipientFormattingException { + String rawText = recipientsText.getText().toString(); + Recipients recipients = RecipientFactory.getRecipientsFromString(getContext(), rawText, false); + + if (recipients.isEmpty()) + throw new RecipientFormattingException("Recipient List Is Empty!"); + + return recipients; + } + + public void disable() { + recipientsText.setText(""); + panel.setVisibility(View.GONE); + } + + public void setPanelChangeListener(RecipientsPanelChangedListener panelChangeListener) { + this.panelChangeListener = panelChangeListener; + } + + private void initialize() { + LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(R.layout.push_recipients_panel, this, true); + + View imageButton = findViewById(R.id.contacts_button); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) + ((MarginLayoutParams) imageButton.getLayoutParams()).topMargin = 0; + + panel = findViewById(R.id.recipients_panel); + initRecipientsEditor(); + } + + private void initRecipientsEditor() { + Recipients recipients = null; + recipientsText = (RecipientsEditor)findViewById(R.id.recipients_text); + + try { + recipients = getRecipients(); + } catch (RecipientFormattingException e) { + recipients = new Recipients( new LinkedList() ); + } + + recipientsText.setAdapter(new RecipientsAdapter(this.getContext())); + recipientsText.populate(recipients); + + recipientsText.setOnFocusChangeListener(new FocusChangedListener()); + recipientsText.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView adapterView, View view, int i, long l) { + if (panelChangeListener != null) { + try { + panelChangeListener.onRecipientsPanelUpdate(getRecipients()); + } catch (RecipientFormattingException rfe) { + panelChangeListener.onRecipientsPanelUpdate(null); + } + } + recipientsText.setText(""); + } + }); + } + + private class FocusChangedListener implements View.OnFocusChangeListener { + public void onFocusChange(View v, boolean hasFocus) { + if (!hasFocus && (panelChangeListener != null)) { + try { + panelChangeListener.onRecipientsPanelUpdate(getRecipients()); + } catch (RecipientFormattingException rfe) { + panelChangeListener.onRecipientsPanelUpdate(null); + } + } + } + } + + public interface RecipientsPanelChangedListener { + public void onRecipientsPanelUpdate(Recipients recipients); + } + +} \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/contacts/ContactAccessor.java b/src/org/thoughtcrime/securesms/contacts/ContactAccessor.java index d3854ebcedf..810e8513a14 100644 --- a/src/org/thoughtcrime/securesms/contacts/ContactAccessor.java +++ b/src/org/thoughtcrime/securesms/contacts/ContactAccessor.java @@ -20,7 +20,9 @@ import android.content.ContentValues; import android.content.Context; import android.database.Cursor; +import android.database.MatrixCursor; import android.database.MergeCursor; +import android.graphics.Bitmap; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; @@ -36,6 +38,7 @@ import org.whispersystems.textsecure.crypto.IdentityKey; import org.whispersystems.textsecure.crypto.InvalidKeyException; +import org.whispersystems.textsecure.directory.Directory; import org.whispersystems.textsecure.util.Base64; import java.io.IOException; @@ -58,6 +61,8 @@ public class ContactAccessor { + public static final String PUSH_COLUMN = "push"; + private static final ContactAccessor instance = new ContactAccessor(); public static synchronized ContactAccessor getInstance() { @@ -85,6 +90,27 @@ public Cursor getCursorForContactsWithNumbers(Context context) { ContactsContract.Contacts.DISPLAY_NAME + " ASC"); } + public Cursor getCursorForContactsWithPush(Context context) { + final ContentResolver resolver = context.getContentResolver(); + final String[] inProjection = new String[]{PhoneLookup._ID, PhoneLookup.DISPLAY_NAME}; + final String[] outProjection = new String[]{PhoneLookup._ID, PhoneLookup.DISPLAY_NAME, PUSH_COLUMN}; + MatrixCursor cursor = new MatrixCursor(outProjection); + List pushNumbers = Directory.getInstance(context).getActiveNumbers(); + for (String pushNumber : pushNumbers) { + Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(pushNumber)); + Cursor lookupCursor = resolver.query(uri, inProjection, null, null, null); + try { + if (lookupCursor != null && lookupCursor.moveToFirst()) { + cursor.addRow(new Object[]{lookupCursor.getLong(0), lookupCursor.getString(1), 1}); + } + } finally { + if (lookupCursor != null) + lookupCursor.close(); + } + } + return cursor; + } + public String getNameFromContact(Context context, Uri uri) { Cursor cursor = null; diff --git a/src/org/thoughtcrime/securesms/contacts/PushFilterCursorWrapper.java b/src/org/thoughtcrime/securesms/contacts/PushFilterCursorWrapper.java deleted file mode 100644 index 6725eb4da2d..00000000000 --- a/src/org/thoughtcrime/securesms/contacts/PushFilterCursorWrapper.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.thoughtcrime.securesms.contacts; - -import android.content.Context; -import android.database.Cursor; -import android.database.CursorWrapper; -import android.os.Debug; -import android.provider.ContactsContract; -import android.util.Log; - -import org.thoughtcrime.securesms.util.Util; -import org.whispersystems.textsecure.util.InvalidNumberException; - -import java.util.List; - -public class PushFilterCursorWrapper extends CursorWrapper { - private int[] pushIndex; - private int[] normalIndex; - private int count = 0; - private int pushCount = 0; - private int pos = 0; - - private final ContactAccessor contactAccessor = ContactAccessor.getInstance(); - - /* - * Don't know of a better way to do this without a large filtering through the entire dataset at first - */ - public PushFilterCursorWrapper(Cursor cursor, Context context) { - super(cursor); - this.count = super.getCount(); - this.pushIndex = new int[this.count]; - this.normalIndex = new int[this.count]; - int pushPos = 0; - int normalPos = 0; - for (int i = 0; i < this.count; i++) { - super.moveToPosition(i); - - - List numbers = contactAccessor.getContactData(context, cursor).numbers; - if (numbers.size() > 0) { - try { - if (Util.isPushTransport(context, Util.canonicalizeNumber(context, numbers.get(0).number))) - this.pushIndex[pushPos++] = i; - else - this.normalIndex[normalPos++] = i; - } catch (InvalidNumberException ine) { - } - } - } - this.pushCount = pushPos; - super.moveToFirst(); - } - - @Override - public boolean move(int offset) { - return this.moveToPosition(this.pos + offset); - } - - @Override - public boolean moveToNext() { - return this.moveToPosition(this.pos + 1); - } - - @Override - public boolean moveToPrevious() { - return this.moveToPosition(this.pos - 1); - } - - @Override - public boolean moveToFirst() { - return this.moveToPosition(0); - } - - @Override - public boolean moveToLast() { - return this.moveToPosition(this.count - 1); - } - - private int getPostFilteredPosition(int preFilteredPosition) { - return preFilteredPosition < this.pushCount - ? this.pushIndex[preFilteredPosition] - : this.normalIndex[preFilteredPosition - pushCount]; - } - - @Override - public boolean moveToPosition(int position) { - if (position >= this.count || position < 0) - return false; - pos = position; - return super.moveToPosition(getPostFilteredPosition(position)); - } - - @Override - public int getCount() { - return this.count; - } - - public int getPushCount() { - return this.pushCount; - } - - @Override - public int getPosition() { - return this.pos; - } - -} \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/gcm/GcmIntentService.java b/src/org/thoughtcrime/securesms/gcm/GcmIntentService.java index 859ba5ee98f..596b50ea022 100644 --- a/src/org/thoughtcrime/securesms/gcm/GcmIntentService.java +++ b/src/org/thoughtcrime/securesms/gcm/GcmIntentService.java @@ -14,6 +14,7 @@ import org.whispersystems.textsecure.crypto.InvalidVersionException; import org.whispersystems.textsecure.directory.Directory; import org.whispersystems.textsecure.directory.NotInDirectoryException; +import org.whispersystems.textsecure.push.ContactNumberDetails; import org.whispersystems.textsecure.push.ContactTokenDetails; import org.whispersystems.textsecure.push.IncomingEncryptedPushMessage; import org.whispersystems.textsecure.push.IncomingPushMessage; @@ -68,9 +69,9 @@ protected void onMessage(Context context, Intent intent) { if (!isActiveNumber(context, message.getSource())) { Directory directory = Directory.getInstance(context); - String contactToken = directory.getToken(message.getSource()); - ContactTokenDetails contactTokenDetails = new ContactTokenDetails(contactToken, message.getRelay()); - directory.setToken(contactTokenDetails, true); + String contactNumber = message.getSource(); + ContactNumberDetails contactNumberDetails = new ContactNumberDetails(contactNumber, message.getRelay()); + directory.setNumber(contactNumberDetails, true); } Intent service = new Intent(context, SendReceiveService.class); diff --git a/src/org/thoughtcrime/securesms/service/DirectoryRefreshService.java b/src/org/thoughtcrime/securesms/service/DirectoryRefreshService.java index a815b411114..d6f50a591d1 100644 --- a/src/org/thoughtcrime/securesms/service/DirectoryRefreshService.java +++ b/src/org/thoughtcrime/securesms/service/DirectoryRefreshService.java @@ -7,16 +7,9 @@ import android.os.PowerManager; import android.util.Log; -import org.thoughtcrime.securesms.Release; import org.thoughtcrime.securesms.push.PushServiceSocketFactory; -import org.thoughtcrime.securesms.util.TextSecurePreferences; +import org.thoughtcrime.securesms.util.DirectoryHelper; -import org.whispersystems.textsecure.directory.Directory; -import org.whispersystems.textsecure.push.ContactTokenDetails; -import org.whispersystems.textsecure.push.PushServiceSocket; - -import java.util.List; -import java.util.Set; import java.util.concurrent.Executor; import java.util.concurrent.Executors; @@ -59,19 +52,8 @@ public RefreshRunnable(PowerManager.WakeLock wakeLock) { public void run() { try { Log.w("DirectoryRefreshService", "Refreshing directory..."); - Directory directory = Directory.getInstance(context); - PushServiceSocket socket = PushServiceSocketFactory.create(context); - - Set eligibleContactTokens = directory.getPushEligibleContactTokens(TextSecurePreferences.getLocalNumber(context)); - List activeTokens = socket.retrieveDirectory(eligibleContactTokens); - - if (activeTokens != null) { - for (ContactTokenDetails activeToken : activeTokens) { - eligibleContactTokens.remove(activeToken.getToken()); - } - directory.setTokens(activeTokens, eligibleContactTokens); - } + DirectoryHelper.refreshDirectory(context); Log.w("DirectoryRefreshService", "Directory refresh complete..."); } finally { diff --git a/src/org/thoughtcrime/securesms/service/RegistrationService.java b/src/org/thoughtcrime/securesms/service/RegistrationService.java index ad4a0b5bbc4..bddde2133a7 100644 --- a/src/org/thoughtcrime/securesms/service/RegistrationService.java +++ b/src/org/thoughtcrime/securesms/service/RegistrationService.java @@ -17,13 +17,12 @@ import org.thoughtcrime.securesms.gcm.GcmIntentService; import org.thoughtcrime.securesms.gcm.GcmRegistrationTimeoutException; import org.thoughtcrime.securesms.push.PushServiceSocketFactory; +import org.thoughtcrime.securesms.util.DirectoryHelper; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.textsecure.crypto.IdentityKey; import org.whispersystems.textsecure.crypto.MasterSecret; import org.whispersystems.textsecure.crypto.PreKeyUtil; import org.whispersystems.textsecure.crypto.ecc.Curve; -import org.whispersystems.textsecure.directory.Directory; -import org.whispersystems.textsecure.push.ContactTokenDetails; import org.whispersystems.textsecure.push.PushServiceSocket; import org.whispersystems.textsecure.storage.PreKeyRecord; import org.whispersystems.textsecure.util.Util; @@ -286,15 +285,7 @@ private void handleCommonRegistration(MasterSecret masterSecret, PushServiceSock String gcmRegistrationId = waitForGcmRegistrationId(); socket.registerGcmId(gcmRegistrationId); - Set contactTokens = Directory.getInstance(this).getPushEligibleContactTokens(number); - List activeTokens = socket.retrieveDirectory(contactTokens); - - if (activeTokens != null) { - for (ContactTokenDetails activeToken : activeTokens) { - contactTokens.remove(activeToken.getToken()); - } - Directory.getInstance(this).setTokens(activeTokens, contactTokens); - } + DirectoryHelper.refreshDirectory(this, socket, number); DirectoryRefreshListener.schedule(this); } diff --git a/src/org/thoughtcrime/securesms/transport/UniversalTransport.java b/src/org/thoughtcrime/securesms/transport/UniversalTransport.java index 5da614301fa..c6734c77b37 100644 --- a/src/org/thoughtcrime/securesms/transport/UniversalTransport.java +++ b/src/org/thoughtcrime/securesms/transport/UniversalTransport.java @@ -29,8 +29,10 @@ import org.whispersystems.textsecure.crypto.MasterSecret; import org.whispersystems.textsecure.directory.Directory; import org.whispersystems.textsecure.directory.NotInDirectoryException; +import org.whispersystems.textsecure.push.ContactNumberDetails; import org.whispersystems.textsecure.push.ContactTokenDetails; import org.whispersystems.textsecure.push.PushServiceSocket; +import org.whispersystems.textsecure.util.DirectoryUtil; import org.whispersystems.textsecure.util.InvalidNumberException; import java.io.IOException; @@ -138,18 +140,13 @@ private boolean isPushTransport(String destination) { return directory.isActiveNumber(destination); } catch (NotInDirectoryException e) { try { - PushServiceSocket socket = PushServiceSocketFactory.create(context); - String contactToken = directory.getToken(destination); - ContactTokenDetails registeredUser = socket.getContactTokenDetails(contactToken); - - if (registeredUser == null) { - registeredUser = new ContactTokenDetails(contactToken); - directory.setToken(registeredUser, false); - return false; - } else { - directory.setToken(registeredUser, true); - return true; - } + PushServiceSocket socket = PushServiceSocketFactory.create(context); + ContactTokenDetails registeredUser = socket.getContactTokenDetails(DirectoryUtil.getDirectoryServerToken(destination)); + boolean registeredFound = !(registeredUser == null); + ContactNumberDetails numberDetails = new ContactNumberDetails(destination, registeredUser == null ? null : registeredUser.getRelay()); + + directory.setNumber(numberDetails, registeredFound); + return registeredFound; } catch (IOException e1) { Log.w("UniversalTransport", e1); return false; diff --git a/src/org/thoughtcrime/securesms/util/DirectoryHelper.java b/src/org/thoughtcrime/securesms/util/DirectoryHelper.java new file mode 100644 index 00000000000..8e9fb46c420 --- /dev/null +++ b/src/org/thoughtcrime/securesms/util/DirectoryHelper.java @@ -0,0 +1,43 @@ +package org.thoughtcrime.securesms.util; + +import android.content.Context; + +import org.thoughtcrime.securesms.push.PushServiceSocketFactory; +import org.whispersystems.textsecure.directory.Directory; +import org.whispersystems.textsecure.push.ContactNumberDetails; +import org.whispersystems.textsecure.push.ContactTokenDetails; +import org.whispersystems.textsecure.push.PushServiceSocket; +import org.whispersystems.textsecure.util.DirectoryUtil; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class DirectoryHelper { + + public static void refreshDirectory(final Context context) { + refreshDirectory(context, PushServiceSocketFactory.create(context)); + } + + public static void refreshDirectory(final Context context, final PushServiceSocket socket) { + refreshDirectory(context, socket, TextSecurePreferences.getLocalNumber(context)); + } + + public static void refreshDirectory(final Context context, final PushServiceSocket socket, final String localNumber) { + final Directory directory = Directory.getInstance(context); + + final Set eligibleContactNumbers = directory.getPushEligibleContactNumbers(localNumber); + + final Map tokenMap = DirectoryUtil.getDirectoryServerTokenMap(eligibleContactNumbers); + final List activeTokens = socket.retrieveDirectory(tokenMap.keySet()); + + if (activeTokens != null) { + final List activeNumbers = ContactNumberDetails.fromContactTokenDetailsList(activeTokens, tokenMap); + for (ContactTokenDetails activeToken : activeTokens) { + eligibleContactNumbers.remove(tokenMap.get(activeToken.getToken())); + } + + directory.setNumbers(activeNumbers, eligibleContactNumbers); + } + } +} diff --git a/src/org/thoughtcrime/securesms/util/Util.java b/src/org/thoughtcrime/securesms/util/Util.java index ae09e985fbd..7252124828c 100644 --- a/src/org/thoughtcrime/securesms/util/Util.java +++ b/src/org/thoughtcrime/securesms/util/Util.java @@ -23,16 +23,9 @@ import android.text.SpannableString; import android.text.style.StyleSpan; import android.util.Log; -import android.widget.EditText; import android.os.Build; import android.provider.Telephony; -import org.thoughtcrime.securesms.mms.MmsRadio; -import org.thoughtcrime.securesms.push.PushServiceSocketFactory; -import org.whispersystems.textsecure.directory.Directory; -import org.whispersystems.textsecure.directory.NotInDirectoryException; -import org.whispersystems.textsecure.push.ContactTokenDetails; -import org.whispersystems.textsecure.push.PushServiceSocket; import org.whispersystems.textsecure.util.InvalidNumberException; import org.whispersystems.textsecure.util.PhoneNumberFormatter; @@ -40,7 +33,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; -import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -156,31 +148,6 @@ public static boolean isDefaultSmsProvider(Context context){ (context.getPackageName().equals(Telephony.Sms.getDefaultSmsPackage(context))); } - public static boolean isPushTransport(Context context, String destination) { - Directory directory = Directory.getInstance(context); - - try { - return directory.isActiveNumber(destination); - } catch (NotInDirectoryException e) { - try { - PushServiceSocket socket = PushServiceSocketFactory.create(context); - String contactToken = directory.getToken(destination); - ContactTokenDetails registeredUser = socket.getContactTokenDetails(contactToken); - - if (registeredUser == null) { - registeredUser = new ContactTokenDetails(contactToken); - directory.setToken(registeredUser, false); - return false; - } else { - directory.setToken(registeredUser, true); - return true; - } - } catch (IOException e1) { - Log.w("UniversalTransport", e1); - return false; - } - } - } // public static Bitmap loadScaledBitmap(InputStream src, int targetWidth, int targetHeight) { // return BitmapFactory.decodeStream(src); //// BitmapFactory.Options options = new BitmapFactory.Options();