mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-21 07:09:56 +01:00
Refactor ContactExchangeTask into reusable manager.
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
package org.briarproject.bramble.api.contact;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.plugin.TransportId;
|
||||||
|
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
public interface ContactExchangeManager {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exchanges contact information with a remote peer.
|
||||||
|
*/
|
||||||
|
void exchangeContacts(TransportId t, DuplexTransportConnection conn,
|
||||||
|
SecretKey masterKey, boolean alice);
|
||||||
|
}
|
||||||
@@ -1,16 +1,6 @@
|
|||||||
package org.briarproject.bramble.api.contact;
|
package org.briarproject.bramble.contact;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
interface ContactExchangeConstants {
|
||||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|
||||||
import org.briarproject.bramble.api.plugin.TransportId;
|
|
||||||
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A task for conducting a contact information exchange with a remote peer.
|
|
||||||
*/
|
|
||||||
@NotNullByDefault
|
|
||||||
public interface ContactExchangeTask {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current version of the contact exchange protocol.
|
* The current version of the contact exchange protocol.
|
||||||
@@ -42,11 +32,4 @@ public interface ContactExchangeTask {
|
|||||||
* Label for signing key binding nonces.
|
* Label for signing key binding nonces.
|
||||||
*/
|
*/
|
||||||
String SIGNING_LABEL = "org.briarproject.briar.contact/EXCHANGE";
|
String SIGNING_LABEL = "org.briarproject.briar.contact/EXCHANGE";
|
||||||
|
|
||||||
/**
|
|
||||||
* Exchanges contact information with a remote peer.
|
|
||||||
*/
|
|
||||||
void exchangeContacts(LocalAuthor localAuthor, SecretKey masterKey,
|
|
||||||
DuplexTransportConnection conn, TransportId transportId,
|
|
||||||
boolean alice);
|
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@ package org.briarproject.bramble.contact;
|
|||||||
import org.briarproject.bramble.api.FormatException;
|
import org.briarproject.bramble.api.FormatException;
|
||||||
import org.briarproject.bramble.api.Predicate;
|
import org.briarproject.bramble.api.Predicate;
|
||||||
import org.briarproject.bramble.api.client.ClientHelper;
|
import org.briarproject.bramble.api.client.ClientHelper;
|
||||||
import org.briarproject.bramble.api.contact.ContactExchangeTask;
|
import org.briarproject.bramble.api.contact.ContactExchangeManager;
|
||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
import org.briarproject.bramble.api.contact.ContactManager;
|
import org.briarproject.bramble.api.contact.ContactManager;
|
||||||
import org.briarproject.bramble.api.contact.event.ContactExchangeFailedEvent;
|
import org.briarproject.bramble.api.contact.event.ContactExchangeFailedEvent;
|
||||||
@@ -17,6 +17,7 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
|
|||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.identity.Author;
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
|
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
@@ -49,16 +50,22 @@ import static java.util.logging.Level.WARNING;
|
|||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.briarproject.bramble.api.contact.RecordTypes.CONTACT_INFO;
|
import static org.briarproject.bramble.api.contact.RecordTypes.CONTACT_INFO;
|
||||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
|
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
|
||||||
|
import static org.briarproject.bramble.contact.ContactExchangeConstants.ALICE_KEY_LABEL;
|
||||||
|
import static org.briarproject.bramble.contact.ContactExchangeConstants.ALICE_NONCE_LABEL;
|
||||||
|
import static org.briarproject.bramble.contact.ContactExchangeConstants.BOB_KEY_LABEL;
|
||||||
|
import static org.briarproject.bramble.contact.ContactExchangeConstants.BOB_NONCE_LABEL;
|
||||||
|
import static org.briarproject.bramble.contact.ContactExchangeConstants.PROTOCOL_VERSION;
|
||||||
|
import static org.briarproject.bramble.contact.ContactExchangeConstants.SIGNING_LABEL;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.bramble.util.ValidationUtils.checkLength;
|
import static org.briarproject.bramble.util.ValidationUtils.checkLength;
|
||||||
import static org.briarproject.bramble.util.ValidationUtils.checkSize;
|
import static org.briarproject.bramble.util.ValidationUtils.checkSize;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
class ContactExchangeTaskImpl implements ContactExchangeTask {
|
class ContactExchangeManagerImpl implements ContactExchangeManager {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
getLogger(ContactExchangeTaskImpl.class.getName());
|
getLogger(ContactExchangeManagerImpl.class.getName());
|
||||||
|
|
||||||
// Accept records with current protocol version, known record type
|
// Accept records with current protocol version, known record type
|
||||||
private static final Predicate<Record> ACCEPT = r ->
|
private static final Predicate<Record> ACCEPT = r ->
|
||||||
@@ -82,17 +89,18 @@ class ContactExchangeTaskImpl implements ContactExchangeTask {
|
|||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
private final ConnectionManager connectionManager;
|
private final ConnectionManager connectionManager;
|
||||||
private final ContactManager contactManager;
|
private final ContactManager contactManager;
|
||||||
|
private final IdentityManager identityManager;
|
||||||
private final TransportPropertyManager transportPropertyManager;
|
private final TransportPropertyManager transportPropertyManager;
|
||||||
private final CryptoComponent crypto;
|
private final CryptoComponent crypto;
|
||||||
private final StreamReaderFactory streamReaderFactory;
|
private final StreamReaderFactory streamReaderFactory;
|
||||||
private final StreamWriterFactory streamWriterFactory;
|
private final StreamWriterFactory streamWriterFactory;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ContactExchangeTaskImpl(DatabaseComponent db, ClientHelper clientHelper,
|
ContactExchangeManagerImpl(DatabaseComponent db, ClientHelper clientHelper,
|
||||||
RecordReaderFactory recordReaderFactory,
|
RecordReaderFactory recordReaderFactory,
|
||||||
RecordWriterFactory recordWriterFactory, EventBus eventBus,
|
RecordWriterFactory recordWriterFactory, EventBus eventBus,
|
||||||
Clock clock, ConnectionManager connectionManager,
|
Clock clock, ConnectionManager connectionManager,
|
||||||
ContactManager contactManager,
|
ContactManager contactManager, IdentityManager identityManager,
|
||||||
TransportPropertyManager transportPropertyManager,
|
TransportPropertyManager transportPropertyManager,
|
||||||
CryptoComponent crypto, StreamReaderFactory streamReaderFactory,
|
CryptoComponent crypto, StreamReaderFactory streamReaderFactory,
|
||||||
StreamWriterFactory streamWriterFactory) {
|
StreamWriterFactory streamWriterFactory) {
|
||||||
@@ -104,6 +112,7 @@ class ContactExchangeTaskImpl implements ContactExchangeTask {
|
|||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
this.connectionManager = connectionManager;
|
this.connectionManager = connectionManager;
|
||||||
this.contactManager = contactManager;
|
this.contactManager = contactManager;
|
||||||
|
this.identityManager = identityManager;
|
||||||
this.transportPropertyManager = transportPropertyManager;
|
this.transportPropertyManager = transportPropertyManager;
|
||||||
this.crypto = crypto;
|
this.crypto = crypto;
|
||||||
this.streamReaderFactory = streamReaderFactory;
|
this.streamReaderFactory = streamReaderFactory;
|
||||||
@@ -111,9 +120,8 @@ class ContactExchangeTaskImpl implements ContactExchangeTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exchangeContacts(LocalAuthor localAuthor,
|
public void exchangeContacts(TransportId t, DuplexTransportConnection conn,
|
||||||
SecretKey masterKey, DuplexTransportConnection conn,
|
SecretKey masterKey, boolean alice) {
|
||||||
TransportId transportId, boolean alice) {
|
|
||||||
// Get the transport connection's input and output streams
|
// Get the transport connection's input and output streams
|
||||||
InputStream in;
|
InputStream in;
|
||||||
OutputStream out;
|
OutputStream out;
|
||||||
@@ -127,9 +135,11 @@ class ContactExchangeTaskImpl implements ContactExchangeTask {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the local transport properties
|
// Get the local author and transport properties
|
||||||
|
LocalAuthor localAuthor;
|
||||||
Map<TransportId, TransportProperties> localProperties;
|
Map<TransportId, TransportProperties> localProperties;
|
||||||
try {
|
try {
|
||||||
|
localAuthor = identityManager.getLocalAuthor();
|
||||||
localProperties = transportPropertyManager.getLocalProperties();
|
localProperties = transportPropertyManager.getLocalProperties();
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
@@ -210,8 +220,7 @@ class ContactExchangeTaskImpl implements ContactExchangeTask {
|
|||||||
ContactId contactId = addContact(remoteInfo.author, localAuthor,
|
ContactId contactId = addContact(remoteInfo.author, localAuthor,
|
||||||
masterKey, timestamp, alice, remoteInfo.properties);
|
masterKey, timestamp, alice, remoteInfo.properties);
|
||||||
// Reuse the connection as a transport connection
|
// Reuse the connection as a transport connection
|
||||||
connectionManager.manageOutgoingConnection(contactId, transportId,
|
connectionManager.manageOutgoingConnection(contactId, t, conn);
|
||||||
conn);
|
|
||||||
// Pseudonym exchange succeeded
|
// Pseudonym exchange succeeded
|
||||||
LOG.info("Pseudonym exchange succeeded");
|
LOG.info("Pseudonym exchange succeeded");
|
||||||
eventBus.broadcast(
|
eventBus.broadcast(
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package org.briarproject.bramble.contact;
|
package org.briarproject.bramble.contact;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.contact.ContactExchangeTask;
|
import org.briarproject.bramble.api.contact.ContactExchangeManager;
|
||||||
import org.briarproject.bramble.api.contact.ContactManager;
|
import org.briarproject.bramble.api.contact.ContactManager;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -19,14 +19,14 @@ public class ContactModule {
|
|||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
ContactManager getContactManager(ContactManagerImpl contactManager) {
|
ContactManager provideContactManager(ContactManagerImpl contactManager) {
|
||||||
return contactManager;
|
return contactManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
ContactExchangeTask provideContactExchangeTask(
|
ContactExchangeManager provideContactExchangeManager(
|
||||||
ContactExchangeTaskImpl contactExchangeTask) {
|
ContactExchangeManagerImpl contactExchangeManager) {
|
||||||
return contactExchangeTask;
|
return contactExchangeManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import org.briarproject.bramble.BrambleCoreEagerSingletons;
|
|||||||
import org.briarproject.bramble.BrambleCoreModule;
|
import org.briarproject.bramble.BrambleCoreModule;
|
||||||
import org.briarproject.bramble.account.BriarAccountModule;
|
import org.briarproject.bramble.account.BriarAccountModule;
|
||||||
import org.briarproject.bramble.api.account.AccountManager;
|
import org.briarproject.bramble.api.account.AccountManager;
|
||||||
import org.briarproject.bramble.api.contact.ContactExchangeTask;
|
import org.briarproject.bramble.api.contact.ContactExchangeManager;
|
||||||
import org.briarproject.bramble.api.contact.ContactManager;
|
import org.briarproject.bramble.api.contact.ContactManager;
|
||||||
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||||
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
|
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
|
||||||
@@ -128,7 +128,7 @@ public interface AndroidComponent
|
|||||||
|
|
||||||
SettingsManager settingsManager();
|
SettingsManager settingsManager();
|
||||||
|
|
||||||
ContactExchangeTask contactExchangeTask();
|
ContactExchangeManager contactExchangeManager();
|
||||||
|
|
||||||
KeyAgreementTask keyAgreementTask();
|
KeyAgreementTask keyAgreementTask();
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,12 @@ import android.os.Bundle;
|
|||||||
import android.support.annotation.UiThread;
|
import android.support.annotation.UiThread;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.contact.ContactExchangeTask;
|
import org.briarproject.bramble.api.contact.ContactExchangeManager;
|
||||||
import org.briarproject.bramble.api.contact.event.ContactExchangeFailedEvent;
|
import org.briarproject.bramble.api.contact.event.ContactExchangeFailedEvent;
|
||||||
import org.briarproject.bramble.api.contact.event.ContactExchangeSucceededEvent;
|
import org.briarproject.bramble.api.contact.event.ContactExchangeSucceededEvent;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
|
||||||
import org.briarproject.bramble.api.event.Event;
|
import org.briarproject.bramble.api.event.Event;
|
||||||
import org.briarproject.bramble.api.event.EventListener;
|
import org.briarproject.bramble.api.event.EventListener;
|
||||||
import org.briarproject.bramble.api.identity.Author;
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
|
||||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
|
||||||
import org.briarproject.bramble.api.keyagreement.KeyAgreementResult;
|
import org.briarproject.bramble.api.keyagreement.KeyAgreementResult;
|
||||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
@@ -21,32 +18,25 @@ import org.briarproject.briar.R;
|
|||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static android.widget.Toast.LENGTH_LONG;
|
import static android.widget.Toast.LENGTH_LONG;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.Objects.requireNonNull;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class ContactExchangeActivity extends KeyAgreementActivity implements
|
public class ContactExchangeActivity extends KeyAgreementActivity implements
|
||||||
EventListener {
|
EventListener {
|
||||||
|
|
||||||
private static final Logger LOG =
|
|
||||||
Logger.getLogger(ContactExchangeActivity.class.getName());
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@IoExecutor
|
@IoExecutor
|
||||||
Executor ioExecutor;
|
Executor ioExecutor;
|
||||||
|
|
||||||
// Fields that are accessed from background threads must be volatile
|
// Fields that are accessed from background threads must be volatile
|
||||||
@Inject
|
@Inject
|
||||||
volatile ContactExchangeTask contactExchangeTask;
|
volatile ContactExchangeManager contactExchangeManager;
|
||||||
@Inject
|
|
||||||
volatile IdentityManager identityManager;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void injectActivity(ActivityComponent component) {
|
public void injectActivity(ActivityComponent component) {
|
||||||
@@ -62,76 +52,62 @@ public class ContactExchangeActivity extends KeyAgreementActivity implements
|
|||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
// Listen to updates from contactExchangeTask
|
// Listen to updates from ContactExchangeManager
|
||||||
eventBus.addListener(this);
|
eventBus.addListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStop() {
|
protected void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
// Stop listening to updates from contactExchangeTask
|
// Stop listening to updates from ContactExchangeManager
|
||||||
eventBus.addListener(this);
|
eventBus.addListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startContactExchange(KeyAgreementResult result) {
|
private void startContactExchange(KeyAgreementResult result) {
|
||||||
ioExecutor.execute(() -> {
|
ioExecutor.execute(() -> {
|
||||||
LocalAuthor localAuthor;
|
|
||||||
// Load the local pseudonym
|
|
||||||
try {
|
|
||||||
localAuthor = identityManager.getLocalAuthor();
|
|
||||||
} catch (DbException e) {
|
|
||||||
logException(LOG, WARNING, e);
|
|
||||||
contactExchangeFailed();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Exchange contact details
|
// Exchange contact details
|
||||||
contactExchangeTask.exchangeContacts(localAuthor,
|
contactExchangeManager.exchangeContacts(result.getTransportId(),
|
||||||
result.getMasterKey(), result.getConnection(),
|
result.getConnection(), result.getMasterKey(),
|
||||||
result.getTransportId(), result.wasAlice());
|
result.wasAlice());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void eventOccurred(Event e) {
|
public void eventOccurred(Event e) {
|
||||||
if (e instanceof ContactExchangeSucceededEvent) {
|
if (e instanceof ContactExchangeSucceededEvent) {
|
||||||
contactExchangeSucceeded(
|
ContactExchangeSucceededEvent c = (ContactExchangeSucceededEvent) e;
|
||||||
((ContactExchangeSucceededEvent) e).getRemoteAuthor());
|
contactExchangeSucceeded(c.getRemoteAuthor());
|
||||||
} else if (e instanceof ContactExchangeFailedEvent) {
|
} else if (e instanceof ContactExchangeFailedEvent) {
|
||||||
ContactExchangeFailedEvent fe = (ContactExchangeFailedEvent) e;
|
ContactExchangeFailedEvent c = (ContactExchangeFailedEvent) e;
|
||||||
if (fe.wasDuplicateContact()) {
|
if (c.wasDuplicateContact()) {
|
||||||
duplicateContact(fe.getDuplicateRemoteAuthor());
|
duplicateContact(requireNonNull(c.getDuplicateRemoteAuthor()));
|
||||||
} else {
|
} else {
|
||||||
contactExchangeFailed();
|
contactExchangeFailed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
private void contactExchangeSucceeded(Author remoteAuthor) {
|
private void contactExchangeSucceeded(Author remoteAuthor) {
|
||||||
runOnUiThreadUnlessDestroyed(() -> {
|
String contactName = remoteAuthor.getName();
|
||||||
String contactName = remoteAuthor.getName();
|
String format = getString(R.string.contact_added_toast);
|
||||||
String format = getString(R.string.contact_added_toast);
|
String text = String.format(format, contactName);
|
||||||
String text = String.format(format, contactName);
|
Toast.makeText(this, text, LENGTH_LONG).show();
|
||||||
Toast.makeText(ContactExchangeActivity.this, text, LENGTH_LONG)
|
supportFinishAfterTransition();
|
||||||
.show();
|
|
||||||
supportFinishAfterTransition();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
private void duplicateContact(Author remoteAuthor) {
|
private void duplicateContact(Author remoteAuthor) {
|
||||||
runOnUiThreadUnlessDestroyed(() -> {
|
String contactName = remoteAuthor.getName();
|
||||||
String contactName = remoteAuthor.getName();
|
String format = getString(R.string.contact_already_exists);
|
||||||
String format = getString(R.string.contact_already_exists);
|
String text = String.format(format, contactName);
|
||||||
String text = String.format(format, contactName);
|
Toast.makeText(this, text, LENGTH_LONG).show();
|
||||||
Toast.makeText(ContactExchangeActivity.this, text, LENGTH_LONG)
|
finish();
|
||||||
.show();
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
private void contactExchangeFailed() {
|
private void contactExchangeFailed() {
|
||||||
runOnUiThreadUnlessDestroyed(() -> {
|
showErrorFragment(R.string.connection_error_explanation);
|
||||||
showErrorFragment(R.string.connection_error_explanation);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
|
|||||||
Reference in New Issue
Block a user