parent
57cdbaedd6
commit
884d8b7f72
3 changed files with 204 additions and 52 deletions
|
@ -35,6 +35,7 @@ import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.push.ContactTokenDetails;
|
import org.whispersystems.signalservice.api.push.ContactTokenDetails;
|
||||||
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
||||||
|
@ -58,16 +59,16 @@ public class ContactsDatabase {
|
||||||
private static final String CALL_MIMETYPE = "vnd.android.cursor.item/vnd.org.thoughtcrime.securesms.call";
|
private static final String CALL_MIMETYPE = "vnd.android.cursor.item/vnd.org.thoughtcrime.securesms.call";
|
||||||
private static final String SYNC = "__TS";
|
private static final String SYNC = "__TS";
|
||||||
|
|
||||||
public static final String ID_COLUMN = "_id";
|
static final String ID_COLUMN = "_id";
|
||||||
public static final String NAME_COLUMN = "name";
|
static final String NAME_COLUMN = "name";
|
||||||
public static final String NUMBER_COLUMN = "number";
|
static final String NUMBER_COLUMN = "number";
|
||||||
public static final String NUMBER_TYPE_COLUMN = "number_type";
|
static final String NUMBER_TYPE_COLUMN = "number_type";
|
||||||
public static final String LABEL_COLUMN = "label";
|
static final String LABEL_COLUMN = "label";
|
||||||
public static final String CONTACT_TYPE_COLUMN = "contact_type";
|
static final String CONTACT_TYPE_COLUMN = "contact_type";
|
||||||
|
|
||||||
public static final int NORMAL_TYPE = 0;
|
static final int NORMAL_TYPE = 0;
|
||||||
public static final int PUSH_TYPE = 1;
|
static final int PUSH_TYPE = 1;
|
||||||
public static final int NEW_TYPE = 2;
|
static final int NEW_TYPE = 2;
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
|
@ -99,7 +100,8 @@ public class ContactsDatabase {
|
||||||
Log.w(TAG, "Adding number: " + registeredNumber);
|
Log.w(TAG, "Adding number: " + registeredNumber);
|
||||||
addedNumbers.add(registeredNumber);
|
addedNumbers.add(registeredNumber);
|
||||||
addTextSecureRawContact(operations, account, systemContactInfo.get().number,
|
addTextSecureRawContact(operations, account, systemContactInfo.get().number,
|
||||||
systemContactInfo.get().id, registeredContact.isVoice());
|
systemContactInfo.get().name, systemContactInfo.get().id,
|
||||||
|
registeredContact.isVoice());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,6 +120,11 @@ public class ContactsDatabase {
|
||||||
} else if (!tokenDetails.isVoice() && currentContactEntry.getValue().isVoiceSupported()) {
|
} else if (!tokenDetails.isVoice() && currentContactEntry.getValue().isVoiceSupported()) {
|
||||||
Log.w(TAG, "Removing voice support: " + currentContactEntry.getKey());
|
Log.w(TAG, "Removing voice support: " + currentContactEntry.getKey());
|
||||||
removeContactVoiceSupport(operations, currentContactEntry.getValue().getId());
|
removeContactVoiceSupport(operations, currentContactEntry.getValue().getId());
|
||||||
|
} else if (!Util.isStringEquals(currentContactEntry.getValue().getRawDisplayName(),
|
||||||
|
currentContactEntry.getValue().getAggregateDisplayName()))
|
||||||
|
{
|
||||||
|
Log.w(TAG, "Updating display name: " + currentContactEntry.getKey());
|
||||||
|
updateDisplayName(operations, currentContactEntry.getValue().getAggregateDisplayName(), currentContactEntry.getValue().getId(), currentContactEntry.getValue().getDisplayNameSource());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +135,7 @@ public class ContactsDatabase {
|
||||||
return addedNumbers;
|
return addedNumbers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NonNull Cursor querySystemContacts(String filter) {
|
@NonNull Cursor querySystemContacts(String filter) {
|
||||||
Uri uri;
|
Uri uri;
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(filter)) {
|
if (!TextUtils.isEmpty(filter)) {
|
||||||
|
@ -176,7 +183,7 @@ public class ContactsDatabase {
|
||||||
new Pair<String, Object>(CONTACT_TYPE_COLUMN, NORMAL_TYPE));
|
new Pair<String, Object>(CONTACT_TYPE_COLUMN, NORMAL_TYPE));
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NonNull Cursor queryTextSecureContacts(String filter) {
|
@NonNull Cursor queryTextSecureContacts(String filter) {
|
||||||
String[] projection = new String[] {ContactsContract.Data._ID,
|
String[] projection = new String[] {ContactsContract.Data._ID,
|
||||||
ContactsContract.Contacts.DISPLAY_NAME,
|
ContactsContract.Contacts.DISPLAY_NAME,
|
||||||
ContactsContract.Data.DATA1};
|
ContactsContract.Data.DATA1};
|
||||||
|
@ -231,6 +238,30 @@ public class ContactsDatabase {
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateDisplayName(List<ContentProviderOperation> operations,
|
||||||
|
@Nullable String displayName,
|
||||||
|
long rawContactId, int displayNameSource)
|
||||||
|
{
|
||||||
|
Uri dataUri = ContactsContract.Data.CONTENT_URI.buildUpon()
|
||||||
|
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
if (displayNameSource != ContactsContract.DisplayNameSources.STRUCTURED_NAME) {
|
||||||
|
operations.add(ContentProviderOperation.newInsert(dataUri)
|
||||||
|
.withValue(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, rawContactId)
|
||||||
|
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName)
|
||||||
|
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
|
||||||
|
.build());
|
||||||
|
} else {
|
||||||
|
operations.add(ContentProviderOperation.newUpdate(dataUri)
|
||||||
|
.withSelection(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?",
|
||||||
|
new String[] {String.valueOf(rawContactId), ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE})
|
||||||
|
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName)
|
||||||
|
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void removeContactVoiceSupport(List<ContentProviderOperation> operations, long rawContactId) {
|
private void removeContactVoiceSupport(List<ContentProviderOperation> operations, long rawContactId) {
|
||||||
operations.add(ContentProviderOperation.newUpdate(RawContacts.CONTENT_URI)
|
operations.add(ContentProviderOperation.newUpdate(RawContacts.CONTENT_URI)
|
||||||
.withSelection(RawContacts._ID + " = ?", new String[] {String.valueOf(rawContactId)})
|
.withSelection(RawContacts._ID + " = ?", new String[] {String.valueOf(rawContactId)})
|
||||||
|
@ -245,7 +276,7 @@ public class ContactsDatabase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addTextSecureRawContact(List<ContentProviderOperation> operations,
|
private void addTextSecureRawContact(List<ContentProviderOperation> operations,
|
||||||
Account account, String e164number,
|
Account account, String e164number, String displayName,
|
||||||
long aggregateId, boolean supportsVoice)
|
long aggregateId, boolean supportsVoice)
|
||||||
{
|
{
|
||||||
int index = operations.size();
|
int index = operations.size();
|
||||||
|
@ -260,6 +291,12 @@ public class ContactsDatabase {
|
||||||
.withValue(RawContacts.SYNC4, String.valueOf(supportsVoice))
|
.withValue(RawContacts.SYNC4, String.valueOf(supportsVoice))
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
|
operations.add(ContentProviderOperation.newInsert(dataUri)
|
||||||
|
.withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, index)
|
||||||
|
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName)
|
||||||
|
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
|
||||||
|
.build());
|
||||||
|
|
||||||
operations.add(ContentProviderOperation.newInsert(dataUri)
|
operations.add(ContentProviderOperation.newInsert(dataUri)
|
||||||
.withValueBackReference(ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID, index)
|
.withValueBackReference(ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID, index)
|
||||||
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
|
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
|
||||||
|
@ -321,7 +358,15 @@ public class ContactsDatabase {
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cursor = context.getContentResolver().query(currentContactsUri, new String[] {BaseColumns._ID, RawContacts.SYNC1, RawContacts.SYNC4}, null, null, null);
|
String[] projection;
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 11) {
|
||||||
|
projection = new String[] {BaseColumns._ID, RawContacts.SYNC1, RawContacts.SYNC4, RawContacts.CONTACT_ID, RawContacts.DISPLAY_NAME_PRIMARY, RawContacts.DISPLAY_NAME_SOURCE};
|
||||||
|
} else{
|
||||||
|
projection = new String[] {BaseColumns._ID, RawContacts.SYNC1, RawContacts.SYNC4, RawContacts.CONTACT_ID};
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor = context.getContentResolver().query(currentContactsUri, projection, null, null, null);
|
||||||
|
|
||||||
while (cursor != null && cursor.moveToNext()) {
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
String currentNumber;
|
String currentNumber;
|
||||||
|
@ -333,7 +378,20 @@ public class ContactsDatabase {
|
||||||
currentNumber = cursor.getString(1);
|
currentNumber = cursor.getString(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
signalContacts.put(currentNumber, new SignalContact(cursor.getLong(0), cursor.getString(2)));
|
long rawContactId = cursor.getLong(0);
|
||||||
|
long contactId = cursor.getLong(3);
|
||||||
|
String supportsVoice = cursor.getString(2);
|
||||||
|
String rawContactDisplayName = null;
|
||||||
|
String aggregateDisplayName = null;
|
||||||
|
int rawContactDisplayNameSource = 0;
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 11) {
|
||||||
|
rawContactDisplayName = cursor.getString(4);
|
||||||
|
rawContactDisplayNameSource = cursor.getInt(5);
|
||||||
|
aggregateDisplayName = getDisplayName(contactId);
|
||||||
|
}
|
||||||
|
|
||||||
|
signalContacts.put(currentNumber, new SignalContact(rawContactId, supportsVoice, rawContactDisplayName, aggregateDisplayName, rawContactDisplayNameSource));
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (cursor != null)
|
if (cursor != null)
|
||||||
|
@ -386,15 +444,33 @@ public class ContactsDatabase {
|
||||||
return Optional.absent();
|
return Optional.absent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private @Nullable String getDisplayName(long contactId) {
|
||||||
|
Cursor cursor = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
|
||||||
|
new String[]{ContactsContract.Contacts.DISPLAY_NAME},
|
||||||
|
ContactsContract.Contacts._ID + " = ?",
|
||||||
|
new String[] {String.valueOf(contactId)},
|
||||||
|
null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
return cursor.getString(0);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (cursor != null) cursor.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class ProjectionMappingCursor extends CursorWrapper {
|
private static class ProjectionMappingCursor extends CursorWrapper {
|
||||||
|
|
||||||
private final Map<String, String> projectionMap;
|
private final Map<String, String> projectionMap;
|
||||||
private final Pair<String, Object>[] extras;
|
private final Pair<String, Object>[] extras;
|
||||||
|
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
public ProjectionMappingCursor(Cursor cursor,
|
ProjectionMappingCursor(Cursor cursor,
|
||||||
Map<String, String> projectionMap,
|
Map<String, String> projectionMap,
|
||||||
Pair<String, Object>... extras)
|
Pair<String, Object>... extras)
|
||||||
{
|
{
|
||||||
super(cursor);
|
super(cursor);
|
||||||
this.projectionMap = projectionMap;
|
this.projectionMap = projectionMap;
|
||||||
|
@ -498,20 +574,46 @@ public class ContactsDatabase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SignalContact {
|
private static class SignalContact {
|
||||||
|
|
||||||
private final long id;
|
private final long id;
|
||||||
@Nullable private final String supportsVoice;
|
@Nullable private final String supportsVoice;
|
||||||
|
@Nullable private final String rawDisplayName;
|
||||||
|
@Nullable private final String aggregateDisplayName;
|
||||||
|
private final int displayNameSource;
|
||||||
|
|
||||||
public SignalContact(long id, @Nullable String supportsVoice) {
|
SignalContact(long id,
|
||||||
this.id = id;
|
@Nullable String supportsVoice,
|
||||||
this.supportsVoice = supportsVoice;
|
@Nullable String rawDisplayName,
|
||||||
|
@Nullable String aggregateDisplayName,
|
||||||
|
int displayNameSource)
|
||||||
|
{
|
||||||
|
this.id = id;
|
||||||
|
this.supportsVoice = supportsVoice;
|
||||||
|
this.rawDisplayName = rawDisplayName;
|
||||||
|
this.aggregateDisplayName = aggregateDisplayName;
|
||||||
|
this.displayNameSource = displayNameSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getId() {
|
public long getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isVoiceSupported() {
|
boolean isVoiceSupported() {
|
||||||
return "true".equals(supportsVoice);
|
return "true".equals(supportsVoice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
String getRawDisplayName() {
|
||||||
|
return rawDisplayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
String getAggregateDisplayName() {
|
||||||
|
return aggregateDisplayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getDisplayNameSource() {
|
||||||
|
return displayNameSource;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,22 +69,24 @@ public class DirectoryHelper {
|
||||||
public static void refreshDirectory(@NonNull Context context, @Nullable MasterSecret masterSecret)
|
public static void refreshDirectory(@NonNull Context context, @Nullable MasterSecret masterSecret)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
List<String> newUsers = refreshDirectory(context,
|
RefreshResult result = refreshDirectory(context,
|
||||||
AccountManagerFactory.createManager(context),
|
AccountManagerFactory.createManager(context),
|
||||||
TextSecurePreferences.getLocalNumber(context));
|
TextSecurePreferences.getLocalNumber(context));
|
||||||
|
|
||||||
if (!newUsers.isEmpty() && TextSecurePreferences.isMultiDevice(context)) {
|
if (!result.getNewUsers().isEmpty() && TextSecurePreferences.isMultiDevice(context)) {
|
||||||
ApplicationContext.getInstance(context)
|
ApplicationContext.getInstance(context)
|
||||||
.getJobManager()
|
.getJobManager()
|
||||||
.add(new MultiDeviceContactUpdateJob(context));
|
.add(new MultiDeviceContactUpdateJob(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyNewUsers(context, masterSecret, newUsers);
|
if (!result.isFresh()) {
|
||||||
|
notifyNewUsers(context, masterSecret, result.getNewUsers());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NonNull List<String> refreshDirectory(@NonNull Context context,
|
public static @NonNull RefreshResult refreshDirectory(@NonNull Context context,
|
||||||
@NonNull SignalServiceAccountManager accountManager,
|
@NonNull SignalServiceAccountManager accountManager,
|
||||||
@NonNull String localNumber)
|
@NonNull String localNumber)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
TextSecureDirectory directory = TextSecureDirectory.getInstance(context);
|
TextSecureDirectory directory = TextSecureDirectory.getInstance(context);
|
||||||
|
@ -101,7 +103,7 @@ public class DirectoryHelper {
|
||||||
return updateContactsDatabase(context, localNumber, activeTokens, true);
|
return updateContactsDatabase(context, localNumber, activeTokens, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LinkedList<>();
|
return new RefreshResult(new LinkedList<String>(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UserCapabilities refreshDirectoryFor(@NonNull Context context,
|
public static UserCapabilities refreshDirectoryFor(@NonNull Context context,
|
||||||
|
@ -119,13 +121,15 @@ public class DirectoryHelper {
|
||||||
if (details.isPresent()) {
|
if (details.isPresent()) {
|
||||||
directory.setNumber(details.get(), true);
|
directory.setNumber(details.get(), true);
|
||||||
|
|
||||||
List<String> newUsers = updateContactsDatabase(context, localNumber, details.get());
|
RefreshResult result = updateContactsDatabase(context, localNumber, details.get());
|
||||||
|
|
||||||
if (!newUsers.isEmpty() && TextSecurePreferences.isMultiDevice(context)) {
|
if (!result.getNewUsers().isEmpty() && TextSecurePreferences.isMultiDevice(context)) {
|
||||||
ApplicationContext.getInstance(context).getJobManager().add(new MultiDeviceContactUpdateJob(context));
|
ApplicationContext.getInstance(context).getJobManager().add(new MultiDeviceContactUpdateJob(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyNewUsers(context, masterSecret, newUsers);
|
if (!result.isFresh()) {
|
||||||
|
notifyNewUsers(context, masterSecret, result.getNewUsers());
|
||||||
|
}
|
||||||
|
|
||||||
return new UserCapabilities(Capability.SUPPORTED, details.get().isVoice() ? Capability.SUPPORTED : Capability.UNSUPPORTED);
|
return new UserCapabilities(Capability.SUPPORTED, details.get().isVoice() ? Capability.SUPPORTED : Capability.UNSUPPORTED);
|
||||||
} else {
|
} else {
|
||||||
|
@ -181,32 +185,34 @@ public class DirectoryHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @NonNull List<String> updateContactsDatabase(@NonNull Context context,
|
private static @NonNull RefreshResult updateContactsDatabase(@NonNull Context context,
|
||||||
@NonNull String localNumber,
|
@NonNull String localNumber,
|
||||||
@NonNull final ContactTokenDetails activeToken)
|
@NonNull final ContactTokenDetails activeToken)
|
||||||
{
|
{
|
||||||
return updateContactsDatabase(context, localNumber,
|
return updateContactsDatabase(context, localNumber,
|
||||||
new LinkedList<ContactTokenDetails>() {{add(activeToken);}},
|
new LinkedList<ContactTokenDetails>() {{add(activeToken);}},
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @NonNull List<String> updateContactsDatabase(@NonNull Context context,
|
private static @NonNull RefreshResult updateContactsDatabase(@NonNull Context context,
|
||||||
@NonNull String localNumber,
|
@NonNull String localNumber,
|
||||||
@NonNull List<ContactTokenDetails> activeTokens,
|
@NonNull List<ContactTokenDetails> activeTokens,
|
||||||
boolean removeMissing)
|
boolean removeMissing)
|
||||||
{
|
{
|
||||||
Optional<Account> account = getOrCreateAccount(context);
|
Optional<AccountHolder> account = getOrCreateAccount(context);
|
||||||
|
|
||||||
if (account.isPresent()) {
|
if (account.isPresent()) {
|
||||||
try {
|
try {
|
||||||
return DatabaseFactory.getContactsDatabase(context)
|
List<String> newUsers = DatabaseFactory.getContactsDatabase(context)
|
||||||
.setRegisteredUsers(account.get(), localNumber, activeTokens, removeMissing);
|
.setRegisteredUsers(account.get().getAccount(), localNumber, activeTokens, removeMissing);
|
||||||
|
|
||||||
|
return new RefreshResult(newUsers, account.get().isFresh());
|
||||||
} catch (RemoteException | OperationApplicationException e) {
|
} catch (RemoteException | OperationApplicationException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LinkedList<>();
|
return new RefreshResult(new LinkedList<String>(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void notifyNewUsers(@NonNull Context context,
|
private static void notifyNewUsers(@NonNull Context context,
|
||||||
|
@ -230,33 +236,73 @@ public class DirectoryHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Optional<Account> getOrCreateAccount(Context context) {
|
private static Optional<AccountHolder> getOrCreateAccount(Context context) {
|
||||||
AccountManager accountManager = AccountManager.get(context);
|
AccountManager accountManager = AccountManager.get(context);
|
||||||
Account[] accounts = accountManager.getAccountsByType("org.thoughtcrime.securesms");
|
Account[] accounts = accountManager.getAccountsByType("org.thoughtcrime.securesms");
|
||||||
|
|
||||||
Optional<Account> account;
|
Optional<AccountHolder> account;
|
||||||
|
|
||||||
if (accounts.length == 0) account = createAccount(context);
|
if (accounts.length == 0) account = createAccount(context);
|
||||||
else account = Optional.of(accounts[0]);
|
else account = Optional.of(new AccountHolder(accounts[0], false));
|
||||||
|
|
||||||
if (account.isPresent() && !ContentResolver.getSyncAutomatically(account.get(), ContactsContract.AUTHORITY)) {
|
if (account.isPresent() && !ContentResolver.getSyncAutomatically(account.get().getAccount(), ContactsContract.AUTHORITY)) {
|
||||||
ContentResolver.setSyncAutomatically(account.get(), ContactsContract.AUTHORITY, true);
|
ContentResolver.setSyncAutomatically(account.get().getAccount(), ContactsContract.AUTHORITY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return account;
|
return account;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Optional<Account> createAccount(Context context) {
|
private static Optional<AccountHolder> createAccount(Context context) {
|
||||||
AccountManager accountManager = AccountManager.get(context);
|
AccountManager accountManager = AccountManager.get(context);
|
||||||
Account account = new Account(context.getString(R.string.app_name), "org.thoughtcrime.securesms");
|
Account account = new Account(context.getString(R.string.app_name), "org.thoughtcrime.securesms");
|
||||||
|
|
||||||
if (accountManager.addAccountExplicitly(account, null, null)) {
|
if (accountManager.addAccountExplicitly(account, null, null)) {
|
||||||
Log.w(TAG, "Created new account...");
|
Log.w(TAG, "Created new account...");
|
||||||
ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1);
|
ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1);
|
||||||
return Optional.of(account);
|
return Optional.of(new AccountHolder(account, true));
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Failed to create account!");
|
Log.w(TAG, "Failed to create account!");
|
||||||
return Optional.absent();
|
return Optional.absent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class AccountHolder {
|
||||||
|
|
||||||
|
private final boolean fresh;
|
||||||
|
private final Account account;
|
||||||
|
|
||||||
|
private AccountHolder(Account account, boolean fresh) {
|
||||||
|
this.fresh = fresh;
|
||||||
|
this.account = account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFresh() {
|
||||||
|
return fresh;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Account getAccount() {
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class RefreshResult {
|
||||||
|
|
||||||
|
private final List<String> newUsers;
|
||||||
|
private final boolean fresh;
|
||||||
|
|
||||||
|
private RefreshResult(List<String> newUsers, boolean fresh) {
|
||||||
|
this.newUsers = newUsers;
|
||||||
|
this.fresh = fresh;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getNewUsers() {
|
||||||
|
return newUsers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFresh() {
|
||||||
|
return fresh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -455,4 +455,8 @@ public class Util {
|
||||||
return (int)value;
|
return (int)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isStringEquals(String first, String second) {
|
||||||
|
if (first == null) return second == null;
|
||||||
|
return first.equals(second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue