made file transfers cancelable
This commit is contained in:
parent
4ab558715c
commit
cc4f3702a8
|
@ -23,4 +23,6 @@ public interface Downloadable {
|
||||||
public int getProgress();
|
public int getProgress();
|
||||||
|
|
||||||
public String getMimeType();
|
public String getMimeType();
|
||||||
|
|
||||||
|
public void cancel();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2040,5 +2040,10 @@ public class XmppConnectionService extends Service {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ import eu.siacs.conversations.crypto.PgpEngine;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.entities.Contact;
|
import eu.siacs.conversations.entities.Contact;
|
||||||
import eu.siacs.conversations.entities.Conversation;
|
import eu.siacs.conversations.entities.Conversation;
|
||||||
|
import eu.siacs.conversations.entities.Downloadable;
|
||||||
import eu.siacs.conversations.entities.Message;
|
import eu.siacs.conversations.entities.Message;
|
||||||
import eu.siacs.conversations.entities.MucOptions;
|
import eu.siacs.conversations.entities.MucOptions;
|
||||||
import eu.siacs.conversations.entities.Presences;
|
import eu.siacs.conversations.entities.Presences;
|
||||||
|
@ -343,6 +344,7 @@ public class ConversationFragment extends Fragment {
|
||||||
MenuItem sendAgain = menu.findItem(R.id.send_again);
|
MenuItem sendAgain = menu.findItem(R.id.send_again);
|
||||||
MenuItem copyUrl = menu.findItem(R.id.copy_url);
|
MenuItem copyUrl = menu.findItem(R.id.copy_url);
|
||||||
MenuItem downloadImage = menu.findItem(R.id.download_image);
|
MenuItem downloadImage = menu.findItem(R.id.download_image);
|
||||||
|
MenuItem cancelTransmission = menu.findItem(R.id.cancel_transmission);
|
||||||
if (this.selectedMessage.getType() != Message.TYPE_TEXT
|
if (this.selectedMessage.getType() != Message.TYPE_TEXT
|
||||||
|| this.selectedMessage.getDownloadable() != null) {
|
|| this.selectedMessage.getDownloadable() != null) {
|
||||||
copyText.setVisible(false);
|
copyText.setVisible(false);
|
||||||
|
@ -359,12 +361,15 @@ public class ConversationFragment extends Fragment {
|
||||||
|| this.selectedMessage.getImageParams().url == null) {
|
|| this.selectedMessage.getImageParams().url == null) {
|
||||||
copyUrl.setVisible(false);
|
copyUrl.setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.selectedMessage.getType() != Message.TYPE_TEXT
|
if (this.selectedMessage.getType() != Message.TYPE_TEXT
|
||||||
|| this.selectedMessage.getDownloadable() != null
|
|| this.selectedMessage.getDownloadable() != null
|
||||||
|| !this.selectedMessage.bodyContainsDownloadable()) {
|
|| !this.selectedMessage.bodyContainsDownloadable()) {
|
||||||
downloadImage.setVisible(false);
|
downloadImage.setVisible(false);
|
||||||
}
|
}
|
||||||
|
if (this.selectedMessage.getDownloadable() == null
|
||||||
|
|| this.selectedMessage.getDownloadable().getStatus() == Downloadable.STATUS_DELETED) {
|
||||||
|
cancelTransmission.setVisible(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,6 +391,9 @@ public class ConversationFragment extends Fragment {
|
||||||
case R.id.download_image:
|
case R.id.download_image:
|
||||||
downloadImage(selectedMessage);
|
downloadImage(selectedMessage);
|
||||||
return true;
|
return true;
|
||||||
|
case R.id.cancel_transmission:
|
||||||
|
cancelTransmission(selectedMessage);
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
return super.onContextItemSelected(item);
|
return super.onContextItemSelected(item);
|
||||||
}
|
}
|
||||||
|
@ -428,6 +436,13 @@ public class ConversationFragment extends Fragment {
|
||||||
.createNewConnection(message);
|
.createNewConnection(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void cancelTransmission(Message message) {
|
||||||
|
Downloadable downloadable = message.getDownloadable();
|
||||||
|
if (downloadable!=null) {
|
||||||
|
downloadable.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void privateMessageWith(final Jid counterpart) {
|
protected void privateMessageWith(final Jid counterpart) {
|
||||||
this.mEditMessage.setText("");
|
this.mEditMessage.setText("");
|
||||||
this.conversation.setNextCounterpart(counterpart);
|
this.conversation.setNextCounterpart(counterpart);
|
||||||
|
|
|
@ -10,7 +10,6 @@ import java.util.Map.Entry;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -76,7 +75,7 @@ public class JingleConnection implements Downloadable {
|
||||||
@Override
|
@Override
|
||||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
public void onIqPacketReceived(Account account, IqPacket packet) {
|
||||||
if (packet.getType() == IqPacket.TYPE_ERROR) {
|
if (packet.getType() == IqPacket.TYPE_ERROR) {
|
||||||
cancel();
|
fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -115,7 +114,7 @@ public class JingleConnection implements Downloadable {
|
||||||
@Override
|
@Override
|
||||||
public void onFileTransferAborted() {
|
public void onFileTransferAborted() {
|
||||||
JingleConnection.this.sendCancel();
|
JingleConnection.this.sendCancel();
|
||||||
JingleConnection.this.cancel();
|
JingleConnection.this.fail();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -162,14 +161,14 @@ public class JingleConnection implements Downloadable {
|
||||||
Reason reason = packet.getReason();
|
Reason reason = packet.getReason();
|
||||||
if (reason != null) {
|
if (reason != null) {
|
||||||
if (reason.hasChild("cancel")) {
|
if (reason.hasChild("cancel")) {
|
||||||
this.cancel();
|
this.fail();
|
||||||
} else if (reason.hasChild("success")) {
|
} else if (reason.hasChild("success")) {
|
||||||
this.receiveSuccess();
|
this.receiveSuccess();
|
||||||
} else {
|
} else {
|
||||||
this.cancel();
|
this.fail();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.cancel();
|
this.fail();
|
||||||
}
|
}
|
||||||
} else if (packet.isAction("session-accept")) {
|
} else if (packet.isAction("session-accept")) {
|
||||||
returnResult = receiveAccept(packet);
|
returnResult = receiveAccept(packet);
|
||||||
|
@ -343,7 +342,7 @@ public class JingleConnection implements Downloadable {
|
||||||
byte[] key = conversation.getSymmetricKey();
|
byte[] key = conversation.getSymmetricKey();
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
this.sendCancel();
|
this.sendCancel();
|
||||||
this.cancel();
|
this.fail();
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
this.file.setKey(key);
|
this.file.setKey(key);
|
||||||
|
@ -352,11 +351,11 @@ public class JingleConnection implements Downloadable {
|
||||||
this.file.setExpectedSize(size);
|
this.file.setExpectedSize(size);
|
||||||
} else {
|
} else {
|
||||||
this.sendCancel();
|
this.sendCancel();
|
||||||
this.cancel();
|
this.fail();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.sendCancel();
|
this.sendCancel();
|
||||||
this.cancel();
|
this.fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,7 +494,7 @@ public class JingleConnection implements Downloadable {
|
||||||
} else {
|
} else {
|
||||||
Log.d(Config.LOGTAG, "activated connection not found");
|
Log.d(Config.LOGTAG, "activated connection not found");
|
||||||
this.sendCancel();
|
this.sendCancel();
|
||||||
this.cancel();
|
this.fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -542,7 +541,7 @@ public class JingleConnection implements Downloadable {
|
||||||
this.transport = connection;
|
this.transport = connection;
|
||||||
if (connection == null) {
|
if (connection == null) {
|
||||||
Log.d(Config.LOGTAG, "could not find suitable candidate");
|
Log.d(Config.LOGTAG, "could not find suitable candidate");
|
||||||
this.disconnect();
|
this.disconnectSocks5Connections();
|
||||||
if (this.initiator.equals(account.getJid())) {
|
if (this.initiator.equals(account.getJid())) {
|
||||||
this.sendFallbackToIbb();
|
this.sendFallbackToIbb();
|
||||||
}
|
}
|
||||||
|
@ -633,7 +632,7 @@ public class JingleConnection implements Downloadable {
|
||||||
reason.addChild("success");
|
reason.addChild("success");
|
||||||
packet.setReason(reason);
|
packet.setReason(reason);
|
||||||
this.sendJinglePacket(packet);
|
this.sendJinglePacket(packet);
|
||||||
this.disconnect();
|
this.disconnectSocks5Connections();
|
||||||
this.mJingleStatus = JINGLE_STATUS_FINISHED;
|
this.mJingleStatus = JINGLE_STATUS_FINISHED;
|
||||||
this.message.setStatus(Message.STATUS_RECEIVED);
|
this.message.setStatus(Message.STATUS_RECEIVED);
|
||||||
this.message.setDownloadable(null);
|
this.message.setDownloadable(null);
|
||||||
|
@ -710,13 +709,30 @@ public class JingleConnection implements Downloadable {
|
||||||
this.mJingleStatus = JINGLE_STATUS_FINISHED;
|
this.mJingleStatus = JINGLE_STATUS_FINISHED;
|
||||||
this.mXmppConnectionService.markMessage(this.message,
|
this.mXmppConnectionService.markMessage(this.message,
|
||||||
Message.STATUS_SEND);
|
Message.STATUS_SEND);
|
||||||
this.disconnect();
|
this.disconnectSocks5Connections();
|
||||||
this.mJingleConnectionManager.finishConnection(this);
|
this.mJingleConnectionManager.finishConnection(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
this.mJingleStatus = JINGLE_STATUS_CANCELED;
|
this.disconnectSocks5Connections();
|
||||||
this.disconnect();
|
if (this.transport != null && this.transport instanceof JingleInbandTransport) {
|
||||||
|
this.transport.disconnect();
|
||||||
|
}
|
||||||
|
this.sendCancel();
|
||||||
|
this.mJingleConnectionManager.finishConnection(this);
|
||||||
|
if (this.responder.equals(account.getJid())) {
|
||||||
|
this.mStatus = Downloadable.STATUS_FAILED;
|
||||||
|
this.mXmppConnectionService.updateConversationUi();
|
||||||
|
} else {
|
||||||
|
this.mXmppConnectionService.markMessage(this.message,
|
||||||
|
Message.STATUS_SEND_FAILED);
|
||||||
|
this.message.setDownloadable(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fail() {
|
||||||
|
this.mJingleStatus = JINGLE_STATUS_FAILED;
|
||||||
|
this.disconnectSocks5Connections();
|
||||||
if (this.message != null) {
|
if (this.message != null) {
|
||||||
if (this.responder.equals(account.getJid())) {
|
if (this.responder.equals(account.getJid())) {
|
||||||
this.mStatus = Downloadable.STATUS_FAILED;
|
this.mStatus = Downloadable.STATUS_FAILED;
|
||||||
|
@ -772,7 +788,7 @@ public class JingleConnection implements Downloadable {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void disconnect() {
|
private void disconnectSocks5Connections() {
|
||||||
Iterator<Entry<String, JingleSocks5Transport>> it = this.connections
|
Iterator<Entry<String, JingleSocks5Transport>> it = this.connections
|
||||||
.entrySet().iterator();
|
.entrySet().iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
|
|
|
@ -28,6 +28,8 @@ public class JingleInbandTransport extends JingleTransport {
|
||||||
|
|
||||||
private boolean established = false;
|
private boolean established = false;
|
||||||
|
|
||||||
|
private boolean connected = true;
|
||||||
|
|
||||||
private DownloadableFile file;
|
private DownloadableFile file;
|
||||||
private JingleConnection connection;
|
private JingleConnection connection;
|
||||||
|
|
||||||
|
@ -42,7 +44,7 @@ public class JingleInbandTransport extends JingleTransport {
|
||||||
private OnIqPacketReceived onAckReceived = new OnIqPacketReceived() {
|
private OnIqPacketReceived onAckReceived = new OnIqPacketReceived() {
|
||||||
@Override
|
@Override
|
||||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
public void onIqPacketReceived(Account account, IqPacket packet) {
|
||||||
if (packet.getType() == IqPacket.TYPE_RESULT) {
|
if (connected && packet.getType() == IqPacket.TYPE_RESULT) {
|
||||||
sendNextBlock();
|
sendNextBlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +66,7 @@ public class JingleInbandTransport extends JingleTransport {
|
||||||
open.setAttribute("sid", this.sessionId);
|
open.setAttribute("sid", this.sessionId);
|
||||||
open.setAttribute("stanza", "iq");
|
open.setAttribute("stanza", "iq");
|
||||||
open.setAttribute("block-size", Integer.toString(this.blockSize));
|
open.setAttribute("block-size", Integer.toString(this.blockSize));
|
||||||
|
this.connected = true;
|
||||||
this.account.getXmppConnection().sendIqPacket(iq,
|
this.account.getXmppConnection().sendIqPacket(iq,
|
||||||
new OnIqPacketReceived() {
|
new OnIqPacketReceived() {
|
||||||
|
|
||||||
|
@ -116,12 +118,19 @@ public class JingleInbandTransport extends JingleTransport {
|
||||||
callback.onFileTransferAborted();
|
callback.onFileTransferAborted();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.sendNextBlock();
|
if (this.connected) {
|
||||||
|
this.sendNextBlock();
|
||||||
|
}
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
callback.onFileTransferAborted();
|
callback.onFileTransferAborted();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnect() {
|
||||||
|
this.connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
private void sendNextBlock() {
|
private void sendNextBlock() {
|
||||||
byte[] buffer = new byte[this.bufferSize];
|
byte[] buffer = new byte[this.bufferSize];
|
||||||
try {
|
try {
|
||||||
|
@ -183,13 +192,14 @@ public class JingleInbandTransport extends JingleTransport {
|
||||||
if (payload.getName().equals("open")) {
|
if (payload.getName().equals("open")) {
|
||||||
if (!established) {
|
if (!established) {
|
||||||
established = true;
|
established = true;
|
||||||
|
connected = true;
|
||||||
this.account.getXmppConnection().sendIqPacket(
|
this.account.getXmppConnection().sendIqPacket(
|
||||||
packet.generateRespone(IqPacket.TYPE_RESULT), null);
|
packet.generateRespone(IqPacket.TYPE_RESULT), null);
|
||||||
} else {
|
} else {
|
||||||
this.account.getXmppConnection().sendIqPacket(
|
this.account.getXmppConnection().sendIqPacket(
|
||||||
packet.generateRespone(IqPacket.TYPE_ERROR), null);
|
packet.generateRespone(IqPacket.TYPE_ERROR), null);
|
||||||
}
|
}
|
||||||
} else if (payload.getName().equals("data")) {
|
} else if (connected && payload.getName().equals("data")) {
|
||||||
this.receiveNextBlock(payload.getContent());
|
this.receiveNextBlock(payload.getContent());
|
||||||
this.account.getXmppConnection().sendIqPacket(
|
this.account.getXmppConnection().sendIqPacket(
|
||||||
packet.generateRespone(IqPacket.TYPE_RESULT), null);
|
packet.generateRespone(IqPacket.TYPE_RESULT), null);
|
||||||
|
|
|
@ -10,4 +10,6 @@ public abstract class JingleTransport {
|
||||||
|
|
||||||
public abstract void send(final DownloadableFile file,
|
public abstract void send(final DownloadableFile file,
|
||||||
final OnFileTransmissionStatusChanged callback);
|
final OnFileTransmissionStatusChanged callback);
|
||||||
|
|
||||||
|
public abstract void disconnect();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,5 +16,8 @@
|
||||||
<item
|
<item
|
||||||
android:id="@+id/download_image"
|
android:id="@+id/download_image"
|
||||||
android:title="@string/download_image"/>
|
android:title="@string/download_image"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/cancel_transmission"
|
||||||
|
android:title="@string/cancel_transmission" />
|
||||||
|
|
||||||
</menu>
|
</menu>
|
|
@ -318,5 +318,6 @@
|
||||||
<string name="sending_file">sending (%1$d%% completed)</string>
|
<string name="sending_file">sending (%1$d%% completed)</string>
|
||||||
<string name="preparing_file">Preparing file for transmission</string>
|
<string name="preparing_file">Preparing file for transmission</string>
|
||||||
<string name="file_offered_for_download">File offered for download</string>
|
<string name="file_offered_for_download">File offered for download</string>
|
||||||
<string name="file">%s file</string>;
|
<string name="file">%s file</string>
|
||||||
|
<string name="cancel_transmission">Cancel transmission</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in New Issue