save images to external storage instead of internal. this requires more permissions. fixed #150 fixed #177 fixed #333 - this might need some more polish though

iNPUTmice created

Change summary

AndroidManifest.xml                                          |   2 
src/eu/siacs/conversations/entities/Account.java             |   1 
src/eu/siacs/conversations/persistance/FileBackend.java      |  45 
src/eu/siacs/conversations/services/ImageProvider.java       |   4 
src/eu/siacs/conversations/ui/adapter/MessageAdapter.java    |  20 
src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java | 628 +++--
6 files changed, 417 insertions(+), 283 deletions(-)

Detailed changes

AndroidManifest.xml 🔗

@@ -8,6 +8,8 @@
         android:minSdkVersion="14"
         android:targetSdkVersion="19" />
 
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_CONTACTS" />
     <uses-permission android:name="android.permission.READ_PROFILE" />
     <uses-permission android:name="android.permission.INTERNET" />

src/eu/siacs/conversations/entities/Account.java 🔗

@@ -20,7 +20,6 @@ import android.content.Context;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.net.Uri;
 
 public class Account  extends AbstractEntity{
 	

src/eu/siacs/conversations/persistance/FileBackend.java 🔗

@@ -20,6 +20,7 @@ import android.graphics.Matrix;
 import android.graphics.RectF;
 import android.media.ExifInterface;
 import android.net.Uri;
+import android.os.Environment;
 import android.util.Base64;
 import android.util.Base64OutputStream;
 import android.util.Log;
@@ -27,6 +28,7 @@ import android.util.LruCache;
 import eu.siacs.conversations.R;
 import eu.siacs.conversations.entities.Conversation;
 import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.services.ImageProvider;
 import eu.siacs.conversations.utils.CryptoHelper;
 import eu.siacs.conversations.xmpp.jingle.JingleFile;
 import eu.siacs.conversations.xmpp.pep.Avatar;
@@ -55,11 +57,11 @@ public class FileBackend {
 		return thumbnailCache;
 	}
 
-	public JingleFile getJingleFile(Message message) {
-		return getJingleFile(message, true);
+	public JingleFile getJingleFileLegacy(Message message) {
+		return getJingleFileLegacy(message, true);
 	}
 
-	public JingleFile getJingleFile(Message message, boolean decrypted) {
+	public JingleFile getJingleFileLegacy(Message message, boolean decrypted) {
 		Conversation conversation = message.getConversation();
 		String prefix = context.getFilesDir().getAbsolutePath();
 		String path = prefix + "/" + conversation.getAccount().getJid() + "/"
@@ -76,7 +78,28 @@ public class FileBackend {
 		}
 		return new JingleFile(path + "/" + filename);
 	}
+	
+	public JingleFile getJingleFile(Message message) {
+		return getJingleFile(message, true);
+	}
 
+	public JingleFile getJingleFile(Message message, boolean decrypted) {
+		StringBuilder filename = new StringBuilder();
+		filename.append(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath());
+		filename.append("/Conversations/");
+		filename.append(message.getUuid());
+		if ((decrypted) || (message.getEncryption() == Message.ENCRYPTION_NONE)) {
+			filename.append(".webp");
+		} else {
+			if (message.getEncryption() == Message.ENCRYPTION_OTR) {
+				filename.append(".webp");
+			} else {
+				filename.append(".webp.pgp");
+			}
+		}
+		return new JingleFile(filename.toString());
+	}
+	
 	public Bitmap resize(Bitmap originalBitmap, int size) {
 		int w = originalBitmap.getWidth();
 		int h = originalBitmap.getHeight();
@@ -190,8 +213,11 @@ public class FileBackend {
 			throws FileNotFoundException {
 		Bitmap thumbnail = thumbnailCache.get(message.getUuid());
 		if ((thumbnail == null) && (!cacheOnly)) {
-			Bitmap fullsize = BitmapFactory.decodeFile(getJingleFile(message)
-					.getAbsolutePath());
+			File file = getJingleFile(message);
+			if (!file.exists()) {
+				file = getJingleFileLegacy(message);
+			}
+			Bitmap fullsize = BitmapFactory.decodeFile(file.getAbsolutePath());
 			if (fullsize == null) {
 				throw new FileNotFoundException();
 			}
@@ -347,6 +373,15 @@ public class FileBackend {
 		return inSampleSize;
 
 	}
+	
+	public Uri getJingleFileUri(Message message) {
+		File file = getJingleFile(message);
+		if (file.exists()) {
+			return Uri.parse("file://"+file.getAbsolutePath());
+		} else {
+			return ImageProvider.getProviderUri(message);
+		}
+	}
 
 	public class ImageCopyException extends Exception {
 		private static final long serialVersionUID = -1010013599132881427L;

src/eu/siacs/conversations/services/ImageProvider.java 🔗

@@ -61,7 +61,7 @@ public class ImageProvider extends ContentProvider {
 			message.setConversation(conversation);
 			conversation.setAccount(account);
 	
-			File file = fileBackend.getJingleFile(message);
+			File file = fileBackend.getJingleFileLegacy(message);
 			pfd = ParcelFileDescriptor.open(file,
 					ParcelFileDescriptor.MODE_READ_ONLY);
 			return pfd;
@@ -110,7 +110,7 @@ public class ImageProvider extends ContentProvider {
 		return 0;
 	}
 	
-	public static Uri getContentUri(Message message) {
+	public static Uri getProviderUri(Message message) {
 		return Uri
 				.parse("content://eu.siacs.conversations.images/"
 						+ message.getConversationUuid()

src/eu/siacs/conversations/ui/adapter/MessageAdapter.java 🔗

@@ -52,8 +52,8 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 		if (this.accountBitmap == null) {
 
 			if (getCount() > 0) {
-				this.accountBitmap = getItem(0)
-						.getConversation().getAccount().getImage(getContext(), 48);
+				this.accountBitmap = getItem(0).getConversation().getAccount()
+						.getImage(getContext(), 48);
 			}
 		}
 		return this.accountBitmap;
@@ -237,8 +237,8 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 			@Override
 			public void onClick(View v) {
 				Intent intent = new Intent(Intent.ACTION_VIEW);
-				intent.setDataAndType(ImageProvider.getContentUri(message),
-						"image/*");
+				intent.setDataAndType(activity.xmppConnectionService
+						.getFileBackend().getJingleFileUri(message), "image/*");
 				getContext().startActivity(intent);
 			}
 		});
@@ -249,7 +249,8 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 				Intent shareIntent = new Intent();
 				shareIntent.setAction(Intent.ACTION_SEND);
 				shareIntent.putExtra(Intent.EXTRA_STREAM,
-						ImageProvider.getContentUri(message));
+						activity.xmppConnectionService.getFileBackend()
+								.getJingleFileUri(message));
 				shareIntent.setType("image/webp");
 				getContext().startActivity(
 						Intent.createChooser(shareIntent,
@@ -269,7 +270,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 			switch (type) {
 			case SENT:
 				view = (View) activity.getLayoutInflater().inflate(
-						R.layout.message_sent, parent,false);
+						R.layout.message_sent, parent, false);
 				viewHolder.message_box = (LinearLayout) view
 						.findViewById(R.id.message_box);
 				viewHolder.contact_picture = (ImageView) view
@@ -287,7 +288,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 				break;
 			case RECIEVED:
 				view = (View) activity.getLayoutInflater().inflate(
-						R.layout.message_recieved, parent,false);
+						R.layout.message_recieved, parent, false);
 				viewHolder.message_box = (LinearLayout) view
 						.findViewById(R.id.message_box);
 				viewHolder.contact_picture = (ImageView) view
@@ -314,7 +315,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 				break;
 			case STATUS:
 				view = (View) activity.getLayoutInflater().inflate(
-						R.layout.message_status, parent,false);
+						R.layout.message_status, parent, false);
 				viewHolder.contact_picture = (ImageView) view
 						.findViewById(R.id.message_photo);
 				if (item.getConversation().getMode() == Conversation.MODE_SINGLE) {
@@ -452,7 +453,8 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 
 		public Bitmap get(Contact contact, Context context) {
 			if (!contactBitmaps.containsKey(contact.getJid())) {
-				contactBitmaps.put(contact.getJid(), contact.getImage(48, context));
+				contactBitmaps.put(contact.getJid(),
+						contact.getImage(48, context));
 			}
 			return contactBitmaps.get(contact.getJid());
 		}

src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java 🔗

@@ -8,7 +8,9 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map.Entry;
 
+import android.content.Intent;
 import android.graphics.BitmapFactory;
+import android.net.Uri;
 import android.util.Log;
 import eu.siacs.conversations.entities.Account;
 import eu.siacs.conversations.entities.Conversation;
@@ -23,12 +25,12 @@ import eu.siacs.conversations.xmpp.stanzas.IqPacket;
 
 public class JingleConnection {
 
-	private final String[] extensions = {"webp","jpeg","jpg","png"};
-	private final String[] cryptoExtensions = {"pgp","gpg","otr"};
-	
+	private final String[] extensions = { "webp", "jpeg", "jpg", "png" };
+	private final String[] cryptoExtensions = { "pgp", "gpg", "otr" };
+
 	private JingleConnectionManager mJingleConnectionManager;
 	private XmppConnectionService mXmppConnectionService;
-	
+
 	public static final int STATUS_INITIATED = 0;
 	public static final int STATUS_ACCEPTED = 1;
 	public static final int STATUS_TERMINATED = 2;
@@ -36,9 +38,9 @@ public class JingleConnection {
 	public static final int STATUS_FINISHED = 4;
 	public static final int STATUS_TRANSMITTING = 5;
 	public static final int STATUS_FAILED = 99;
-	
+
 	private int ibbBlockSize = 4096;
-	
+
 	private int status = -1;
 	private Message message;
 	private String sessionId;
@@ -47,54 +49,64 @@ public class JingleConnection {
 	private String responder;
 	private List<JingleCandidate> candidates = new ArrayList<JingleCandidate>();
 	private HashMap<String, JingleSocks5Transport> connections = new HashMap<String, JingleSocks5Transport>();
-	
+
 	private String transportId;
 	private Element fileOffer;
 	private JingleFile file = null;
-	
+
 	private String contentName;
 	private String contentCreator;
-	
+
 	private boolean receivedCandidate = false;
 	private boolean sentCandidate = false;
-	
+
 	private boolean acceptedAutomatically = false;
-	
+
 	private JingleTransport transport = null;
-	
+
 	private OnIqPacketReceived responseListener = new OnIqPacketReceived() {
-		
+
 		@Override
 		public void onIqPacketReceived(Account account, IqPacket packet) {
 			if (packet.getType() == IqPacket.TYPE_ERROR) {
 				if (initiator.equals(account.getFullJid())) {
-					mXmppConnectionService.markMessage(message, Message.STATUS_SEND_FAILED);
+					mXmppConnectionService.markMessage(message,
+							Message.STATUS_SEND_FAILED);
 				}
 				status = STATUS_FAILED;
 			}
 		}
 	};
-	
+
 	final OnFileTransmissionStatusChanged onFileTransmissionSatusChanged = new OnFileTransmissionStatusChanged() {
-		
+
 		@Override
 		public void onFileTransmitted(JingleFile file) {
 			if (responder.equals(account.getFullJid())) {
 				sendSuccess();
 				if (acceptedAutomatically) {
 					message.markUnread();
-					JingleConnection.this.mXmppConnectionService.notifyUi(message.getConversation(), true);
+					JingleConnection.this.mXmppConnectionService.notifyUi(
+							message.getConversation(), true);
 				}
 				BitmapFactory.Options options = new BitmapFactory.Options();
 				options.inJustDecodeBounds = true;
-				BitmapFactory.decodeFile(file.getAbsolutePath(),options);
+				BitmapFactory.decodeFile(file.getAbsolutePath(), options);
 				int imageHeight = options.outHeight;
 				int imageWidth = options.outWidth;
-				message.setBody(""+file.getSize()+","+imageWidth+","+imageHeight);
+				message.setBody("" + file.getSize() + "," + imageWidth + ","
+						+ imageHeight);
 				mXmppConnectionService.databaseBackend.createMessage(message);
-				mXmppConnectionService.markMessage(message, Message.STATUS_RECIEVED);
+				mXmppConnectionService.markMessage(message,
+						Message.STATUS_RECIEVED);
+			}
+			Log.d("xmppService",
+					"sucessfully transmitted file:" + file.getAbsolutePath());
+			if (message.getEncryption()!=Message.ENCRYPTION_PGP) {
+				Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
+				intent.setData(Uri.fromFile(file));
+				mXmppConnectionService.sendBroadcast(intent);
 			}
-			Log.d("xmppService","sucessfully transmitted file:"+file.getAbsolutePath());
 		}
 
 		@Override
@@ -103,48 +115,49 @@ public class JingleConnection {
 			JingleConnection.this.cancel();
 		}
 	};
-	
+
 	private OnProxyActivated onProxyActivated = new OnProxyActivated() {
-		
+
 		@Override
 		public void success() {
 			if (initiator.equals(account.getFullJid())) {
-				Log.d("xmppService","we were initiating. sending file");
-				transport.send(file,onFileTransmissionSatusChanged);
+				Log.d("xmppService", "we were initiating. sending file");
+				transport.send(file, onFileTransmissionSatusChanged);
 			} else {
-				transport.receive(file,onFileTransmissionSatusChanged);
-				Log.d("xmppService","we were responding. receiving file");
+				transport.receive(file, onFileTransmissionSatusChanged);
+				Log.d("xmppService", "we were responding. receiving file");
 			}
 		}
-		
+
 		@Override
 		public void failed() {
-			Log.d("xmppService","proxy activation failed");
+			Log.d("xmppService", "proxy activation failed");
 		}
 	};
-	
+
 	public JingleConnection(JingleConnectionManager mJingleConnectionManager) {
 		this.mJingleConnectionManager = mJingleConnectionManager;
-		this.mXmppConnectionService = mJingleConnectionManager.getXmppConnectionService();
+		this.mXmppConnectionService = mJingleConnectionManager
+				.getXmppConnectionService();
 	}
-	
+
 	public String getSessionId() {
 		return this.sessionId;
 	}
-	
+
 	public String getAccountJid() {
 		return this.account.getFullJid();
 	}
-	
+
 	public String getCounterPart() {
 		return this.message.getCounterpart();
 	}
-	
+
 	public void deliverPacket(JinglePacket packet) {
 		boolean returnResult = true;
 		if (packet.isAction("session-terminate")) {
 			Reason reason = packet.getReason();
-			if (reason!=null) {
+			if (reason != null) {
 				if (reason.hasChild("cancel")) {
 					this.cancel();
 				} else if (reason.hasChild("success")) {
@@ -164,24 +177,26 @@ public class JingleConnection {
 				returnResult = this.receiveFallbackToIbb(packet);
 			} else {
 				returnResult = false;
-				Log.d("xmppService","trying to fallback to something unknown"+packet.toString());
+				Log.d("xmppService", "trying to fallback to something unknown"
+						+ packet.toString());
 			}
 		} else if (packet.isAction("transport-accept")) {
 			returnResult = this.receiveTransportAccept(packet);
 		} else {
-			Log.d("xmppService","packet arrived in connection. action was "+packet.getAction());
+			Log.d("xmppService", "packet arrived in connection. action was "
+					+ packet.getAction());
 			returnResult = false;
 		}
 		IqPacket response;
 		if (returnResult) {
 			response = packet.generateRespone(IqPacket.TYPE_RESULT);
-			
+
 		} else {
 			response = packet.generateRespone(IqPacket.TYPE_ERROR);
 		}
 		account.getXmppConnection().sendIqPacket(response, null);
 	}
-	
+
 	public void init(Message message) {
 		this.contentCreator = "initiator";
 		this.contentName = this.mJingleConnectionManager.nextRandomId();
@@ -193,42 +208,52 @@ public class JingleConnection {
 		if (this.candidates.size() > 0) {
 			this.sendInitRequest();
 		} else {
-			this.mJingleConnectionManager.getPrimaryCandidate(account, new OnPrimaryCandidateFound() {
-				
-				@Override
-				public void onPrimaryCandidateFound(boolean success, final JingleCandidate candidate) {
-					if (success) {
-						final JingleSocks5Transport socksConnection = new JingleSocks5Transport(JingleConnection.this, candidate);
-						connections.put(candidate.getCid(), socksConnection);
-						socksConnection.connect(new OnTransportConnected() {
-							
-							@Override
-							public void failed() {
-								Log.d("xmppService","connection to our own primary candidete failed");
-								sendInitRequest();
-							}
-							
-							@Override
-							public void established() {
-								Log.d("xmppService","succesfully connected to our own primary candidate");
+			this.mJingleConnectionManager.getPrimaryCandidate(account,
+					new OnPrimaryCandidateFound() {
+
+						@Override
+						public void onPrimaryCandidateFound(boolean success,
+								final JingleCandidate candidate) {
+							if (success) {
+								final JingleSocks5Transport socksConnection = new JingleSocks5Transport(
+										JingleConnection.this, candidate);
+								connections.put(candidate.getCid(),
+										socksConnection);
+								socksConnection
+										.connect(new OnTransportConnected() {
+
+											@Override
+											public void failed() {
+												Log.d("xmppService",
+														"connection to our own primary candidete failed");
+												sendInitRequest();
+											}
+
+											@Override
+											public void established() {
+												Log.d("xmppService",
+														"succesfully connected to our own primary candidate");
+												mergeCandidate(candidate);
+												sendInitRequest();
+											}
+										});
 								mergeCandidate(candidate);
+							} else {
+								Log.d("xmppService",
+										"no primary candidate of our own was found");
 								sendInitRequest();
 							}
-						});
-						mergeCandidate(candidate);
-					} else {
-						Log.d("xmppService","no primary candidate of our own was found");
-						sendInitRequest();
-					}
-				}
-			});
+						}
+					});
 		}
-		
+
 	}
-	
+
 	public void init(Account account, JinglePacket packet) {
 		this.status = STATUS_INITIATED;
-		Conversation conversation = this.mXmppConnectionService.findOrCreateConversation(account, packet.getFrom().split("/")[0], false);
+		Conversation conversation = this.mXmppConnectionService
+				.findOrCreateConversation(account,
+						packet.getFrom().split("/")[0], false);
 		this.message = new Message(conversation, "", Message.ENCRYPTION_NONE);
 		this.message.setType(Message.TYPE_IMAGE);
 		this.message.setStatus(Message.STATUS_RECEIVED_OFFER);
@@ -243,46 +268,62 @@ public class JingleConnection {
 		this.contentCreator = content.getAttribute("creator");
 		this.contentName = content.getAttribute("name");
 		this.transportId = content.getTransportId();
-		this.mergeCandidates(JingleCandidate.parse(content.socks5transport().getChildren()));
+		this.mergeCandidates(JingleCandidate.parse(content.socks5transport()
+				.getChildren()));
 		this.fileOffer = packet.getJingleContent().getFileOffer();
-		if (fileOffer!=null) {
+		if (fileOffer != null) {
 			Element fileSize = fileOffer.findChild("size");
 			Element fileNameElement = fileOffer.findChild("name");
-			if (fileNameElement!=null) {
+			if (fileNameElement != null) {
 				boolean supportedFile = false;
-				String[] filename = fileNameElement.getContent().toLowerCase(Locale.US).split("\\.");
-				if (Arrays.asList(this.extensions).contains(filename[filename.length - 1])) {
+				String[] filename = fileNameElement.getContent()
+						.toLowerCase(Locale.US).split("\\.");
+				if (Arrays.asList(this.extensions).contains(
+						filename[filename.length - 1])) {
 					supportedFile = true;
-				} else if (Arrays.asList(this.cryptoExtensions).contains(filename[filename.length - 1])) {
+				} else if (Arrays.asList(this.cryptoExtensions).contains(
+						filename[filename.length - 1])) {
 					if (filename.length == 3) {
-						if (Arrays.asList(this.extensions).contains(filename[filename.length -2])) {
+						if (Arrays.asList(this.extensions).contains(
+								filename[filename.length - 2])) {
 							supportedFile = true;
 							if (filename[filename.length - 1].equals("otr")) {
-								Log.d("xmppService","receiving otr file");
-								this.message.setEncryption(Message.ENCRYPTION_OTR);
+								Log.d("xmppService", "receiving otr file");
+								this.message
+										.setEncryption(Message.ENCRYPTION_OTR);
 							} else {
-								this.message.setEncryption(Message.ENCRYPTION_PGP);
+								this.message
+										.setEncryption(Message.ENCRYPTION_PGP);
 							}
 						}
 					}
 				}
 				if (supportedFile) {
 					long size = Long.parseLong(fileSize.getContent());
-					message.setBody(""+size);
+					message.setBody("" + size);
 					conversation.getMessages().add(message);
-					if (size<=this.mJingleConnectionManager.getAutoAcceptFileSize()) {
-						Log.d("xmppService","auto accepting file from "+packet.getFrom());
+					if (size <= this.mJingleConnectionManager
+							.getAutoAcceptFileSize()) {
+						Log.d("xmppService", "auto accepting file from "
+								+ packet.getFrom());
 						this.acceptedAutomatically = true;
 						this.sendAccept();
 					} else {
 						message.markUnread();
-						Log.d("xmppService","not auto accepting new file offer with size: "+size+" allowed size:"+this.mJingleConnectionManager.getAutoAcceptFileSize());
-						this.mXmppConnectionService.notifyUi(conversation, true);
+						Log.d("xmppService",
+								"not auto accepting new file offer with size: "
+										+ size
+										+ " allowed size:"
+										+ this.mJingleConnectionManager
+												.getAutoAcceptFileSize());
+						this.mXmppConnectionService
+								.notifyUi(conversation, true);
 					}
-					this.file = this.mXmppConnectionService.getFileBackend().getJingleFile(message,false);
+					this.file = this.mXmppConnectionService.getFileBackend()
+							.getJingleFile(message, false);
 					if (message.getEncryption() == Message.ENCRYPTION_OTR) {
 						byte[] key = conversation.getSymmetricKey();
-						if (key==null) {
+						if (key == null) {
 							this.sendCancel();
 							this.cancel();
 							return;
@@ -304,20 +345,21 @@ public class JingleConnection {
 			this.cancel();
 		}
 	}
-	
+
 	private void sendInitRequest() {
 		JinglePacket packet = this.bootstrapPacket("session-initiate");
-		Content content = new Content(this.contentCreator,this.contentName);
+		Content content = new Content(this.contentCreator, this.contentName);
 		if (message.getType() == Message.TYPE_IMAGE) {
 			content.setTransportId(this.transportId);
-			this.file = this.mXmppConnectionService.getFileBackend().getJingleFile(message,false);
+			this.file = this.mXmppConnectionService.getFileBackend()
+					.getJingleFile(message, false);
 			if (message.getEncryption() == Message.ENCRYPTION_OTR) {
 				Conversation conversation = this.message.getConversation();
 				this.mXmppConnectionService.renewSymmetricKey(conversation);
 				content.setFileOffer(this.file, true);
 				this.file.setKey(conversation.getSymmetricKey());
 			} else {
-				content.setFileOffer(this.file,false);
+				content.setFileOffer(this.file, false);
 			}
 			this.transportId = this.mJingleConnectionManager.nextRandomId();
 			content.setTransportId(this.transportId);
@@ -327,62 +369,72 @@ public class JingleConnection {
 			this.status = STATUS_INITIATED;
 		}
 	}
-	
+
 	private List<Element> getCandidatesAsElements() {
 		List<Element> elements = new ArrayList<Element>();
-		for(JingleCandidate c : this.candidates) {
+		for (JingleCandidate c : this.candidates) {
 			elements.add(c.toElement());
 		}
 		return elements;
 	}
-	
+
 	private void sendAccept() {
 		status = STATUS_ACCEPTED;
 		mXmppConnectionService.markMessage(message, Message.STATUS_RECIEVING);
-		this.mJingleConnectionManager.getPrimaryCandidate(this.account, new OnPrimaryCandidateFound() {
-			
-			@Override
-			public void onPrimaryCandidateFound(boolean success,final JingleCandidate candidate) {
-				final JinglePacket packet = bootstrapPacket("session-accept");
-				final Content content = new Content(contentCreator,contentName);
-				content.setFileOffer(fileOffer);
-				content.setTransportId(transportId);
-				if ((success)&&(!equalCandidateExists(candidate))) {
-					final JingleSocks5Transport socksConnection = new JingleSocks5Transport(JingleConnection.this, candidate);
-					connections.put(candidate.getCid(), socksConnection);
-					socksConnection.connect(new OnTransportConnected() {
-						
-						@Override
-						public void failed() {
-							Log.d("xmppService","connection to our own primary candidate failed");
-							content.socks5transport().setChildren(getCandidatesAsElements());
-							packet.setContent(content);
-							sendJinglePacket(packet);
-							connectNextCandidate();
-						}
-						
-						@Override
-						public void established() {
-							Log.d("xmppService","connected to primary candidate");
-							mergeCandidate(candidate);
-							content.socks5transport().setChildren(getCandidatesAsElements());
+		this.mJingleConnectionManager.getPrimaryCandidate(this.account,
+				new OnPrimaryCandidateFound() {
+
+					@Override
+					public void onPrimaryCandidateFound(boolean success,
+							final JingleCandidate candidate) {
+						final JinglePacket packet = bootstrapPacket("session-accept");
+						final Content content = new Content(contentCreator,
+								contentName);
+						content.setFileOffer(fileOffer);
+						content.setTransportId(transportId);
+						if ((success) && (!equalCandidateExists(candidate))) {
+							final JingleSocks5Transport socksConnection = new JingleSocks5Transport(
+									JingleConnection.this, candidate);
+							connections.put(candidate.getCid(), socksConnection);
+							socksConnection.connect(new OnTransportConnected() {
+
+								@Override
+								public void failed() {
+									Log.d("xmppService",
+											"connection to our own primary candidate failed");
+									content.socks5transport().setChildren(
+											getCandidatesAsElements());
+									packet.setContent(content);
+									sendJinglePacket(packet);
+									connectNextCandidate();
+								}
+
+								@Override
+								public void established() {
+									Log.d("xmppService",
+											"connected to primary candidate");
+									mergeCandidate(candidate);
+									content.socks5transport().setChildren(
+											getCandidatesAsElements());
+									packet.setContent(content);
+									sendJinglePacket(packet);
+									connectNextCandidate();
+								}
+							});
+						} else {
+							Log.d("xmppService",
+									"did not find a primary candidate for ourself");
+							content.socks5transport().setChildren(
+									getCandidatesAsElements());
 							packet.setContent(content);
 							sendJinglePacket(packet);
 							connectNextCandidate();
 						}
-					});
-				} else {
-					Log.d("xmppService","did not find a primary candidate for ourself");
-					content.socks5transport().setChildren(getCandidatesAsElements());
-					packet.setContent(content);
-					sendJinglePacket(packet);
-					connectNextCandidate();
-				}
-			}
-		});
-		
+					}
+				});
+
 	}
-	
+
 	private JinglePacket bootstrapPacket(String action) {
 		JinglePacket packet = new JinglePacket();
 		packet.setAction(action);
@@ -392,15 +444,16 @@ public class JingleConnection {
 		packet.setInitiator(this.initiator);
 		return packet;
 	}
-	
+
 	private void sendJinglePacket(JinglePacket packet) {
-		//Log.d("xmppService",packet.toString());
-		account.getXmppConnection().sendIqPacket(packet,responseListener);
+		// Log.d("xmppService",packet.toString());
+		account.getXmppConnection().sendIqPacket(packet, responseListener);
 	}
-	
+
 	private boolean receiveAccept(JinglePacket packet) {
 		Content content = packet.getJingleContent();
-		mergeCandidates(JingleCandidate.parse(content.socks5transport().getChildren()));
+		mergeCandidates(JingleCandidate.parse(content.socks5transport()
+				.getChildren()));
 		this.status = STATUS_ACCEPTED;
 		mXmppConnectionService.markMessage(message, Message.STATUS_UNSEND);
 		this.connectNextCandidate();
@@ -411,16 +464,20 @@ public class JingleConnection {
 		Content content = packet.getJingleContent();
 		if (content.hasSocks5Transport()) {
 			if (content.socks5transport().hasChild("activated")) {
-				if ((this.transport!=null)&&(this.transport instanceof JingleSocks5Transport)) {
+				if ((this.transport != null)
+						&& (this.transport instanceof JingleSocks5Transport)) {
 					onProxyActivated.success();
 				} else {
-					String cid = content.socks5transport().findChild("activated").getAttribute("cid");
-					Log.d("xmppService","received proxy activated ("+cid+")prior to choosing our own transport");
-					JingleSocks5Transport connection = this.connections.get(cid);
-					if (connection!=null) {
+					String cid = content.socks5transport()
+							.findChild("activated").getAttribute("cid");
+					Log.d("xmppService", "received proxy activated (" + cid
+							+ ")prior to choosing our own transport");
+					JingleSocks5Transport connection = this.connections
+							.get(cid);
+					if (connection != null) {
 						connection.setActivated(true);
 					} else {
-						Log.d("xmppService","activated connection not found");
+						Log.d("xmppService", "activated connection not found");
 						this.sendCancel();
 						this.cancel();
 					}
@@ -430,23 +487,25 @@ public class JingleConnection {
 				onProxyActivated.failed();
 				return true;
 			} else if (content.socks5transport().hasChild("candidate-error")) {
-				Log.d("xmppService","received candidate error");
+				Log.d("xmppService", "received candidate error");
 				this.receivedCandidate = true;
-				if ((status == STATUS_ACCEPTED)&&(this.sentCandidate)) {
+				if ((status == STATUS_ACCEPTED) && (this.sentCandidate)) {
 					this.connect();
 				}
 				return true;
-			} else if (content.socks5transport().hasChild("candidate-used")){
-				String cid = content.socks5transport().findChild("candidate-used").getAttribute("cid");
-				if (cid!=null) {
-					Log.d("xmppService","candidate used by counterpart:"+cid);
+			} else if (content.socks5transport().hasChild("candidate-used")) {
+				String cid = content.socks5transport()
+						.findChild("candidate-used").getAttribute("cid");
+				if (cid != null) {
+					Log.d("xmppService", "candidate used by counterpart:" + cid);
 					JingleCandidate candidate = getCandidate(cid);
 					candidate.flagAsUsedByCounterpart();
 					this.receivedCandidate = true;
-					if ((status == STATUS_ACCEPTED)&&(this.sentCandidate)) {
+					if ((status == STATUS_ACCEPTED) && (this.sentCandidate)) {
 						this.connect();
 					} else {
-						Log.d("xmppService","ignoring because file is already in transmission or we havent sent our candidate yet");
+						Log.d("xmppService",
+								"ignoring because file is already in transmission or we havent sent our candidate yet");
 					}
 					return true;
 				} else {
@@ -463,8 +522,8 @@ public class JingleConnection {
 	private void connect() {
 		final JingleSocks5Transport connection = chooseConnection();
 		this.transport = connection;
-		if (connection==null) {
-			Log.d("xmppService","could not find suitable candidate");
+		if (connection == null) {
+			Log.d("xmppService", "could not find suitable candidate");
 			this.disconnect();
 			if (this.initiator.equals(account.getFullJid())) {
 				this.sendFallbackToIbb();
@@ -473,65 +532,80 @@ public class JingleConnection {
 			this.status = STATUS_TRANSMITTING;
 			if (connection.needsActivation()) {
 				if (connection.getCandidate().isOurs()) {
-					Log.d("xmppService","candidate "+connection.getCandidate().getCid()+" was our proxy. going to activate");
+					Log.d("xmppService", "candidate "
+							+ connection.getCandidate().getCid()
+							+ " was our proxy. going to activate");
 					IqPacket activation = new IqPacket(IqPacket.TYPE_SET);
 					activation.setTo(connection.getCandidate().getJid());
-					activation.query("http://jabber.org/protocol/bytestreams").setAttribute("sid", this.getSessionId());
-					activation.query().addChild("activate").setContent(this.getCounterPart());
-					this.account.getXmppConnection().sendIqPacket(activation, new OnIqPacketReceived() {
-						
-						@Override
-						public void onIqPacketReceived(Account account, IqPacket packet) {
-							if (packet.getType()==IqPacket.TYPE_ERROR) {
-								onProxyActivated.failed();
-							} else {
-								onProxyActivated.success();
-								sendProxyActivated(connection.getCandidate().getCid());
-							}
-						}
-					});
+					activation.query("http://jabber.org/protocol/bytestreams")
+							.setAttribute("sid", this.getSessionId());
+					activation.query().addChild("activate")
+							.setContent(this.getCounterPart());
+					this.account.getXmppConnection().sendIqPacket(activation,
+							new OnIqPacketReceived() {
+
+								@Override
+								public void onIqPacketReceived(Account account,
+										IqPacket packet) {
+									if (packet.getType() == IqPacket.TYPE_ERROR) {
+										onProxyActivated.failed();
+									} else {
+										onProxyActivated.success();
+										sendProxyActivated(connection
+												.getCandidate().getCid());
+									}
+								}
+							});
 				} else {
-					Log.d("xmppService","candidate "+connection.getCandidate().getCid()+" was a proxy. waiting for other party to activate");
+					Log.d("xmppService",
+							"candidate "
+									+ connection.getCandidate().getCid()
+									+ " was a proxy. waiting for other party to activate");
 				}
 			} else {
 				if (initiator.equals(account.getFullJid())) {
-					Log.d("xmppService","we were initiating. sending file");
-					connection.send(file,onFileTransmissionSatusChanged);
+					Log.d("xmppService", "we were initiating. sending file");
+					connection.send(file, onFileTransmissionSatusChanged);
 				} else {
-					Log.d("xmppService","we were responding. receiving file");
-					connection.receive(file,onFileTransmissionSatusChanged);
+					Log.d("xmppService", "we were responding. receiving file");
+					connection.receive(file, onFileTransmissionSatusChanged);
 				}
 			}
 		}
 	}
-	
+
 	private JingleSocks5Transport chooseConnection() {
 		JingleSocks5Transport connection = null;
-		for (Entry<String, JingleSocks5Transport> cursor : connections.entrySet()) {
-	    	JingleSocks5Transport currentConnection = cursor.getValue();
-	    	//Log.d("xmppService","comparing candidate: "+currentConnection.getCandidate().toString());
-	        if (currentConnection.isEstablished()&&(currentConnection.getCandidate().isUsedByCounterpart()||(!currentConnection.getCandidate().isOurs()))) {
-	        	//Log.d("xmppService","is usable");
-	        	if (connection==null) {
-	        		connection = currentConnection;
-	        	} else {
-	        		if (connection.getCandidate().getPriority()<currentConnection.getCandidate().getPriority()) {
-	        			connection = currentConnection;
-	        		} else if (connection.getCandidate().getPriority()==currentConnection.getCandidate().getPriority()) {
-	        			//Log.d("xmppService","found two candidates with same priority");
-	        			if (initiator.equals(account.getFullJid())) {
-	        				if (currentConnection.getCandidate().isOurs()) {
-	        					connection = currentConnection;
-	        				}
-	        			} else {
-	        				if (!currentConnection.getCandidate().isOurs()) {
-	        					connection = currentConnection;
-	        				}
-	        			}
-	        		}
-	        	}
-	        }
-	    }
+		for (Entry<String, JingleSocks5Transport> cursor : connections
+				.entrySet()) {
+			JingleSocks5Transport currentConnection = cursor.getValue();
+			// Log.d("xmppService","comparing candidate: "+currentConnection.getCandidate().toString());
+			if (currentConnection.isEstablished()
+					&& (currentConnection.getCandidate().isUsedByCounterpart() || (!currentConnection
+							.getCandidate().isOurs()))) {
+				// Log.d("xmppService","is usable");
+				if (connection == null) {
+					connection = currentConnection;
+				} else {
+					if (connection.getCandidate().getPriority() < currentConnection
+							.getCandidate().getPriority()) {
+						connection = currentConnection;
+					} else if (connection.getCandidate().getPriority() == currentConnection
+							.getCandidate().getPriority()) {
+						// Log.d("xmppService","found two candidates with same priority");
+						if (initiator.equals(account.getFullJid())) {
+							if (currentConnection.getCandidate().isOurs()) {
+								connection = currentConnection;
+							}
+						} else {
+							if (!currentConnection.getCandidate().isOurs()) {
+								connection = currentConnection;
+							}
+						}
+					}
+				}
+			}
+		}
 		return connection;
 	}
 
@@ -543,60 +617,68 @@ public class JingleConnection {
 		this.sendJinglePacket(packet);
 		this.disconnect();
 		this.status = STATUS_FINISHED;
-		this.mXmppConnectionService.markMessage(this.message, Message.STATUS_RECIEVED);
+		this.mXmppConnectionService.markMessage(this.message,
+				Message.STATUS_RECIEVED);
 		this.mJingleConnectionManager.finishConnection(this);
 	}
-	
+
 	private void sendFallbackToIbb() {
 		JinglePacket packet = this.bootstrapPacket("transport-replace");
-		Content content = new Content(this.contentCreator,this.contentName);
+		Content content = new Content(this.contentCreator, this.contentName);
 		this.transportId = this.mJingleConnectionManager.nextRandomId();
 		content.setTransportId(this.transportId);
-		content.ibbTransport().setAttribute("block-size",""+this.ibbBlockSize);
+		content.ibbTransport().setAttribute("block-size",
+				"" + this.ibbBlockSize);
 		packet.setContent(content);
 		this.sendJinglePacket(packet);
 	}
-	
+
 	private boolean receiveFallbackToIbb(JinglePacket packet) {
-		String receivedBlockSize = packet.getJingleContent().ibbTransport().getAttribute("block-size");
-		if (receivedBlockSize!=null) {
+		String receivedBlockSize = packet.getJingleContent().ibbTransport()
+				.getAttribute("block-size");
+		if (receivedBlockSize != null) {
 			int bs = Integer.parseInt(receivedBlockSize);
-			if (bs>this.ibbBlockSize) {
+			if (bs > this.ibbBlockSize) {
 				this.ibbBlockSize = bs;
 			}
 		}
 		this.transportId = packet.getJingleContent().getTransportId();
-		this.transport = new JingleInbandTransport(this.account,this.responder,this.transportId,this.ibbBlockSize);
+		this.transport = new JingleInbandTransport(this.account,
+				this.responder, this.transportId, this.ibbBlockSize);
 		this.transport.receive(file, onFileTransmissionSatusChanged);
 		JinglePacket answer = bootstrapPacket("transport-accept");
 		Content content = new Content("initiator", "a-file-offer");
 		content.setTransportId(this.transportId);
-		content.ibbTransport().setAttribute("block-size", ""+this.ibbBlockSize);
+		content.ibbTransport().setAttribute("block-size",
+				"" + this.ibbBlockSize);
 		answer.setContent(content);
 		this.sendJinglePacket(answer);
 		return true;
 	}
-	
+
 	private boolean receiveTransportAccept(JinglePacket packet) {
 		if (packet.getJingleContent().hasIbbTransport()) {
-			String receivedBlockSize = packet.getJingleContent().ibbTransport().getAttribute("block-size");
-			if (receivedBlockSize!=null) {
+			String receivedBlockSize = packet.getJingleContent().ibbTransport()
+					.getAttribute("block-size");
+			if (receivedBlockSize != null) {
 				int bs = Integer.parseInt(receivedBlockSize);
-				if (bs>this.ibbBlockSize) {
+				if (bs > this.ibbBlockSize) {
 					this.ibbBlockSize = bs;
 				}
 			}
-			this.transport = new JingleInbandTransport(this.account,this.responder,this.transportId,this.ibbBlockSize);
+			this.transport = new JingleInbandTransport(this.account,
+					this.responder, this.transportId, this.ibbBlockSize);
 			this.transport.connect(new OnTransportConnected() {
-				
+
 				@Override
 				public void failed() {
-					Log.d("xmppService","ibb open failed");
+					Log.d("xmppService", "ibb open failed");
 				}
-				
+
 				@Override
 				public void established() {
-					JingleConnection.this.transport.send(file, onFileTransmissionSatusChanged);
+					JingleConnection.this.transport.send(file,
+							onFileTransmissionSatusChanged);
 				}
 			});
 			return true;
@@ -604,31 +686,35 @@ public class JingleConnection {
 			return false;
 		}
 	}
-	
+
 	private void receiveSuccess() {
 		this.status = STATUS_FINISHED;
-		this.mXmppConnectionService.markMessage(this.message, Message.STATUS_SEND);
+		this.mXmppConnectionService.markMessage(this.message,
+				Message.STATUS_SEND);
 		this.disconnect();
 		this.mJingleConnectionManager.finishConnection(this);
 	}
-	
+
 	public void cancel() {
 		this.disconnect();
-		if (this.message!=null) {
+		if (this.message != null) {
 			if (this.responder.equals(account.getFullJid())) {
-				this.mXmppConnectionService.markMessage(this.message, Message.STATUS_RECEPTION_FAILED);
+				this.mXmppConnectionService.markMessage(this.message,
+						Message.STATUS_RECEPTION_FAILED);
 			} else {
 				if (this.status == STATUS_INITIATED) {
-					this.mXmppConnectionService.markMessage(this.message, Message.STATUS_SEND_REJECTED);
+					this.mXmppConnectionService.markMessage(this.message,
+							Message.STATUS_SEND_REJECTED);
 				} else {
-					this.mXmppConnectionService.markMessage(this.message, Message.STATUS_SEND_FAILED);
+					this.mXmppConnectionService.markMessage(this.message,
+							Message.STATUS_SEND_FAILED);
 				}
 			}
 		}
 		this.status = STATUS_CANCELED;
 		this.mJingleConnectionManager.finishConnection(this);
 	}
-	
+
 	private void sendCancel() {
 		JinglePacket packet = bootstrapPacket("session-terminate");
 		Reason reason = new Reason();
@@ -638,73 +724,82 @@ public class JingleConnection {
 	}
 
 	private void connectNextCandidate() {
-		for(JingleCandidate candidate : this.candidates) {
-			if ((!connections.containsKey(candidate.getCid())&&(!candidate.isOurs()))) {
+		for (JingleCandidate candidate : this.candidates) {
+			if ((!connections.containsKey(candidate.getCid()) && (!candidate
+					.isOurs()))) {
 				this.connectWithCandidate(candidate);
 				return;
 			}
 		}
 		this.sendCandidateError();
 	}
-	
+
 	private void connectWithCandidate(final JingleCandidate candidate) {
-		final JingleSocks5Transport socksConnection = new JingleSocks5Transport(this,candidate);
+		final JingleSocks5Transport socksConnection = new JingleSocks5Transport(
+				this, candidate);
 		connections.put(candidate.getCid(), socksConnection);
 		socksConnection.connect(new OnTransportConnected() {
-			
+
 			@Override
 			public void failed() {
-				Log.d("xmppService", "connection failed with "+candidate.getHost()+":"+candidate.getPort());
+				Log.d("xmppService",
+						"connection failed with " + candidate.getHost() + ":"
+								+ candidate.getPort());
 				connectNextCandidate();
 			}
-			
+
 			@Override
 			public void established() {
-				Log.d("xmppService", "established connection with "+candidate.getHost()+":"+candidate.getPort());
+				Log.d("xmppService",
+						"established connection with " + candidate.getHost()
+								+ ":" + candidate.getPort());
 				sendCandidateUsed(candidate.getCid());
 			}
 		});
 	}
 
 	private void disconnect() {
-		Iterator<Entry<String, JingleSocks5Transport>> it = this.connections.entrySet().iterator();
-	    while (it.hasNext()) {
-	        Entry<String, JingleSocks5Transport> pairs = it.next();
-	        pairs.getValue().disconnect();
-	        it.remove();
-	    }
-	}
-	
+		Iterator<Entry<String, JingleSocks5Transport>> it = this.connections
+				.entrySet().iterator();
+		while (it.hasNext()) {
+			Entry<String, JingleSocks5Transport> pairs = it.next();
+			pairs.getValue().disconnect();
+			it.remove();
+		}
+	}
+
 	private void sendProxyActivated(String cid) {
 		JinglePacket packet = bootstrapPacket("transport-info");
-		Content content = new Content(this.contentCreator,this.contentName);
+		Content content = new Content(this.contentCreator, this.contentName);
 		content.setTransportId(this.transportId);
-		content.socks5transport().addChild("activated").setAttribute("cid", cid);
+		content.socks5transport().addChild("activated")
+				.setAttribute("cid", cid);
 		packet.setContent(content);
 		this.sendJinglePacket(packet);
 	}
-	
+
 	private void sendCandidateUsed(final String cid) {
 		JinglePacket packet = bootstrapPacket("transport-info");
-		Content content = new Content(this.contentCreator,this.contentName);
+		Content content = new Content(this.contentCreator, this.contentName);
 		content.setTransportId(this.transportId);
-		content.socks5transport().addChild("candidate-used").setAttribute("cid", cid);
+		content.socks5transport().addChild("candidate-used")
+				.setAttribute("cid", cid);
 		packet.setContent(content);
 		this.sentCandidate = true;
-		if ((receivedCandidate)&&(status == STATUS_ACCEPTED)) {
+		if ((receivedCandidate) && (status == STATUS_ACCEPTED)) {
 			connect();
 		}
 		this.sendJinglePacket(packet);
 	}
-	
+
 	private void sendCandidateError() {
 		JinglePacket packet = bootstrapPacket("transport-info");
-		Content content = new Content(this.contentCreator,this.contentName);
+		Content content = new Content(this.contentCreator, this.contentName);
 		content.setTransportId(this.transportId);
 		content.socks5transport().addChild("candidate-error");
 		packet.setContent(content);
 		this.sentCandidate = true;
-		if ((receivedCandidate)&&(status == STATUS_ACCEPTED)) {
+		if ((receivedCandidate) && (status == STATUS_ACCEPTED)) {
 			connect();
 		}
 		this.sendJinglePacket(packet);
@@ -713,72 +808,73 @@ public class JingleConnection {
 	public String getInitiator() {
 		return this.initiator;
 	}
-	
+
 	public String getResponder() {
 		return this.responder;
 	}
-	
+
 	public int getStatus() {
 		return this.status;
 	}
-	
+
 	private boolean equalCandidateExists(JingleCandidate candidate) {
-		for(JingleCandidate c : this.candidates) {
+		for (JingleCandidate c : this.candidates) {
 			if (c.equalValues(candidate)) {
 				return true;
 			}
 		}
 		return false;
 	}
-	
+
 	private void mergeCandidate(JingleCandidate candidate) {
-		for(JingleCandidate c : this.candidates) {
+		for (JingleCandidate c : this.candidates) {
 			if (c.equals(candidate)) {
 				return;
 			}
 		}
 		this.candidates.add(candidate);
 	}
-	
+
 	private void mergeCandidates(List<JingleCandidate> candidates) {
-		for(JingleCandidate c : candidates) {
+		for (JingleCandidate c : candidates) {
 			mergeCandidate(c);
 		}
 	}
-	
+
 	private JingleCandidate getCandidate(String cid) {
-		for(JingleCandidate c : this.candidates) {
+		for (JingleCandidate c : this.candidates) {
 			if (c.getCid().equals(cid)) {
 				return c;
 			}
 		}
 		return null;
 	}
-	
+
 	interface OnProxyActivated {
 		public void success();
+
 		public void failed();
 	}
 
 	public boolean hasTransportId(String sid) {
 		return sid.equals(this.transportId);
 	}
-	
+
 	public JingleTransport getTransport() {
 		return this.transport;
 	}
 
 	public void accept() {
-		if (status==STATUS_INITIATED) {
+		if (status == STATUS_INITIATED) {
 			new Thread(new Runnable() {
-				
+
 				@Override
 				public void run() {
 					sendAccept();
 				}
 			}).start();
 		} else {
-			Log.d("xmppService","status ("+status+") was not ok");
+			Log.d("xmppService", "status (" + status + ") was not ok");
 		}
 	}
 }