mirror of
https://github.com/oxen-io/session-android.git
synced 2025-04-29 19:10:46 +00:00
Add progress listener for attachments.
// FREEBIE
This commit is contained in:
parent
64833318da
commit
e7f1c52eb2
@ -18,6 +18,8 @@ package org.whispersystems.textsecure.api;
|
|||||||
|
|
||||||
import org.whispersystems.libaxolotl.InvalidMessageException;
|
import org.whispersystems.libaxolotl.InvalidMessageException;
|
||||||
import org.whispersystems.textsecure.api.crypto.AttachmentCipherInputStream;
|
import org.whispersystems.textsecure.api.crypto.AttachmentCipherInputStream;
|
||||||
|
import org.whispersystems.textsecure.api.messages.TextSecureAttachment;
|
||||||
|
import org.whispersystems.textsecure.api.messages.TextSecureAttachment.ProgressListener;
|
||||||
import org.whispersystems.textsecure.api.messages.TextSecureAttachmentPointer;
|
import org.whispersystems.textsecure.api.messages.TextSecureAttachmentPointer;
|
||||||
import org.whispersystems.textsecure.api.messages.TextSecureDataMessage;
|
import org.whispersystems.textsecure.api.messages.TextSecureDataMessage;
|
||||||
import org.whispersystems.textsecure.api.messages.TextSecureEnvelope;
|
import org.whispersystems.textsecure.api.messages.TextSecureEnvelope;
|
||||||
@ -88,10 +90,10 @@ public class TextSecureMessageReceiver {
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @throws InvalidMessageException
|
* @throws InvalidMessageException
|
||||||
*/
|
*/
|
||||||
public InputStream retrieveAttachment(TextSecureAttachmentPointer pointer, File destination)
|
public InputStream retrieveAttachment(TextSecureAttachmentPointer pointer, File destination, ProgressListener listener)
|
||||||
throws IOException, InvalidMessageException
|
throws IOException, InvalidMessageException
|
||||||
{
|
{
|
||||||
socket.retrieveAttachment(pointer.getRelay().orNull(), pointer.getId(), destination);
|
socket.retrieveAttachment(pointer.getRelay().orNull(), pointer.getId(), destination, listener);
|
||||||
return new AttachmentCipherInputStream(destination, pointer.getKey());
|
return new AttachmentCipherInputStream(destination, pointer.getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,6 +335,7 @@ public class TextSecureMessageSender {
|
|||||||
PushAttachmentData attachmentData = new PushAttachmentData(attachment.getContentType(),
|
PushAttachmentData attachmentData = new PushAttachmentData(attachment.getContentType(),
|
||||||
attachment.getInputStream(),
|
attachment.getInputStream(),
|
||||||
attachment.getLength(),
|
attachment.getLength(),
|
||||||
|
attachment.getListener(),
|
||||||
attachmentKey);
|
attachmentKey);
|
||||||
|
|
||||||
long attachmentId = socket.sendAttachment(attachmentData);
|
long attachmentId = socket.sendAttachment(attachmentData);
|
||||||
|
@ -47,9 +47,10 @@ public abstract class TextSecureAttachment {
|
|||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
private InputStream inputStream;
|
private InputStream inputStream;
|
||||||
private String contentType;
|
private String contentType;
|
||||||
private long length;
|
private long length;
|
||||||
|
private ProgressListener listener;
|
||||||
|
|
||||||
private Builder() {}
|
private Builder() {}
|
||||||
|
|
||||||
@ -68,12 +69,21 @@ public abstract class TextSecureAttachment {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder withListener(ProgressListener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public TextSecureAttachmentStream build() {
|
public TextSecureAttachmentStream build() {
|
||||||
if (inputStream == null) throw new IllegalArgumentException("Must specify stream!");
|
if (inputStream == null) throw new IllegalArgumentException("Must specify stream!");
|
||||||
if (contentType == null) throw new IllegalArgumentException("No content type specified!");
|
if (contentType == null) throw new IllegalArgumentException("No content type specified!");
|
||||||
if (length == 0) throw new IllegalArgumentException("No length specified!");
|
if (length == 0) throw new IllegalArgumentException("No length specified!");
|
||||||
|
|
||||||
return new TextSecureAttachmentStream(inputStream, contentType, length);
|
return new TextSecureAttachmentStream(inputStream, contentType, length, listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ProgressListener {
|
||||||
|
public void onAttachmentProgress(long total, long progress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,13 +23,15 @@ import java.io.InputStream;
|
|||||||
*/
|
*/
|
||||||
public class TextSecureAttachmentStream extends TextSecureAttachment {
|
public class TextSecureAttachmentStream extends TextSecureAttachment {
|
||||||
|
|
||||||
private final InputStream inputStream;
|
private final InputStream inputStream;
|
||||||
private final long length;
|
private final long length;
|
||||||
|
private final ProgressListener listener;
|
||||||
|
|
||||||
public TextSecureAttachmentStream(InputStream inputStream, String contentType, long length) {
|
public TextSecureAttachmentStream(InputStream inputStream, String contentType, long length, ProgressListener listener) {
|
||||||
super(contentType);
|
super(contentType);
|
||||||
this.inputStream = inputStream;
|
this.inputStream = inputStream;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
|
this.listener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -49,4 +51,8 @@ public class TextSecureAttachmentStream extends TextSecureAttachment {
|
|||||||
public long getLength() {
|
public long getLength() {
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ProgressListener getListener() {
|
||||||
|
return listener;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ public class DeviceContactsInputStream extends ChunkedInputStream {
|
|||||||
InputStream avatarStream = new LimitedInputStream(in, avatarLength);
|
InputStream avatarStream = new LimitedInputStream(in, avatarLength);
|
||||||
String avatarContentType = details.getAvatar().getContentType();
|
String avatarContentType = details.getAvatar().getContentType();
|
||||||
|
|
||||||
avatar = Optional.of(new TextSecureAttachmentStream(avatarStream, avatarContentType, avatarLength));
|
avatar = Optional.of(new TextSecureAttachmentStream(avatarStream, avatarContentType, avatarLength, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DeviceContact(number, name, avatar);
|
return new DeviceContact(number, name, avatar);
|
||||||
|
@ -36,7 +36,7 @@ public class DeviceGroupsInputStream extends ChunkedInputStream{
|
|||||||
InputStream avatarStream = new ChunkedInputStream.LimitedInputStream(in, avatarLength);
|
InputStream avatarStream = new ChunkedInputStream.LimitedInputStream(in, avatarLength);
|
||||||
String avatarContentType = details.getAvatar().getContentType();
|
String avatarContentType = details.getAvatar().getContentType();
|
||||||
|
|
||||||
avatar = Optional.of(new TextSecureAttachmentStream(avatarStream, avatarContentType, avatarLength));
|
avatar = Optional.of(new TextSecureAttachmentStream(avatarStream, avatarContentType, avatarLength, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DeviceGroup(id, name, members, avatar);
|
return new DeviceGroup(id, name, members, avatar);
|
||||||
|
@ -16,20 +16,26 @@
|
|||||||
*/
|
*/
|
||||||
package org.whispersystems.textsecure.internal.push;
|
package org.whispersystems.textsecure.internal.push;
|
||||||
|
|
||||||
|
import org.whispersystems.textsecure.api.messages.TextSecureAttachment.ProgressListener;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
public class PushAttachmentData {
|
public class PushAttachmentData {
|
||||||
|
|
||||||
private final String contentType;
|
private final String contentType;
|
||||||
private final InputStream data;
|
private final InputStream data;
|
||||||
private final long dataSize;
|
private final long dataSize;
|
||||||
private final byte[] key;
|
private final byte[] key;
|
||||||
|
private final ProgressListener listener;
|
||||||
|
|
||||||
public PushAttachmentData(String contentType, InputStream data, long dataSize, byte[] key) {
|
public PushAttachmentData(String contentType, InputStream data, long dataSize,
|
||||||
|
ProgressListener listener, byte[] key)
|
||||||
|
{
|
||||||
this.contentType = contentType;
|
this.contentType = contentType;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.dataSize = dataSize;
|
this.dataSize = dataSize;
|
||||||
this.key = key;
|
this.key = key;
|
||||||
|
this.listener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getContentType() {
|
public String getContentType() {
|
||||||
@ -47,4 +53,8 @@ public class PushAttachmentData {
|
|||||||
public byte[] getKey() {
|
public byte[] getKey() {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ProgressListener getListener() {
|
||||||
|
return listener;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,10 +27,11 @@ import org.whispersystems.libaxolotl.state.PreKeyRecord;
|
|||||||
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
|
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
|
||||||
import org.whispersystems.libaxolotl.util.guava.Optional;
|
import org.whispersystems.libaxolotl.util.guava.Optional;
|
||||||
import org.whispersystems.textsecure.api.crypto.AttachmentCipherOutputStream;
|
import org.whispersystems.textsecure.api.crypto.AttachmentCipherOutputStream;
|
||||||
|
import org.whispersystems.textsecure.api.messages.TextSecureAttachment.ProgressListener;
|
||||||
import org.whispersystems.textsecure.api.messages.multidevice.DeviceInfo;
|
import org.whispersystems.textsecure.api.messages.multidevice.DeviceInfo;
|
||||||
import org.whispersystems.textsecure.api.push.ContactTokenDetails;
|
import org.whispersystems.textsecure.api.push.ContactTokenDetails;
|
||||||
import org.whispersystems.textsecure.api.push.TextSecureAddress;
|
|
||||||
import org.whispersystems.textsecure.api.push.SignedPreKeyEntity;
|
import org.whispersystems.textsecure.api.push.SignedPreKeyEntity;
|
||||||
|
import org.whispersystems.textsecure.api.push.TextSecureAddress;
|
||||||
import org.whispersystems.textsecure.api.push.TrustStore;
|
import org.whispersystems.textsecure.api.push.TrustStore;
|
||||||
import org.whispersystems.textsecure.api.push.exceptions.AuthorizationFailedException;
|
import org.whispersystems.textsecure.api.push.exceptions.AuthorizationFailedException;
|
||||||
import org.whispersystems.textsecure.api.push.exceptions.ExpectationFailedException;
|
import org.whispersystems.textsecure.api.push.exceptions.ExpectationFailedException;
|
||||||
@ -335,12 +336,12 @@ public class PushServiceSocket {
|
|||||||
Log.w(TAG, "Got attachment content location: " + attachmentKey.getLocation());
|
Log.w(TAG, "Got attachment content location: " + attachmentKey.getLocation());
|
||||||
|
|
||||||
uploadAttachment("PUT", attachmentKey.getLocation(), attachment.getData(),
|
uploadAttachment("PUT", attachmentKey.getLocation(), attachment.getData(),
|
||||||
attachment.getDataSize(), attachment.getKey());
|
attachment.getDataSize(), attachment.getKey(), attachment.getListener());
|
||||||
|
|
||||||
return attachmentKey.getId();
|
return attachmentKey.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void retrieveAttachment(String relay, long attachmentId, File destination) throws IOException {
|
public void retrieveAttachment(String relay, long attachmentId, File destination, ProgressListener listener) throws IOException {
|
||||||
String path = String.format(ATTACHMENT_PATH, String.valueOf(attachmentId));
|
String path = String.format(ATTACHMENT_PATH, String.valueOf(attachmentId));
|
||||||
|
|
||||||
if (!Util.isEmpty(relay)) {
|
if (!Util.isEmpty(relay)) {
|
||||||
@ -352,7 +353,7 @@ public class PushServiceSocket {
|
|||||||
|
|
||||||
Log.w(TAG, "Attachment: " + attachmentId + " is at: " + descriptor.getLocation());
|
Log.w(TAG, "Attachment: " + attachmentId + " is at: " + descriptor.getLocation());
|
||||||
|
|
||||||
downloadExternalFile(descriptor.getLocation(), destination);
|
downloadExternalFile(descriptor.getLocation(), destination, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ContactTokenDetails> retrieveDirectory(Set<String> contactTokens)
|
public List<ContactTokenDetails> retrieveDirectory(Set<String> contactTokens)
|
||||||
@ -374,7 +375,7 @@ public class PushServiceSocket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void downloadExternalFile(String url, File localDestination)
|
private void downloadExternalFile(String url, File localDestination, ProgressListener listener)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
URL downloadUrl = new URL(url);
|
URL downloadUrl = new URL(url);
|
||||||
@ -388,13 +389,19 @@ public class PushServiceSocket {
|
|||||||
throw new NonSuccessfulResponseCodeException("Bad response: " + connection.getResponseCode());
|
throw new NonSuccessfulResponseCodeException("Bad response: " + connection.getResponseCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputStream output = new FileOutputStream(localDestination);
|
OutputStream output = new FileOutputStream(localDestination);
|
||||||
InputStream input = connection.getInputStream();
|
InputStream input = connection.getInputStream();
|
||||||
byte[] buffer = new byte[4096];
|
byte[] buffer = new byte[4096];
|
||||||
int read;
|
int contentLength = connection.getContentLength();
|
||||||
|
int read,totalRead = 0;
|
||||||
|
|
||||||
while ((read = input.read(buffer)) != -1) {
|
while ((read = input.read(buffer)) != -1) {
|
||||||
output.write(buffer, 0, read);
|
output.write(buffer, 0, read);
|
||||||
|
totalRead += read;
|
||||||
|
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onAttachmentProgress(contentLength, totalRead);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
output.close();
|
output.close();
|
||||||
@ -406,7 +413,8 @@ public class PushServiceSocket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void uploadAttachment(String method, String url, InputStream data, long dataSize, byte[] key)
|
private void uploadAttachment(String method, String url, InputStream data,
|
||||||
|
long dataSize, byte[] key, ProgressListener listener)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
URL uploadUrl = new URL(url);
|
URL uploadUrl = new URL(url);
|
||||||
@ -427,9 +435,21 @@ public class PushServiceSocket {
|
|||||||
try {
|
try {
|
||||||
OutputStream stream = connection.getOutputStream();
|
OutputStream stream = connection.getOutputStream();
|
||||||
AttachmentCipherOutputStream out = new AttachmentCipherOutputStream(key, stream);
|
AttachmentCipherOutputStream out = new AttachmentCipherOutputStream(key, stream);
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int read, written = 0;
|
||||||
|
|
||||||
Util.copy(data, out);
|
while ((read = data.read(buffer)) != -1) {
|
||||||
|
out.write(buffer, 0, read);
|
||||||
|
written += read;
|
||||||
|
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onAttachmentProgress(dataSize, written);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.close();
|
||||||
out.flush();
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
|
||||||
if (connection.getResponseCode() != 200) {
|
if (connection.getResponseCode() != 200) {
|
||||||
throw new IOException("Bad response: " + connection.getResponseCode() + " " + connection.getResponseMessage());
|
throw new IOException("Bad response: " + connection.getResponseCode() + " " + connection.getResponseMessage());
|
||||||
|
@ -96,7 +96,6 @@ public class Util {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void copy(InputStream in, OutputStream out) throws IOException {
|
public static void copy(InputStream in, OutputStream out) throws IOException {
|
||||||
byte[] buffer = new byte[4096];
|
byte[] buffer = new byte[4096];
|
||||||
int read;
|
int read;
|
||||||
@ -124,19 +123,4 @@ public class Util {
|
|||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] toVarint64(long value) {
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
if ((value & ~0x7FL) == 0) {
|
|
||||||
out.write((int) value);
|
|
||||||
return out.toByteArray();
|
|
||||||
} else {
|
|
||||||
out.write(((int) value & 0x7F) | 0x80);
|
|
||||||
value >>>= 7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user