made file transfers cancelable

This commit is contained in:
iNPUTmice 2014-11-15 12:37:09 +01:00
parent 4ab558715c
commit cc4f3702a8
8 changed files with 76 additions and 22 deletions

View file

@ -23,4 +23,6 @@ public interface Downloadable {
public int getProgress(); public int getProgress();
public String getMimeType(); public String getMimeType();
public void cancel();
} }

View file

@ -2040,5 +2040,10 @@ public class XmppConnectionService extends Service {
return ""; return "";
} }
@Override
public void cancel() {
}
} }
} }

View file

@ -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);

View file

@ -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()) {

View file

@ -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;
} }
if (this.connected) {
this.sendNextBlock(); 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);

View file

@ -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();
} }

View file

@ -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>

View file

@ -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>