Merge pull request #1 from siacs/development

Dominik SchΓΌrmann created

pull

Change summary

res/values/strings.xml                                         |   3 
src/eu/siacs/conversations/entities/Conversation.java          |   3 
src/eu/siacs/conversations/entities/Message.java               |   1 
src/eu/siacs/conversations/services/XmppConnectionService.java |  11 
src/eu/siacs/conversations/ui/ConversationActivity.java        |  80 
src/eu/siacs/conversations/ui/ConversationFragment.java        | 347 ++-
src/eu/siacs/conversations/ui/ManageAccountActivity.java       |  33 
src/eu/siacs/conversations/ui/XmppActivity.java                |  35 
8 files changed, 282 insertions(+), 231 deletions(-)

Detailed changes

res/values/strings.xml πŸ”—

@@ -83,4 +83,7 @@
     <string name="openkeychain_required_long">Conversations utilizes a third party app called <b>OpenKeychain</b> to encrypt and decrypt messages and to mange your public keys.\n\nOpenKeychain is licensed under GPLv3 and available on F-Droid and Google Play.\n\n<small>(Please restart Conversations afterwards.)</small></string>
     <string name="restart">Restart</string>
     <string name="install">Install</string>
+    <string name="offering">offering&#8230;</string>
+    <string name="no_pgp_key">No openPGP Key found</string>
+    <string name="contact_has_no_pgp_key">Conversations is unable to encrypt your messages because your contact is not announcing his or hers public key.\n\n<small>Please ask your contact to setup openPGP.</small></string>
 </resources>

src/eu/siacs/conversations/entities/Conversation.java πŸ”—

@@ -15,7 +15,6 @@ import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
-import android.util.Log;
 
 public class Conversation extends AbstractEntity {
 
@@ -238,7 +237,6 @@ public class Conversation extends AbstractEntity {
 				}
 				return this.otrSession;
 			} catch (OtrException e) {
-				Log.d("xmppServic", "couldnt start otr");
 				return null;
 			}
 		}
@@ -347,7 +345,6 @@ public class Conversation extends AbstractEntity {
 	}
 	
 	public void setNextMessage(String message) {
-		Log.d("xmppService","saving text: "+message);
 		this.nextMessage = message;
 	}
 }

src/eu/siacs/conversations/entities/Message.java πŸ”—

@@ -17,7 +17,6 @@ public class Message extends AbstractEntity {
 	public static final int STATUS_SEND = 2;
 	public static final int STATUS_SEND_FAILED = 3;
 	public static final int STATUS_SEND_REJECTED = 4;
-	public static final int STATUS_PREPARING = 5;
 	public static final int STATUS_OFFERED = 6;
 
 	public static final int ENCRYPTION_NONE = 0;

src/eu/siacs/conversations/services/XmppConnectionService.java πŸ”—

@@ -451,18 +451,14 @@ public class XmppConnectionService extends Service {
 		final Message message = new Message(conversation, "",Message.ENCRYPTION_NONE);
 		message.setPresence(presence);
 		message.setType(Message.TYPE_IMAGE);
-		message.setStatus(Message.STATUS_PREPARING);
-		conversation.getMessages().add(message);
-		if (convChangedListener != null) {
-			convChangedListener.onConversationListChanged();
-		}
+		message.setStatus(Message.STATUS_OFFERED);
 		new Thread(new Runnable() {
 
 			@Override
 			public void run() {
 				getFileBackend().copyImageToPrivateStorage(message, uri);
-				message.setStatus(Message.STATUS_OFFERED);
 				databaseBackend.createMessage(message);
+				conversation.getMessages().add(message);
 				if (convChangedListener != null) {
 					convChangedListener.onConversationListChanged();
 				}
@@ -477,14 +473,13 @@ public class XmppConnectionService extends Service {
 		final Message message = new Message(conversation, "",Message.ENCRYPTION_DECRYPTED);
 		message.setPresence(presence);
 		message.setType(Message.TYPE_IMAGE);
-		message.setStatus(Message.STATUS_PREPARING);
+		message.setStatus(Message.STATUS_OFFERED);
 		new Thread(new Runnable() {
 
 			@Override
 			public void run() {
 				getFileBackend().copyImageToPrivateStorage(message, uri);
 				getPgpEngine().encrypt(message, callback);
-				message.setStatus(Message.STATUS_OFFERED);
 			}
 		}).start();
 		return message;

src/eu/siacs/conversations/ui/ConversationActivity.java πŸ”—

@@ -178,16 +178,14 @@ public class ConversationActivity extends XmppActivity {
 					convLastMsg.setVisibility(View.VISIBLE);
 					imagePreview.setVisibility(View.GONE);
 				} else if (latestMessage.getType() == Message.TYPE_IMAGE) {
-					if ((latestMessage.getStatus() >= Message.STATUS_RECIEVED)&&(latestMessage.getStatus() != Message.STATUS_PREPARING)) {
+					if (latestMessage.getStatus() >= Message.STATUS_RECIEVED) {
 						convLastMsg.setVisibility(View.GONE);
 						imagePreview.setVisibility(View.VISIBLE);
 						loadBitmap(latestMessage, imagePreview);
 					} else {
 						convLastMsg.setVisibility(View.VISIBLE);
 						imagePreview.setVisibility(View.GONE);
-						if (latestMessage.getStatus() == Message.STATUS_PREPARING) {
-							convLastMsg.setText(getText(R.string.preparing_image));
-						} else  if (latestMessage.getStatus() == Message.STATUS_RECEIVED_OFFER) {
+						if (latestMessage.getStatus() == Message.STATUS_RECEIVED_OFFER) {
 							convLastMsg.setText(getText(R.string.image_offered_for_download));
 						} else if (latestMessage.getStatus() == Message.STATUS_RECIEVING) {
 							convLastMsg.setText(getText(R.string.receiving_image));
@@ -343,26 +341,42 @@ public class ConversationActivity extends XmppActivity {
 	}
 
 	private void attachFile() {
-		if (getSelectedConversation().getNextEncryption() == Message.ENCRYPTION_PGP) {
+		final Conversation conversation = getSelectedConversation();
+		if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
 			if (hasPgp()) {
-				xmppConnectionService.getPgpEngine().hasKey(getSelectedConversation().getContact(), new OnPgpEngineResult() {
-					
-					@Override
-					public void userInputRequried(PendingIntent pi) {
-						ConversationActivity.this.runIntent(pi, REQUEST_SEND_PGP_IMAGE);
-					}
-					
-					@Override
-					public void success() {
-						attachFileDialog();
-					}
-					
-					@Override
-					public void error(OpenPgpError openPgpError) {
-						// TODO Auto-generated method stub
+				if (conversation.getContact().getPgpKeyId()!=0) {
+					xmppConnectionService.getPgpEngine().hasKey(conversation.getContact(), new OnPgpEngineResult() {
+						
+						@Override
+						public void userInputRequried(PendingIntent pi) {
+							ConversationActivity.this.runIntent(pi, REQUEST_SEND_PGP_IMAGE);
+						}
 						
+						@Override
+						public void success() {
+							attachFileDialog();
+						}
+						
+						@Override
+						public void error(OpenPgpError openPgpError) {
+							// TODO Auto-generated method stub
+							
+						}
+					});
+				} else {
+					final ConversationFragment fragment = (ConversationFragment) getFragmentManager()
+							.findFragmentByTag("conversation");
+					if (fragment != null) {
+						fragment.showNoPGPKeyDialog(new OnClickListener() {
+							
+							@Override
+							public void onClick(DialogInterface dialog, int which) {
+								conversation.setNextEncryption(Message.ENCRYPTION_NONE);
+								attachFileDialog();
+							}
+						});
 					}
-				});
+				}
 			}
 		} else if (getSelectedConversation().getNextEncryption() == Message.ENCRYPTION_NONE) {
 			attachFileDialog();
@@ -409,7 +423,7 @@ public class ConversationActivity extends XmppActivity {
 			startActivity(inviteIntent);
 			break;
 		case R.id.action_security:
-			final Conversation selConv = getSelectedConversation();
+			final Conversation conversation = getSelectedConversation();
 			View menuItemView = findViewById(R.id.action_security);
 			PopupMenu popup = new PopupMenu(this, menuItemView);
 			final ConversationFragment fragment = (ConversationFragment) getFragmentManager()
@@ -421,19 +435,25 @@ public class ConversationActivity extends XmppActivity {
 					public boolean onMenuItemClick(MenuItem item) {
 						switch (item.getItemId()) {
 						case R.id.encryption_choice_none:
-							selConv.setNextEncryption(Message.ENCRYPTION_NONE);
+							conversation.setNextEncryption(Message.ENCRYPTION_NONE);
 							item.setChecked(true);
 							break;
 						case R.id.encryption_choice_otr:
-							selConv.setNextEncryption(Message.ENCRYPTION_OTR);
+							conversation.setNextEncryption(Message.ENCRYPTION_OTR);
 							item.setChecked(true);
 							break;
 						case R.id.encryption_choice_pgp:
-							selConv.setNextEncryption(Message.ENCRYPTION_PGP);
-							item.setChecked(true);
+							if (hasPgp()) {
+								if (conversation.getAccount().getKeys().has("pgp_signature")) {
+									conversation.setNextEncryption(Message.ENCRYPTION_PGP);
+									item.setChecked(true);
+								} else {
+									announcePgp(conversation.getAccount());
+								}
+							}
 							break;
 						default:
-							selConv.setNextEncryption(Message.ENCRYPTION_NONE);
+							conversation.setNextEncryption(Message.ENCRYPTION_NONE);
 							break;
 						}
 						fragment.updateChatMsgHint();
@@ -441,7 +461,7 @@ public class ConversationActivity extends XmppActivity {
 					}
 				});
 				popup.inflate(R.menu.encryption_choices);
-				switch (selConv.getNextEncryption()) {
+				switch (conversation.getNextEncryption()) {
 				case Message.ENCRYPTION_NONE:
 					popup.getMenu().findItem(R.id.encryption_choice_none)
 							.setChecked(true);
@@ -454,10 +474,6 @@ public class ConversationActivity extends XmppActivity {
 					popup.getMenu().findItem(R.id.encryption_choice_pgp)
 							.setChecked(true);
 					break;
-				case Message.ENCRYPTION_DECRYPTED:
-					popup.getMenu().findItem(R.id.encryption_choice_pgp)
-							.setChecked(true);
-					break;
 				default:
 					popup.getMenu().findItem(R.id.encryption_choice_none)
 							.setChecked(true);

src/eu/siacs/conversations/ui/ConversationFragment.java πŸ”—

@@ -192,6 +192,155 @@ public class ConversationFragment extends Fragment {
 				}
 			}
 
+			private void displayStatus(ViewHolder viewHolder, Message message) {
+				String filesize = null;
+				String info = null;
+				boolean error = false;
+				if (message.getType() == Message.TYPE_IMAGE) {
+					String[] fileParams = message.getBody().split(",");
+					long size = Long.parseLong(fileParams[0]);
+					filesize = size / 1024 + " KB";
+				}
+				switch (message.getStatus()) {
+				case Message.STATUS_UNSEND:
+					info = getString(R.string.sending);
+					break;
+				case Message.STATUS_OFFERED:
+					info = getString(R.string.offering);
+					break;
+				case Message.STATUS_SEND_FAILED:
+					info = getString(R.string.send_failed);
+					error = true;
+					break;
+				case Message.STATUS_SEND_REJECTED:
+					info = getString(R.string.send_rejected);
+					error = true;
+					break;
+				default:
+					if ((message.getConversation().getMode() == Conversation.MODE_MULTI)
+							&& (message.getStatus() <= Message.STATUS_RECIEVED)) {
+						info = message.getCounterpart();
+					}
+					break;
+				}
+				if (error) {
+					viewHolder.time.setTextColor(0xFFe92727);
+				} else {
+					viewHolder.time.setTextColor(0xFF8e8e8e);
+				}
+				if (message.getEncryption() == Message.ENCRYPTION_NONE) {
+					viewHolder.indicator.setVisibility(View.GONE);
+				} else {
+					viewHolder.indicator.setVisibility(View.VISIBLE);
+				}
+
+				String formatedTime = UIHelper.readableTimeDifference(message
+						.getTimeSent());
+				if (message.getStatus() <= Message.STATUS_RECIEVED) {
+					if ((filesize != null) && (info != null)) {
+						viewHolder.time.setText(filesize + " \u00B7 " + info);
+					} else if ((filesize == null) && (info != null)) {
+						viewHolder.time.setText(formatedTime + " \u00B7 "
+								+ info);
+					} else if ((filesize != null) && (info == null)) {
+						viewHolder.time.setText(formatedTime + " \u00B7 "
+								+ filesize);
+					} else {
+						viewHolder.time.setText(formatedTime);
+					}
+				} else {
+					if ((filesize != null) && (info != null)) {
+						viewHolder.time.setText(filesize + " \u00B7 " + info);
+					} else if ((filesize == null) && (info != null)) {
+						viewHolder.time.setText(info + " \u00B7 "
+								+ formatedTime);
+					} else if ((filesize != null) && (info == null)) {
+						viewHolder.time.setText(filesize + " \u00B7 "
+								+ formatedTime);
+					} else {
+						viewHolder.time.setText(formatedTime);
+					}
+				}
+			}
+
+			private void displayInfoMessage(ViewHolder viewHolder, int r) {
+				viewHolder.download_button.setVisibility(View.GONE);
+				viewHolder.image.setVisibility(View.GONE);
+				viewHolder.messageBody.setVisibility(View.VISIBLE);
+				viewHolder.messageBody.setText(getString(r));
+				viewHolder.messageBody.setTextColor(0xff33B5E5);
+				viewHolder.messageBody.setTypeface(null, Typeface.ITALIC);
+			}
+
+			private void displayDecryptionFailed(ViewHolder viewHolder) {
+				viewHolder.download_button.setVisibility(View.GONE);
+				viewHolder.image.setVisibility(View.GONE);
+				viewHolder.messageBody.setVisibility(View.VISIBLE);
+				viewHolder.messageBody
+						.setText(getString(R.string.decryption_failed));
+				viewHolder.messageBody.setTextColor(0xFFe92727);
+				viewHolder.messageBody.setTypeface(null, Typeface.NORMAL);
+			}
+
+			private void displayTextMessage(ViewHolder viewHolder, String text) {
+				if (viewHolder.download_button != null) {
+					viewHolder.download_button.setVisibility(View.GONE);
+				}
+				viewHolder.image.setVisibility(View.GONE);
+				viewHolder.messageBody.setVisibility(View.VISIBLE);
+				if (text != null) {
+					viewHolder.messageBody.setText(text.trim());
+				} else {
+					viewHolder.messageBody.setText("");
+				}
+				viewHolder.messageBody.setTextColor(0xff333333);
+				viewHolder.messageBody.setTypeface(null, Typeface.NORMAL);
+			}
+
+			private void displayImageMessage(ViewHolder viewHolder,
+					final Message message) {
+				if (viewHolder.download_button != null) {
+					viewHolder.download_button.setVisibility(View.GONE);
+				}
+				viewHolder.messageBody.setVisibility(View.GONE);
+				viewHolder.image.setVisibility(View.VISIBLE);
+				String[] fileParams = message.getBody().split(",");
+				if (fileParams.length == 3) {
+					double target = metrics.density * 288;
+					int w = Integer.parseInt(fileParams[1]);
+					int h = Integer.parseInt(fileParams[2]);
+					int scalledW;
+					int scalledH;
+					if (w <= h) {
+						scalledW = (int) (w / ((double) h / target));
+						scalledH = (int) target;
+					} else {
+						scalledW = (int) target;
+						scalledH = (int) (h / ((double) w / target));
+					}
+					viewHolder.image
+							.setLayoutParams(new LinearLayout.LayoutParams(
+									scalledW, scalledH));
+				}
+				activity.loadBitmap(message, viewHolder.image);
+				viewHolder.image.setOnClickListener(new OnClickListener() {
+
+					@Override
+					public void onClick(View v) {
+						Uri uri = Uri
+								.parse("content://eu.siacs.conversations.images/"
+										+ message.getConversationUuid()
+										+ "/"
+										+ message.getUuid());
+						Log.d("xmppService",
+								"staring intent with uri:" + uri.toString());
+						Intent intent = new Intent(Intent.ACTION_VIEW);
+						intent.setDataAndType(uri, "image/*");
+						startActivity(intent);
+					}
+				});
+			}
+
 			@Override
 			public View getView(int position, View view, ViewGroup parent) {
 				final Message item = getItem(position);
@@ -265,38 +414,9 @@ public class ConversationFragment extends Fragment {
 					}
 				}
 
-				if (item.getEncryption() == Message.ENCRYPTION_NONE) {
-					viewHolder.indicator.setVisibility(View.GONE);
-				} else {
-					viewHolder.indicator.setVisibility(View.VISIBLE);
-				}
-
-				String filesize = "";
-
-				if ((item.getType() == Message.TYPE_IMAGE)
-						&& ((item.getEncryption() == Message.ENCRYPTION_DECRYPTED) || (item
-								.getEncryption() == Message.ENCRYPTION_NONE))) {
-					String[] fileParams = item.getBody().split(",");
-					if ((fileParams.length >= 1)
-							&& (item.getStatus() != Message.STATUS_PREPARING)) {
-						long size = Long.parseLong(fileParams[0]);
-						filesize = size / 1024 + " KB \u00B7 ";
-					}
-					if ((item.getStatus() == Message.STATUS_PREPARING)
-							|| (item.getStatus() == Message.STATUS_RECIEVING)) {
-						viewHolder.image.setVisibility(View.GONE);
-						viewHolder.messageBody.setVisibility(View.VISIBLE);
-						if (item.getStatus() == Message.STATUS_PREPARING) {
-							viewHolder.messageBody
-									.setText(getString(R.string.preparing_image));
-						} else if (item.getStatus() == Message.STATUS_RECIEVING) {
-							viewHolder.download_button.setVisibility(View.GONE);
-							viewHolder.messageBody
-									.setText(getString(R.string.receiving_image));
-						}
-						viewHolder.messageBody.setTextColor(0xff33B5E5);
-						viewHolder.messageBody.setTypeface(null,
-								Typeface.ITALIC);
+				if (item.getType() == Message.TYPE_IMAGE) {
+					if (item.getStatus() == Message.STATUS_RECIEVING) {
+						displayInfoMessage(viewHolder, R.string.receiving_image);
 					} else if (item.getStatus() == Message.STATUS_RECEIVED_OFFER) {
 						viewHolder.image.setVisibility(View.GONE);
 						viewHolder.messageBody.setVisibility(View.GONE);
@@ -316,114 +436,28 @@ public class ConversationFragment extends Fragment {
 										}
 									}
 								});
+					} else if ((item.getEncryption() == Message.ENCRYPTION_DECRYPTED)
+							|| (item.getEncryption() == Message.ENCRYPTION_NONE)) {
+						displayImageMessage(viewHolder, item);
+					} else if (item.getEncryption() == Message.ENCRYPTION_PGP) {
+						displayInfoMessage(viewHolder,
+								R.string.encrypted_message);
 					} else {
-						viewHolder.messageBody.setVisibility(View.GONE);
-						viewHolder.image.setVisibility(View.VISIBLE);
-						if (fileParams.length == 3) {
-							double target = metrics.density * 288;
-							int w = Integer.parseInt(fileParams[1]);
-							int h = Integer.parseInt(fileParams[2]);
-							int scalledW;
-							int scalledH;
-							if (w <= h) {
-								scalledW = (int) (w / ((double) h / target));
-								scalledH = (int) target;
-							} else {
-								scalledW = (int) target;
-								scalledH = (int) (h / ((double) w / target));
-							}
-							viewHolder.image
-									.setLayoutParams(new LinearLayout.LayoutParams(
-											scalledW, scalledH));
-						} else {
-							Log.d("xmppService",
-									"message body has less than 3 params");
-						}
-						activity.loadBitmap(item, viewHolder.image);
-						viewHolder.image
-								.setOnClickListener(new OnClickListener() {
-
-									@Override
-									public void onClick(View v) {
-										Uri uri = Uri.parse("content://eu.siacs.conversations.images/"
-												+ item.getConversationUuid()
-												+ "/" + item.getUuid());
-										Log.d("xmppService",
-												"staring intent with uri:"
-														+ uri.toString());
-										Intent intent = new Intent(
-												Intent.ACTION_VIEW);
-										intent.setDataAndType(uri, "image/*");
-										startActivity(intent);
-									}
-								});
+						displayDecryptionFailed(viewHolder);
 					}
 				} else {
-					viewHolder.image.setVisibility(View.GONE);
-					viewHolder.messageBody.setVisibility(View.VISIBLE);
-					String body = item.getBody();
-					if (body != null) {
-						if (item.getEncryption() == Message.ENCRYPTION_PGP) {
-							viewHolder.messageBody
-									.setText(getString(R.string.encrypted_message));
-							viewHolder.messageBody.setTextColor(0xff33B5E5);
-							viewHolder.messageBody.setTypeface(null,
-									Typeface.ITALIC);
-						} else if (item.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) {
-							viewHolder.messageBody
-									.setText(getString(R.string.decryption_failed));
-							viewHolder.messageBody.setTextColor(0xFFe92727);
-							viewHolder.messageBody.setTypeface(null,
-									Typeface.NORMAL);
-						} else {
-							viewHolder.messageBody.setText(body.trim());
-							viewHolder.messageBody.setTextColor(0xff333333);
-							viewHolder.messageBody.setTypeface(null,
-									Typeface.NORMAL);
-						}
-					}
-				}
-				switch (item.getStatus()) {
-				case Message.STATUS_UNSEND:
-					viewHolder.time.setTypeface(null, Typeface.ITALIC);
-					viewHolder.time.setTextColor(0xFF8e8e8e);
-					viewHolder.time.setText(filesize + "sending\u2026");
-					break;
-				case Message.STATUS_OFFERED:
-					viewHolder.time.setTypeface(null, Typeface.ITALIC);
-					viewHolder.time.setTextColor(0xFF8e8e8e);
-					viewHolder.time.setText(filesize + "offering\u2026");
-					break;
-				case Message.STATUS_SEND_FAILED:
-					viewHolder.time.setText(filesize
-							+ getString(R.string.send_failed)
-							+ " \u00B7 "
-							+ UIHelper.readableTimeDifference(item
-									.getTimeSent()));
-					viewHolder.time.setTextColor(0xFFe92727);
-					viewHolder.time.setTypeface(null, Typeface.NORMAL);
-					break;
-				case Message.STATUS_SEND_REJECTED:
-					viewHolder.time.setText(filesize
-							+ getString(R.string.send_rejected));
-					viewHolder.time.setTextColor(0xFFe92727);
-					viewHolder.time.setTypeface(null, Typeface.NORMAL);
-					break;
-				default:
-					viewHolder.time.setTypeface(null, Typeface.NORMAL);
-					viewHolder.time.setTextColor(0xFF8e8e8e);
-					if (item.getConversation().getMode() == Conversation.MODE_SINGLE) {
-						viewHolder.time.setText(filesize
-								+ UIHelper.readableTimeDifference(item
-										.getTimeSent()));
+					if (item.getEncryption() == Message.ENCRYPTION_PGP) {
+						displayInfoMessage(viewHolder,
+								R.string.encrypted_message);
+					} else if (item.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) {
+						displayDecryptionFailed(viewHolder);
 					} else {
-						viewHolder.time.setText(item.getCounterpart()
-								+ " \u00B7 "
-								+ UIHelper.readableTimeDifference(item
-										.getTimeSent()));
+						displayTextMessage(viewHolder, item.getBody());
 					}
-					break;
 				}
+
+				displayStatus(viewHolder, item);
+
 				return view;
 			}
 		};
@@ -518,7 +552,6 @@ public class ConversationFragment extends Fragment {
 	}
 
 	private void decryptMessage(final Message message) {
-		Log.d("xmppService", "called to decrypt");
 		PgpEngine engine = activity.xmppConnectionService.getPgpEngine();
 		if (engine != null) {
 			engine.decrypt(message, new OnPgpEngineResult() {
@@ -531,7 +564,6 @@ public class ConversationFragment extends Fragment {
 
 				@Override
 				public void success() {
-					Log.d("xmppService", "successfully decrypted");
 					activity.xmppConnectionService.databaseBackend
 							.updateMessage(message);
 					updateMessages();
@@ -546,7 +578,7 @@ public class ConversationFragment extends Fragment {
 				}
 			});
 		} else {
-			Log.d("xmppService", "engine was null");
+			pgpInfo.setVisibility(View.VISIBLE);
 		}
 	}
 
@@ -686,29 +718,32 @@ public class ConversationFragment extends Fragment {
 						});
 
 			} else {
-				AlertDialog.Builder builder = new AlertDialog.Builder(
-						getActivity());
-				builder.setTitle("No openPGP key found");
-				builder.setIconAttribute(android.R.attr.alertDialogIcon);
-				builder.setMessage("There is no openPGP key associated with this contact");
-				builder.setNegativeButton("Cancel", null);
-				builder.setPositiveButton("Send plain text",
-						new DialogInterface.OnClickListener() {
+				showNoPGPKeyDialog(new DialogInterface.OnClickListener() {
 
-							@Override
-							public void onClick(DialogInterface dialog,
-									int which) {
-								conversation
-										.setNextEncryption(Message.ENCRYPTION_NONE);
-								message.setEncryption(Message.ENCRYPTION_NONE);
-								xmppService.sendMessage(message, null);
-								chatMsg.setText("");
-							}
-						});
-				builder.create().show();
+					@Override
+					public void onClick(DialogInterface dialog,
+							int which) {
+						conversation
+								.setNextEncryption(Message.ENCRYPTION_NONE);
+						message.setEncryption(Message.ENCRYPTION_NONE);
+						xmppService.sendMessage(message, null);
+						chatMsg.setText("");
+					}
+				});
 			}
 		}
 	}
+	
+	public void showNoPGPKeyDialog(DialogInterface.OnClickListener listener) {
+		AlertDialog.Builder builder = new AlertDialog.Builder(
+				getActivity());
+		builder.setTitle(getString(R.string.no_pgp_key));
+		builder.setIconAttribute(android.R.attr.alertDialogIcon);
+		builder.setMessage(getText(R.string.contact_has_no_pgp_key));
+		builder.setNegativeButton(getString(R.string.cancel), null);
+		builder.setPositiveButton(getString(R.string.send_unencrypted),listener);
+		builder.create().show();
+	}
 
 	protected void sendOtrMessage(final Message message) {
 		ConversationActivity activity = (ConversationActivity) getActivity();

src/eu/siacs/conversations/ui/ManageAccountActivity.java πŸ”—

@@ -38,8 +38,6 @@ import android.widget.ListView;
 import android.widget.TextView;
 
 public class ManageAccountActivity extends XmppActivity {
-
-	public static final int REQUEST_ANNOUNCE_PGP = 0x73731;
 	
 	protected boolean isActionMode = false;
 	protected ActionMode actionMode;
@@ -281,7 +279,7 @@ public class ManageAccountActivity extends XmppActivity {
 							} else if (item.getItemId()==R.id.mgmt_account_announce_pgp) {
 								if (activity.hasPgp()) {
 									mode.finish();
-									announcePgp();
+									announcePgp(selectedAccountForActionMode);
 								}
 							} else if (item.getItemId() == R.id.mgmt_otr_key) {
 								AlertDialog.Builder builder = new AlertDialog.Builder(activity);
@@ -361,33 +359,6 @@ public class ManageAccountActivity extends XmppActivity {
 			}
 		});
 	}
-
-	private void announcePgp() {
-		final Account account = selectedAccountForActionMode;
-		xmppConnectionService.getPgpEngine().generateSignature(account, "online", new OnPgpEngineResult() {
-			
-			@Override
-			public void userInputRequried(PendingIntent pi) {
-				try {
-					startIntentSenderForResult(pi.getIntentSender(), REQUEST_ANNOUNCE_PGP, null, 0, 0, 0);
-				} catch (SendIntentException e) {
-					Log.d("xmppService","coulnd start intent for pgp anncouncment");
-				}
-			}
-			
-			@Override
-			public void success() {
-				xmppConnectionService.databaseBackend.updateAccount(account);
-				xmppConnectionService.sendPgpPresence(account, account.getPgpSignature());
-			}
-			
-			@Override
-			public void error(OpenPgpError openPgpError) {
-				// TODO Auto-generated method stub
-				
-			}
-		});
-	}
 	
 	@Override
 	protected void onStop() {
@@ -487,7 +458,7 @@ public class ManageAccountActivity extends XmppActivity {
 		 super.onActivityResult(requestCode, resultCode, data);
 		 if (resultCode == RESULT_OK) {
 			if (requestCode == REQUEST_ANNOUNCE_PGP) {
-				announcePgp();
+				announcePgp(selectedAccountForActionMode);
 			 }
 		 }
 	 }

src/eu/siacs/conversations/ui/XmppActivity.java πŸ”—

@@ -1,28 +1,37 @@
 package eu.siacs.conversations.ui;
 
+import org.openintents.openpgp.OpenPgpError;
+
 import eu.siacs.conversations.R;
+import eu.siacs.conversations.crypto.OnPgpEngineResult;
+import eu.siacs.conversations.entities.Account;
 import eu.siacs.conversations.entities.Conversation;
 import eu.siacs.conversations.services.XmppConnectionService;
 import eu.siacs.conversations.services.XmppConnectionService.XmppConnectionBinder;
 import eu.siacs.conversations.utils.ExceptionHelper;
 import android.app.Activity;
 import android.app.AlertDialog;
+import android.app.PendingIntent;
 import android.app.AlertDialog.Builder;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
+import android.content.IntentSender.SendIntentException;
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.util.Log;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
 
 public abstract class XmppActivity extends Activity {
 	
+	public static final int REQUEST_ANNOUNCE_PGP = 0x73731;
+	
 	protected final static String LOGTAG = "xmppService";
 	
 	public XmppConnectionService xmppConnectionService;
@@ -152,4 +161,30 @@ public abstract class XmppActivity extends Activity {
 				| Intent.FLAG_ACTIVITY_CLEAR_TOP);
 		startActivity(viewConversationIntent);
 	}
+	
+	protected void announcePgp(final Account account) {
+		xmppConnectionService.getPgpEngine().generateSignature(account, "online", new OnPgpEngineResult() {
+			
+			@Override
+			public void userInputRequried(PendingIntent pi) {
+				try {
+					startIntentSenderForResult(pi.getIntentSender(), REQUEST_ANNOUNCE_PGP, null, 0, 0, 0);
+				} catch (SendIntentException e) {
+					Log.d("xmppService","coulnd start intent for pgp anncouncment");
+				}
+			}
+			
+			@Override
+			public void success() {
+				xmppConnectionService.databaseBackend.updateAccount(account);
+				xmppConnectionService.sendPgpPresence(account, account.getPgpSignature());
+			}
+			
+			@Override
+			public void error(OpenPgpError openPgpError) {
+				// TODO Auto-generated method stub
+				
+			}
+		});
+	}
 }