XmppActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import eu.siacs.conversations.R;
  4import eu.siacs.conversations.entities.Account;
  5import eu.siacs.conversations.entities.Contact;
  6import eu.siacs.conversations.entities.Conversation;
  7import eu.siacs.conversations.entities.Message;
  8import eu.siacs.conversations.entities.Presences;
  9import eu.siacs.conversations.services.XmppConnectionService;
 10import eu.siacs.conversations.services.XmppConnectionService.XmppConnectionBinder;
 11import eu.siacs.conversations.utils.ExceptionHelper;
 12import android.app.Activity;
 13import android.app.AlertDialog;
 14import android.app.PendingIntent;
 15import android.app.AlertDialog.Builder;
 16import android.content.ComponentName;
 17import android.content.Context;
 18import android.content.DialogInterface;
 19import android.content.DialogInterface.OnClickListener;
 20import android.content.IntentSender.SendIntentException;
 21import android.content.Intent;
 22import android.content.ServiceConnection;
 23import android.net.Uri;
 24import android.os.Bundle;
 25import android.os.IBinder;
 26import android.view.MenuItem;
 27import android.view.View;
 28import android.view.inputmethod.InputMethodManager;
 29import android.widget.EditText;
 30
 31public abstract class XmppActivity extends Activity {
 32
 33	public static final int REQUEST_ANNOUNCE_PGP = 0x73731;
 34
 35	protected final static String LOGTAG = "xmppService";
 36
 37	public XmppConnectionService xmppConnectionService;
 38	public boolean xmppConnectionServiceBound = false;
 39	protected boolean handledViewIntent = false;
 40	
 41	protected interface OnValueEdited {
 42		public void onValueEdited(String value);
 43	}
 44
 45	protected ServiceConnection mConnection = new ServiceConnection() {
 46
 47		@Override
 48		public void onServiceConnected(ComponentName className, IBinder service) {
 49			XmppConnectionBinder binder = (XmppConnectionBinder) service;
 50			xmppConnectionService = binder.getService();
 51			xmppConnectionServiceBound = true;
 52			onBackendConnected();
 53		}
 54
 55		@Override
 56		public void onServiceDisconnected(ComponentName arg0) {
 57			xmppConnectionServiceBound = false;
 58		}
 59	};
 60
 61	@Override
 62	protected void onStart() {
 63		super.onStart();
 64		if (!xmppConnectionServiceBound) {
 65			connectToBackend();
 66		}
 67	}
 68
 69	public void connectToBackend() {
 70		Intent intent = new Intent(this, XmppConnectionService.class);
 71		intent.setAction("ui");
 72		startService(intent);
 73		bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
 74	}
 75
 76	@Override
 77	protected void onStop() {
 78		super.onStop();
 79		if (xmppConnectionServiceBound) {
 80			unbindService(mConnection);
 81			xmppConnectionServiceBound = false;
 82		}
 83	}
 84
 85	protected void hideKeyboard() {
 86		InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
 87
 88		View focus = getCurrentFocus();
 89
 90		if (focus != null) {
 91
 92			inputManager.hideSoftInputFromWindow(focus.getWindowToken(),
 93					InputMethodManager.HIDE_NOT_ALWAYS);
 94		}
 95	}
 96
 97	public boolean hasPgp() {
 98		return xmppConnectionService.getPgpEngine() != null;
 99	}
100
101	public void showInstallPgpDialog() {
102		Builder builder = new AlertDialog.Builder(this);
103		builder.setTitle(getString(R.string.openkeychain_required));
104		builder.setIconAttribute(android.R.attr.alertDialogIcon);
105		builder.setMessage(getText(R.string.openkeychain_required_long));
106		builder.setNegativeButton(getString(R.string.cancel), null);
107		builder.setNeutralButton(getString(R.string.restart),
108				new OnClickListener() {
109
110					@Override
111					public void onClick(DialogInterface dialog, int which) {
112						if (xmppConnectionServiceBound) {
113							unbindService(mConnection);
114							xmppConnectionServiceBound = false;
115						}
116						stopService(new Intent(XmppActivity.this,
117								XmppConnectionService.class));
118						finish();
119					}
120				});
121		builder.setPositiveButton(getString(R.string.install),
122				new OnClickListener() {
123
124					@Override
125					public void onClick(DialogInterface dialog, int which) {
126						Uri uri = Uri
127								.parse("market://details?id=org.sufficientlysecure.keychain");
128						Intent intent = new Intent(Intent.ACTION_VIEW, uri);
129						startActivity(intent);
130						finish();
131					}
132				});
133		builder.create().show();
134	}
135
136	abstract void onBackendConnected();
137
138	public boolean onOptionsItemSelected(MenuItem item) {
139		switch (item.getItemId()) {
140		case R.id.action_settings:
141			startActivity(new Intent(this, SettingsActivity.class));
142			break;
143		case R.id.action_accounts:
144			startActivity(new Intent(this, ManageAccountActivity.class));
145			break;
146		}
147		return super.onOptionsItemSelected(item);
148	}
149
150	@Override
151	protected void onCreate(Bundle savedInstanceState) {
152		super.onCreate(savedInstanceState);
153		ExceptionHelper.init(getApplicationContext());
154	}
155
156	public void switchToConversation(Conversation conversation) {
157		switchToConversation(conversation, null, false);
158	}
159
160	public void switchToConversation(Conversation conversation, String text,
161			boolean newTask) {
162		Intent viewConversationIntent = new Intent(this,
163				ConversationActivity.class);
164		viewConversationIntent.setAction(Intent.ACTION_VIEW);
165		viewConversationIntent.putExtra(ConversationActivity.CONVERSATION,
166				conversation.getUuid());
167		if (text != null) {
168			viewConversationIntent.putExtra(ConversationActivity.TEXT, text);
169		}
170		viewConversationIntent.setType(ConversationActivity.VIEW_CONVERSATION);
171		if (newTask) {
172			viewConversationIntent.setFlags(viewConversationIntent.getFlags()
173					| Intent.FLAG_ACTIVITY_NEW_TASK
174					| Intent.FLAG_ACTIVITY_SINGLE_TOP);
175		} else {
176			viewConversationIntent.setFlags(viewConversationIntent.getFlags()
177					| Intent.FLAG_ACTIVITY_CLEAR_TOP);
178		}
179		startActivity(viewConversationIntent);
180	}
181
182	public void switchToContactDetails(Contact contact) {
183		Intent intent = new Intent(this, ContactDetailsActivity.class);
184		intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT);
185		intent.putExtra("account", contact.getAccount().getJid());
186		intent.putExtra("contact", contact.getJid());
187		startActivity(intent);
188	}
189
190	protected void announcePgp(Account account, final Conversation conversation) {
191		xmppConnectionService.getPgpEngine().generateSignature(account,
192				"online", new UiCallback<Account>() {
193
194					@Override
195					public void userInputRequried(PendingIntent pi,
196							Account account) {
197						try {
198							startIntentSenderForResult(pi.getIntentSender(),
199									REQUEST_ANNOUNCE_PGP, null, 0, 0, 0);
200						} catch (SendIntentException e) {}
201					}
202
203					@Override
204					public void success(Account account) {
205						xmppConnectionService.databaseBackend
206								.updateAccount(account);
207						xmppConnectionService.sendPresencePacket(account,
208								xmppConnectionService.getPresenceGenerator()
209										.sendPresence(account));
210						if (conversation != null) {
211							conversation
212									.setNextEncryption(Message.ENCRYPTION_PGP);
213						}
214					}
215
216					@Override
217					public void error(int error, Account account) {
218						displayErrorDialog(error);
219					}
220				});
221	}
222
223	protected void displayErrorDialog(final int errorCode) {
224		runOnUiThread(new Runnable() {
225
226			@Override
227			public void run() {
228				AlertDialog.Builder builder = new AlertDialog.Builder(
229						XmppActivity.this);
230				builder.setIconAttribute(android.R.attr.alertDialogIcon);
231				builder.setTitle(getString(R.string.error));
232				builder.setMessage(errorCode);
233				builder.setNeutralButton(R.string.accept, null);
234				builder.create().show();
235			}
236		});
237
238	}
239
240	protected void showAddToRosterDialog(final Conversation conversation) {
241		String jid = conversation.getContactJid();
242		AlertDialog.Builder builder = new AlertDialog.Builder(this);
243		builder.setTitle(jid);
244		builder.setMessage(getString(R.string.not_in_roster));
245		builder.setNegativeButton(getString(R.string.cancel), null);
246		builder.setPositiveButton(getString(R.string.add_contact),
247				new DialogInterface.OnClickListener() {
248
249					@Override
250					public void onClick(DialogInterface dialog, int which) {
251						String jid = conversation.getContactJid();
252						Account account = conversation.getAccount();
253						Contact contact = account.getRoster().getContact(jid);
254						xmppConnectionService.createContact(contact);
255					}
256				});
257		builder.create().show();
258	}
259
260	protected void quickEdit(final String previousValue, final OnValueEdited callback) {
261		AlertDialog.Builder builder = new AlertDialog.Builder(this);
262		View view = (View) getLayoutInflater().inflate(R.layout.quickedit, null);
263		final EditText editor = (EditText) view.findViewById(R.id.editor);
264		editor.setText(previousValue);
265		builder.setView(view);
266		builder.setNegativeButton(R.string.cancel, null);
267		builder.setPositiveButton(R.string.edit, new OnClickListener() {
268			
269			@Override
270			public void onClick(DialogInterface dialog, int which) {
271				String value = editor.getText().toString();
272				if (!previousValue.equals(value) && value.trim().length() > 0) {
273					callback.onValueEdited(value);
274				}
275			}
276		});
277		builder.create().show();
278	}
279	
280	public void selectPresence(final Conversation conversation,
281			final OnPresenceSelected listener) {
282		Contact contact = conversation.getContact();
283		if (contact == null) {
284			showAddToRosterDialog(conversation);
285		} else {
286			Presences presences = contact.getPresences();
287			if (presences.size() == 0) {
288				conversation.setNextPresence(null);
289				listener.onPresenceSelected();
290			} else if (presences.size() == 1) {
291				String presence = (String) presences.asStringArray()[0];
292				conversation.setNextPresence(presence);
293				listener.onPresenceSelected();
294			} else {
295				final StringBuilder presence = new StringBuilder();
296				AlertDialog.Builder builder = new AlertDialog.Builder(this);
297				builder.setTitle(getString(R.string.choose_presence));
298				final String[] presencesArray = presences.asStringArray();
299				int preselectedPresence = 0;
300				for (int i = 0; i < presencesArray.length; ++i) {
301					if (presencesArray[i].equals(contact.lastseen.presence)) {
302						preselectedPresence = i;
303						break;
304					}
305				}
306				presence.append(presencesArray[preselectedPresence]);
307				builder.setSingleChoiceItems(presencesArray,
308						preselectedPresence,
309						new DialogInterface.OnClickListener() {
310
311							@Override
312							public void onClick(DialogInterface dialog,
313									int which) {
314								presence.delete(0, presence.length());
315								presence.append(presencesArray[which]);
316							}
317						});
318				builder.setNegativeButton(R.string.cancel, null);
319				builder.setPositiveButton(R.string.ok, new OnClickListener() {
320
321					@Override
322					public void onClick(DialogInterface dialog, int which) {
323						conversation.setNextPresence(presence.toString());
324						listener.onPresenceSelected();
325					}
326				});
327				builder.create().show();
328			}
329		}
330	}
331}