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