Java源码示例:org.whispersystems.signalservice.api.push.SignalServiceAddress
示例1
private OutgoingPushMessageList getEncryptedMessages(PushServiceSocket socket,
SignalServiceAddress recipient,
Optional<UnidentifiedAccess> unidentifiedAccess,
long timestamp,
byte[] plaintext,
boolean online)
throws IOException, InvalidKeyException, UntrustedIdentityException
{
List<OutgoingPushMessage> messages = new LinkedList<>();
if (!recipient.matches(localAddress) || unidentifiedAccess.isPresent()) {
messages.add(getEncryptedMessage(socket, recipient, unidentifiedAccess, SignalServiceAddress.DEFAULT_DEVICE_ID, plaintext));
}
for (int deviceId : store.getSubDeviceSessions(recipient.getIdentifier())) {
if (store.containsSession(new SignalProtocolAddress(recipient.getIdentifier(), deviceId))) {
messages.add(getEncryptedMessage(socket, recipient, unidentifiedAccess, deviceId, plaintext));
}
}
return new OutgoingPushMessageList(recipient.getIdentifier(), timestamp, messages, online);
}
示例2
private static boolean doParamsMatch(@NonNull SignalContactRecord contact,
@NonNull SignalServiceAddress address,
@NonNull String givenName,
@NonNull String familyName,
@Nullable byte[] profileKey,
@NonNull String username,
@Nullable IdentityState identityState,
@Nullable byte[] identityKey,
boolean blocked,
boolean profileSharing,
boolean archived)
{
return Objects.equals(contact.getAddress(), address) &&
Objects.equals(contact.getGivenName().or(""), givenName) &&
Objects.equals(contact.getFamilyName().or(""), familyName) &&
Arrays.equals(contact.getProfileKey().orNull(), profileKey) &&
Objects.equals(contact.getUsername().or(""), username) &&
Objects.equals(contact.getIdentityState(), identityState) &&
Arrays.equals(contact.getIdentityKey().orNull(), identityKey) &&
contact.isBlocked() == blocked &&
contact.isProfileSharingEnabled() == profileSharing &&
contact.isArchived() == archived;
}
示例3
public SentTranscriptMessage(Optional<SignalServiceAddress> destination, long timestamp, SignalServiceDataMessage message,
long expirationStartTimestamp, Map<SignalServiceAddress, Boolean> unidentifiedStatus,
boolean isRecipientUpdate)
{
this.destination = destination;
this.timestamp = timestamp;
this.message = message;
this.expirationStartTimestamp = expirationStartTimestamp;
this.unidentifiedStatusByUuid = new HashMap<>();
this.unidentifiedStatusByE164 = new HashMap<>();
this.recipients = unidentifiedStatus.keySet();
this.isRecipientUpdate = isRecipientUpdate;
for (Map.Entry<SignalServiceAddress, Boolean> entry : unidentifiedStatus.entrySet()) {
if (entry.getKey().getUuid().isPresent()) {
unidentifiedStatusByUuid.put(entry.getKey().getUuid().get().toString(), entry.getValue());
}
if (entry.getKey().getNumber().isPresent()) {
unidentifiedStatusByE164.put(entry.getKey().getNumber().get(), entry.getValue());
}
}
}
示例4
private Optional<UnidentifiedAccessPair> getAccessFor(SignalServiceAddress recipient) {
byte[] recipientUnidentifiedAccessKey = getTargetUnidentifiedAccessKey(recipient);
byte[] selfUnidentifiedAccessKey = getSelfUnidentifiedAccessKey();
byte[] selfUnidentifiedAccessCertificate = getSenderCertificate();
if (recipientUnidentifiedAccessKey == null || selfUnidentifiedAccessKey == null || selfUnidentifiedAccessCertificate == null) {
return Optional.absent();
}
try {
return Optional.of(new UnidentifiedAccessPair(
new UnidentifiedAccess(recipientUnidentifiedAccessKey, selfUnidentifiedAccessCertificate),
new UnidentifiedAccess(selfUnidentifiedAccessKey, selfUnidentifiedAccessCertificate)
));
} catch (InvalidCertificateException e) {
return Optional.absent();
}
}
示例5
/**
* Send a message to a group.
*
* @param recipients The group members.
* @param message The group message.
* @throws IOException
*/
public List<SendMessageResult> sendMessage(List<SignalServiceAddress> recipients,
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess,
boolean isRecipientUpdate,
SignalServiceDataMessage message)
throws IOException, UntrustedIdentityException
{
byte[] content = createMessageContent(message);
long timestamp = message.getTimestamp();
List<SendMessageResult> results = sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, content, false);
boolean needsSyncInResults = false;
for (SendMessageResult result : results) {
if (result.getSuccess() != null && result.getSuccess().isNeedsSync()) {
needsSyncInResults = true;
break;
}
}
if (needsSyncInResults || isMultiDevice.get()) {
byte[] syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.<SignalServiceAddress>absent(), timestamp, results, isRecipientUpdate);
sendMessage(localAddress, Optional.<UnidentifiedAccess>absent(), timestamp, syncMessage, false);
}
return results;
}
示例6
public DeviceContact(SignalServiceAddress address, Optional<String> name,
Optional<SignalServiceAttachmentStream> avatar,
Optional<String> color,
Optional<VerifiedMessage> verified,
Optional<byte[]> profileKey,
boolean blocked,
Optional<Integer> expirationTimer)
{
this.address = address;
this.name = name;
this.avatar = avatar;
this.color = color;
this.verified = verified;
this.profileKey = profileKey;
this.blocked = blocked;
this.expirationTimer = expirationTimer;
}
示例7
private byte[] createMultiDeviceBlockedContent(BlockedListMessage blocked) {
Content.Builder container = Content.newBuilder();
SyncMessage.Builder syncMessage = createSyncMessageBuilder();
SyncMessage.Blocked.Builder blockedMessage = SyncMessage.Blocked.newBuilder();
for (SignalServiceAddress address : blocked.getAddresses()) {
if (address.getUuid().isPresent()) {
blockedMessage.addUuids(address.getUuid().get().toString());
}
if (address.getNumber().isPresent()) {
blockedMessage.addNumbers(address.getNumber().get());
}
}
for (byte[] groupId : blocked.getGroupIds()) {
blockedMessage.addGroupIds(ByteString.copyFrom(groupId));
}
return container.setSyncMessage(syncMessage.setBlocked(blockedMessage)).build().toByteArray();
}
示例8
static String computeSafetyNumber(SignalServiceAddress ownAddress, IdentityKey ownIdentityKey, SignalServiceAddress theirAddress, IdentityKey theirIdentityKey) {
int version;
byte[] ownId;
byte[] theirId;
if (ServiceConfig.capabilities.isUuid()
&& ownAddress.getUuid().isPresent() && theirAddress.getUuid().isPresent()) {
// Version 2: UUID user
version = 2;
ownId = UuidUtil.toByteArray(ownAddress.getUuid().get());
theirId = UuidUtil.toByteArray(theirAddress.getUuid().get());
} else {
// Version 1: E164 user
version = 1;
if (!ownAddress.getNumber().isPresent() || !theirAddress.getNumber().isPresent()) {
return "INVALID ID";
}
ownId = ownAddress.getNumber().get().getBytes();
theirId = theirAddress.getNumber().get().getBytes();
}
Fingerprint fingerprint = new NumericFingerprintGenerator(5200).createFor(version, ownId, ownIdentityKey, theirId, theirIdentityKey);
return fingerprint.getDisplayableFingerprint().getDisplayText();
}
示例9
@WorkerThread
public static @NonNull ProfileAndCredential retrieveProfile(@NonNull Context context,
@NonNull Recipient recipient,
@NonNull SignalServiceProfile.RequestType requestType)
throws IOException
{
SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, recipient);
Optional<UnidentifiedAccess> unidentifiedAccess = getUnidentifiedAccess(context, recipient);
Optional<ProfileKey> profileKey = ProfileKeyUtil.profileKeyOptional(recipient.getProfileKey());
ProfileAndCredential profile;
try {
profile = retrieveProfileInternal(address, profileKey, unidentifiedAccess, requestType);
} catch (NonSuccessfulResponseCodeException e) {
if (unidentifiedAccess.isPresent()) {
profile = retrieveProfileInternal(address, profileKey, Optional.absent(), requestType);
} else {
throw e;
}
}
return profile;
}
示例10
/**
* Trust this the identity with this fingerprint
*
* @param name username of the identity
* @param fingerprint Fingerprint
*/
public boolean trustIdentityVerified(String name, byte[] fingerprint) throws InvalidNumberException {
SignalServiceAddress address = canonicalizeAndResolveSignalServiceAddress(name);
List<JsonIdentityKeyStore.Identity> ids = account.getSignalProtocolStore().getIdentities(address);
if (ids == null) {
return false;
}
for (JsonIdentityKeyStore.Identity id : ids) {
if (!Arrays.equals(id.getIdentityKey().serialize(), fingerprint)) {
continue;
}
account.getSignalProtocolStore().setIdentityTrustLevel(address, id.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED);
try {
sendVerifiedMessage(address, id.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED);
} catch (IOException | UntrustedIdentityException e) {
e.printStackTrace();
}
account.save();
return true;
}
return false;
}
示例11
public SignalServiceEnvelope(int type, Optional<SignalServiceAddress> sender, int senderDevice, long timestamp, byte[] legacyMessage, byte[] content, long serverTimestamp, String uuid) {
Envelope.Builder builder = Envelope.newBuilder()
.setType(Envelope.Type.valueOf(type))
.setSourceDevice(senderDevice)
.setTimestamp(timestamp)
.setServerTimestamp(serverTimestamp);
if (sender.isPresent()) {
if (sender.get().getUuid().isPresent()) {
builder.setSourceUuid(sender.get().getUuid().get().toString());
}
if (sender.get().getNumber().isPresent()) {
builder.setSourceE164(sender.get().getNumber().get());
}
}
if (uuid != null) {
builder.setServerGuid(uuid);
}
if (legacyMessage != null) builder.setLegacyMessage(ByteString.copyFrom(legacyMessage));
if (content != null) builder.setContent(ByteString.copyFrom(content));
this.envelope = builder.build();
}
示例12
public SignalServiceEnvelope(int type, Optional<SignalServiceAddress> sender, int senderDevice, long timestamp, byte[] legacyMessage, byte[] content, long serverTimestamp, String uuid) {
Envelope.Builder builder = Envelope.newBuilder()
.setType(Envelope.Type.valueOf(type))
.setSourceDevice(senderDevice)
.setTimestamp(timestamp)
.setServerTimestamp(serverTimestamp);
if (sender.isPresent()) {
if (sender.get().getUuid().isPresent()) {
builder.setSourceUuid(sender.get().getUuid().get().toString());
}
if (sender.get().getNumber().isPresent()) {
builder.setSourceE164(sender.get().getNumber().get());
}
}
if (uuid != null) {
builder.setServerGuid(uuid);
}
if (legacyMessage != null) builder.setLegacyMessage(ByteString.copyFrom(legacyMessage));
if (content != null) builder.setContent(ByteString.copyFrom(content));
this.envelope = builder.build();
}
示例13
private SignalServiceDataMessage.Quote createQuote(DataMessage content) {
if (!content.hasQuote()) return null;
List<SignalServiceDataMessage.Quote.QuotedAttachment> attachments = new LinkedList<>();
for (DataMessage.Quote.QuotedAttachment attachment : content.getQuote().getAttachmentsList()) {
attachments.add(new SignalServiceDataMessage.Quote.QuotedAttachment(attachment.getContentType(),
attachment.getFileName(),
attachment.hasThumbnail() ? createAttachmentPointer(attachment.getThumbnail()) : null));
}
if (SignalServiceAddress.isValidAddress(content.getQuote().getAuthorUuid(), content.getQuote().getAuthorE164())) {
SignalServiceAddress address = new SignalServiceAddress(UuidUtil.parseOrNull(content.getQuote().getAuthorUuid()), content.getQuote().getAuthorE164());
return new SignalServiceDataMessage.Quote(content.getQuote().getId(),
address,
content.getQuote().getText(),
attachments);
} else {
Log.w(TAG, "Quote was missing an author! Returning null.");
return null;
}
}
示例14
@Override
public Set<SignalServiceAddress> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
Set<SignalServiceAddress> addresses = new HashSet<>();
if (node.isArray()) {
for (JsonNode recipient : node) {
String recipientName = recipient.get("name").asText();
UUID uuid = UuidUtil.parseOrThrow(recipient.get("uuid").asText());
final SignalServiceAddress serviceAddress = new SignalServiceAddress(uuid, recipientName);
addresses.add(serviceAddress);
}
}
return addresses;
}
示例15
/**
* This method will do it's best to craft a fully-populated {@link SignalServiceAddress} based on
* the provided recipient. This includes performing a possible network request if no UUID is
* available.
*/
@WorkerThread
public static @NonNull SignalServiceAddress toSignalServiceAddress(@NonNull Context context, @NonNull Recipient recipient) {
recipient = recipient.resolve();
if (!recipient.getUuid().isPresent() && !recipient.getE164().isPresent()) {
throw new AssertionError(recipient.getId() + " - No UUID or phone number!");
}
if (FeatureFlags.uuids() && !recipient.getUuid().isPresent()) {
Log.i(TAG, recipient.getId() + " is missing a UUID...");
try {
RegisteredState state = DirectoryHelper.refreshDirectoryFor(context, recipient, false);
recipient = Recipient.resolved(recipient.getId());
Log.i(TAG, "Successfully performed a UUID fetch for " + recipient.getId() + ". Registered: " + state);
} catch (IOException e) {
Log.w(TAG, "Failed to fetch a UUID for " + recipient.getId() + ". Scheduling a future fetch and building an address without one.");
ApplicationDependencies.getJobManager().add(new DirectoryRefreshJob(recipient, false));
}
}
return new SignalServiceAddress(Optional.fromNullable(recipient.getUuid().orNull()), Optional.fromNullable(recipient.resolve().getE164().orNull()));
}
示例16
public @NonNull List<Integer> getSubDevices(@NonNull RecipientId recipientId) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
List<Integer> results = new LinkedList<>();
try (Cursor cursor = database.query(TABLE_NAME, new String[] {DEVICE},
RECIPIENT_ID + " = ?",
new String[] {recipientId.serialize()},
null, null, null))
{
while (cursor != null && cursor.moveToNext()) {
int device = cursor.getInt(cursor.getColumnIndexOrThrow(DEVICE));
if (device != SignalServiceAddress.DEFAULT_DEVICE_ID) {
results.add(device);
}
}
}
return results;
}
示例17
private OutgoingPushMessageList getEncryptedMessages(PushServiceSocket socket,
SignalServiceAddress recipient,
Optional<UnidentifiedAccess> unidentifiedAccess,
long timestamp,
byte[] plaintext,
boolean online)
throws IOException, InvalidKeyException, UntrustedIdentityException
{
List<OutgoingPushMessage> messages = new LinkedList<>();
if (!recipient.matches(localAddress) || unidentifiedAccess.isPresent()) {
messages.add(getEncryptedMessage(socket, recipient, unidentifiedAccess, SignalServiceAddress.DEFAULT_DEVICE_ID, plaintext));
}
for (int deviceId : store.getSubDeviceSessions(recipient.getIdentifier())) {
if (store.containsSession(new SignalProtocolAddress(recipient.getIdentifier(), deviceId))) {
messages.add(getEncryptedMessage(socket, recipient, unidentifiedAccess, deviceId, plaintext));
}
}
return new OutgoingPushMessageList(recipient.getIdentifier(), timestamp, messages, online);
}
示例18
private void handleInvalidMessage(@NonNull SignalServiceAddress sender,
int senderDevice,
@NonNull Optional<GroupId> groupId,
long timestamp,
@NonNull Optional<Long> smsMessageId)
{
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
if (!smsMessageId.isPresent()) {
Optional<InsertResult> insertResult = insertPlaceholder(sender.getIdentifier(), senderDevice, timestamp, groupId);
if (insertResult.isPresent()) {
smsDatabase.markAsInvalidMessage(insertResult.get().getMessageId());
ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId());
}
} else {
smsDatabase.markAsNoSession(smsMessageId.get());
}
}
示例19
public SignalServiceEnvelope getNext() {
try {
if (cursor == null || !cursor.moveToNext())
return null;
int type = cursor.getInt(cursor.getColumnIndexOrThrow(TYPE));
String sourceUuid = cursor.getString(cursor.getColumnIndexOrThrow(SOURCE_UUID));
String sourceE164 = cursor.getString(cursor.getColumnIndexOrThrow(SOURCE_E164));
int deviceId = cursor.getInt(cursor.getColumnIndexOrThrow(DEVICE_ID));
String legacyMessage = cursor.getString(cursor.getColumnIndexOrThrow(LEGACY_MSG));
String content = cursor.getString(cursor.getColumnIndexOrThrow(CONTENT));
long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP));
long serverTimestamp = cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_TIMESTAMP));
String serverGuid = cursor.getString(cursor.getColumnIndexOrThrow(SERVER_GUID));
return new SignalServiceEnvelope(type,
SignalServiceAddress.fromRaw(sourceUuid, sourceE164),
deviceId,
timestamp,
legacyMessage != null ? Base64.decode(legacyMessage) : null,
content != null ? Base64.decode(content) : null,
serverTimestamp,
serverGuid);
} catch (IOException e) {
throw new AssertionError(e);
}
}
示例20
/**
* Send a typing indicator.
*
* @param recipient The destination
* @param message The typing indicator to deliver
* @throws IOException
* @throws UntrustedIdentityException
*/
public void sendTyping(SignalServiceAddress recipient,
Optional<UnidentifiedAccessPair> unidentifiedAccess,
SignalServiceTypingMessage message)
throws IOException, UntrustedIdentityException
{
byte[] content = createTypingContent(message);
sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), message.getTimestamp(), content, true);
}
示例21
private SignalServiceAddress resolveSignalServiceAddress(String identifier) {
if (resolver != null) {
return resolver.resolveSignalServiceAddress(identifier);
} else {
return Util.getSignalServiceAddressFromIdentifier(identifier);
}
}
示例22
/**
* Send a call setup message to a single recipient.
*
* @param recipient The message's destination.
* @param message The call message.
* @throws IOException
*/
public void sendCallMessage(SignalServiceAddress recipient,
Optional<UnidentifiedAccessPair> unidentifiedAccess,
SignalServiceCallMessage message)
throws IOException, UntrustedIdentityException
{
byte[] content = createCallContent(message);
sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), content, false);
}
示例23
/**
* Send a message to a single recipient.
*
* @param recipient The message's destination.
* @param message The message.
* @throws UntrustedIdentityException
* @throws IOException
*/
public SendMessageResult sendMessage(SignalServiceAddress recipient,
Optional<UnidentifiedAccessPair> unidentifiedAccess,
SignalServiceDataMessage message)
throws UntrustedIdentityException, IOException
{
byte[] content = createMessageContent(message);
long timestamp = message.getTimestamp();
SendMessageResult result = sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, content, false);
if (result.getSuccess() != null && result.getSuccess().isNeedsSync()) {
byte[] syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.of(recipient), timestamp, Collections.singletonList(result), false);
sendMessage(localAddress, Optional.<UnidentifiedAccess>absent(), timestamp, syncMessage, false);
}
if (message.isEndSession()) {
if (recipient.getUuid().isPresent()) {
store.deleteAllSessions(recipient.getUuid().get().toString());
}
if (recipient.getNumber().isPresent()) {
store.deleteAllSessions(recipient.getNumber().get());
}
if (eventListener.isPresent()) {
eventListener.get().onSecurityEvent(recipient);
}
}
return result;
}
示例24
private SendMessageResult sendMessage(SignalServiceAddress address, SignalServiceDataMessage message) throws IOException {
SignalServiceMessageSender messageSender = getMessageSender();
try {
return messageSender.sendMessage(address, getAccessFor(address), message);
} catch (UntrustedIdentityException e) {
account.getSignalProtocolStore().saveIdentity(resolveSignalServiceAddress(e.getIdentifier()), e.getIdentityKey(), TrustLevel.UNTRUSTED);
return SendMessageResult.identityFailure(address, e.getIdentityKey());
}
}
示例25
private void handleStaleDevices(SignalServiceAddress recipient, StaleDevices staleDevices) {
for (int staleDeviceId : staleDevices.getStaleDevices()) {
if (recipient.getUuid().isPresent()) {
store.deleteSession(new SignalProtocolAddress(recipient.getUuid().get().toString(), staleDeviceId));
}
if (recipient.getNumber().isPresent()) {
store.deleteSession(new SignalProtocolAddress(recipient.getNumber().get(), staleDeviceId));
}
}
}
示例26
private static SignalProtocolAddress getPreferredProtocolAddress(SignalProtocolStore store, SignalServiceAddress address, int sourceDevice) {
SignalProtocolAddress uuidAddress = address.getUuid().isPresent() ? new SignalProtocolAddress(address.getUuid().get().toString(), sourceDevice) : null;
SignalProtocolAddress e164Address = address.getNumber().isPresent() ? new SignalProtocolAddress(address.getNumber().get(), sourceDevice) : null;
if (uuidAddress != null && store.containsSession(uuidAddress)) {
return uuidAddress;
} else if (e164Address != null && store.containsSession(e164Address)) {
return e164Address;
} else {
return new SignalProtocolAddress(address.getIdentifier(), sourceDevice);
}
}
示例27
private static @NonNull RecipientId findId(@NonNull SignalServiceAddress address,
@NonNull Map<String, Recipient> byE164,
@NonNull Map<UUID, Recipient> byUuid)
{
if (address.getNumber().isPresent() && byE164.containsKey(address.getNumber().get())) {
return Objects.requireNonNull(byE164.get(address.getNumber().get())).getId();
} else if (address.getUuid().isPresent() && byUuid.containsKey(address.getUuid().get())) {
return Objects.requireNonNull(byUuid.get(address.getUuid().get())).getId();
} else {
throw new IllegalStateException("Found an address that was never provided!");
}
}
示例28
@Test
public void merge_fillInGaps_treatNamePartsAsOneUnit() {
SignalContactRecord remote = new SignalContactRecord.Builder(byteArray(1), new SignalServiceAddress(UUID_A, null))
.setBlocked(true)
.setGivenName("AFirst")
.setFamilyName("")
.setProfileSharingEnabled(true)
.build();
SignalContactRecord local = new SignalContactRecord.Builder(byteArray(2), new SignalServiceAddress(UUID_B, E164_B))
.setBlocked(false)
.setIdentityKey(byteArray(2))
.setProfileKey(byteArray(3))
.setGivenName("BFirst")
.setFamilyName("BLast")
.setUsername("username B")
.setProfileSharingEnabled(false)
.build();
SignalContactRecord merged = new ContactConflictMerger(Collections.singletonList(local), SELF).merge(remote, local, mock(KeyGenerator.class));
assertEquals(UUID_A, merged.getAddress().getUuid().get());
assertEquals(E164_B, merged.getAddress().getNumber().get());
assertTrue(merged.isBlocked());
assertArrayEquals(byteArray(2), merged.getIdentityKey().get());
assertEquals(IdentityState.DEFAULT, merged.getIdentityState());
assertArrayEquals(byteArray(3), merged.getProfileKey().get());
assertEquals("AFirst", merged.getGivenName().get());
assertFalse(merged.getFamilyName().isPresent());
assertEquals("username B", merged.getUsername().get());
assertTrue(merged.isProfileSharingEnabled());
}
示例29
@Override
public void onRun() throws Exception {
if (!TextSecurePreferences.isReadReceiptsEnabled(accountContext)) return;
SignalServiceAddress remoteAddress = new SignalServiceAddress(address);
SignalServiceReceiptMessage receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.READ, messageIds, timestamp);
BcmChatCore.INSTANCE.sendReceipt(accountContext, remoteAddress, receiptMessage);
}
示例30
/**
* Send a call setup message to a single recipient.
*
* @param recipient The message's destination.
* @param message The call message.
* @throws IOException
*/
public void sendCallMessage(SignalServiceAddress recipient,
Optional<UnidentifiedAccessPair> unidentifiedAccess,
SignalServiceCallMessage message)
throws IOException, UntrustedIdentityException
{
byte[] content = createCallContent(message);
sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), content, false);
}