/**
   * Method fired when "add" button is clicked.
   *
   * @param v add button's <tt>View</tt>
   */
  public void onAddClicked(View v) {
    Spinner accountsSpiner = (Spinner) findViewById(R.id.selectAccountSpinner);

    Account selectedAcc = (Account) accountsSpiner.getSelectedItem();
    if (selectedAcc == null) {
      logger.error("No account selected");
      return;
    }

    ProtocolProviderService pps = selectedAcc.getProtocolProvider();
    if (pps == null) {
      logger.error("No provider registered for account " + selectedAcc.getAccountName());
      return;
    }

    View content = findViewById(android.R.id.content);
    String contactAddress = ViewUtil.getTextViewValue(content, R.id.editContactName);

    String displayName = ViewUtil.getTextViewValue(content, R.id.editDisplayName);
    if (displayName != null && displayName.length() > 0) {
      addRenameListener(pps, null, contactAddress, displayName);
    }

    Spinner groupSpinner = (Spinner) findViewById(R.id.selectGroupSpinner);
    ContactListUtils.addContact(
        pps, (MetaContactGroup) groupSpinner.getSelectedItem(), contactAddress);
    finish();
  }
  /** Updates Jitsi icon notification to reflect current global status. */
  public void updateJitsiIconNotification() {
    String status;
    if (getGlobalStatus().isOnline()) {
      // At least one provider is online
      status = JitsiApplication.getResString(R.string.service_gui_ONLINE);
    } else {
      // There are no active providers so we consider to be in
      // the offline state
      status = JitsiApplication.getResString(R.string.service_gui_OFFLINE);
    }

    int notificationID = OSGiService.getGeneralNotificationId();
    if (notificationID == -1) {
      logger.debug(
          "Not displaying status notification because"
              + " there's no global notification icon available.");
      return;
    }

    AndroidUtils.updateGeneralNotification(
        JitsiApplication.getGlobalContext(),
        notificationID,
        JitsiApplication.getResString(R.string.app_name),
        status,
        System.currentTimeMillis());
  }
Example #3
0
  /**
   * Creates new call to target <tt>destination</tt>.
   *
   * @param context the android context
   * @param destination the target callee name that will be used.
   */
  private static void createCall(Context context, String destination) {
    Iterator<ProtocolProviderService> allProviders =
        AccountUtils.getRegisteredProviders().iterator();

    if (!allProviders.hasNext()) {
      logger.error("No registered providers found");
      return;
    }

    createCall(context, destination, allProviders.next());
  }
Example #4
0
  /**
   * Checks if there is a call in progress. If true then shows a warning toast and finishes the
   * activity.
   *
   * @param activity activity doing a check.
   * @return <tt>true</tt> if there is call in progress and <tt>Activity</tt> was finished.
   */
  public static boolean checkCallInProgress(Activity activity) {
    if (CallManager.getActiveCallsCount() > 0) {
      logger.warn("Call is in progress");

      Toast t =
          Toast.makeText(activity, R.string.service_gui_WARN_CALL_IN_PROGRESS, Toast.LENGTH_SHORT);
      t.show();

      activity.finish();
      return true;
    } else {
      return false;
    }
  }
Example #5
0
  /**
   * Creates new call to given <tt>destination</tt> using selected <tt>provider</tt>.
   *
   * @param context the android context
   * @param destination target callee name.
   * @param provider the provider that will be used to make a call.
   */
  public static void createCall(
      final Context context, final String destination, final ProtocolProviderService provider) {
    if (createCallThread != null) {
      logger.warn("Another call is already being created");
      return;
    } else if (CallManager.getActiveCallsCount() > 0) {
      logger.warn("Another call is in progress");
      return;
    }

    final long dialogId =
        ProgressDialogFragment.showProgressDialog(
            JitsiApplication.getResString(R.string.service_gui_OUTGOING_CALL),
            JitsiApplication.getResString(R.string.service_gui_OUTGOING_CALL_MSG, destination));

    createCallThread =
        new Thread("Create call thread") {
          public void run() {
            try {
              CallManager.createCall(provider, destination);
            } catch (Throwable t) {
              logger.error("Error creating the call: " + t.getMessage(), t);
              AndroidUtils.showAlertDialog(
                  context, context.getString(R.string.service_gui_ERROR), t.getMessage());
            } finally {
              if (DialogActivity.waitForDialogOpened(dialogId)) {
                DialogActivity.closeDialog(JitsiApplication.getGlobalContext(), dialogId);
              } else {
                logger.error("Failed to wait for the dialog: " + dialogId);
              }
              createCallThread = null;
            }
          }
        };

    createCallThread.start();
  }
Example #6
0
/**
 * @author Yana Stamcheva
 * @author Pawel Domas
 */
public class AndroidCallUtil {
  /** The logger for this class. */
  private static final Logger logger = Logger.getLogger(AndroidCallUtil.class);

  /** Field used to track the thread used to create outgoing calls. */
  private static Thread createCallThread;

  /**
   * Creates an android call.
   *
   * @param context the android context
   * @param callButtonView the button view that generated the call
   * @param contact the contact address to call
   */
  public static void createAndroidCall(Context context, View callButtonView, String contact) {
    if (AccountUtils.getRegisteredProviders().size() > 1)
      showCallViaMenu(context, callButtonView, contact);
    else createCall(context, contact);
  }

  /**
   * Creates new call to target <tt>destination</tt>.
   *
   * @param context the android context
   * @param destination the target callee name that will be used.
   */
  private static void createCall(Context context, String destination) {
    Iterator<ProtocolProviderService> allProviders =
        AccountUtils.getRegisteredProviders().iterator();

    if (!allProviders.hasNext()) {
      logger.error("No registered providers found");
      return;
    }

    createCall(context, destination, allProviders.next());
  }

  /**
   * Creates new call to given <tt>destination</tt> using selected <tt>provider</tt>.
   *
   * @param context the android context
   * @param destination target callee name.
   * @param provider the provider that will be used to make a call.
   */
  public static void createCall(
      final Context context, final String destination, final ProtocolProviderService provider) {
    if (createCallThread != null) {
      logger.warn("Another call is already being created");
      return;
    } else if (CallManager.getActiveCallsCount() > 0) {
      logger.warn("Another call is in progress");
      return;
    }

    final long dialogId =
        ProgressDialogFragment.showProgressDialog(
            JitsiApplication.getResString(R.string.service_gui_OUTGOING_CALL),
            JitsiApplication.getResString(R.string.service_gui_OUTGOING_CALL_MSG, destination));

    createCallThread =
        new Thread("Create call thread") {
          public void run() {
            try {
              CallManager.createCall(provider, destination);
            } catch (Throwable t) {
              logger.error("Error creating the call: " + t.getMessage(), t);
              AndroidUtils.showAlertDialog(
                  context, context.getString(R.string.service_gui_ERROR), t.getMessage());
            } finally {
              if (DialogActivity.waitForDialogOpened(dialogId)) {
                DialogActivity.closeDialog(JitsiApplication.getGlobalContext(), dialogId);
              } else {
                logger.error("Failed to wait for the dialog: " + dialogId);
              }
              createCallThread = null;
            }
          }
        };

    createCallThread.start();
  }

  /**
   * Shows "call via" menu allowing user to selected from multiple providers.
   *
   * @param context the android context
   * @param v the View that will contain the popup menu.
   * @param destination target callee name.
   */
  private static void showCallViaMenu(final Context context, View v, final String destination) {
    PopupMenu popup = new PopupMenu(context, v);

    Menu menu = popup.getMenu();

    Iterator<ProtocolProviderService> registeredProviders =
        AccountUtils.getRegisteredProviders().iterator();

    while (registeredProviders.hasNext()) {
      final ProtocolProviderService provider = registeredProviders.next();
      String accountAddress = provider.getAccountID().getAccountAddress();

      MenuItem menuItem = menu.add(Menu.NONE, Menu.NONE, Menu.NONE, accountAddress);

      menuItem.setOnMenuItemClickListener(
          new MenuItem.OnMenuItemClickListener() {
            public boolean onMenuItemClick(MenuItem item) {
              createCall(context, destination, provider);

              return false;
            }
          });
    }

    popup.show();
  }

  /**
   * Checks if there is a call in progress. If true then shows a warning toast and finishes the
   * activity.
   *
   * @param activity activity doing a check.
   * @return <tt>true</tt> if there is call in progress and <tt>Activity</tt> was finished.
   */
  public static boolean checkCallInProgress(Activity activity) {
    if (CallManager.getActiveCallsCount() > 0) {
      logger.warn("Call is in progress");

      Toast t =
          Toast.makeText(activity, R.string.service_gui_WARN_CALL_IN_PROGRESS, Toast.LENGTH_SHORT);
      t.show();

      activity.finish();
      return true;
    } else {
      return false;
    }
  }
}
/**
 * The <tt>AndroidLoginRenderer</tt> is the Android renderer for login events.
 *
 * @author Yana Stamcheva
 * @author Pawel Domas
 */
public class AndroidLoginRenderer implements LoginRenderer {
  /** The logger */
  private static final Logger logger = Logger.getLogger(AndroidLoginRenderer.class);

  /** The <tt>CallListener</tt>. */
  private CallListener androidCallListener;

  /** The android implementation of the provider presence listener. */
  private final ProviderPresenceStatusListener androidPresenceListener =
      new UIProviderPresenceStatusListener();

  /** The security authority used by this login renderer. */
  private final SecurityAuthority securityAuthority;

  /** Authorization handler instance. */
  private final AuthorizationHandlerImpl authorizationHandler;

  /** Cached global status value */
  private PresenceStatus globalStatus;

  /** List of global status listeners. */
  private EventListenerList<PresenceStatus> globalStatusListeners =
      new EventListenerList<PresenceStatus>();

  /** Caches avatar image to track the changes */
  private byte[] localAvatarRaw;

  /** Local avatar drawable */
  private Drawable localAvatar;

  /** Caches local status to track the changes */
  private byte[] localStatusRaw;

  /** Local status drawable */
  private Drawable localStatusDrawable;

  /**
   * Creates an instance of <tt>AndroidLoginRenderer</tt> by specifying the current
   * <tt>Context</tt>.
   *
   * @param defaultSecurityAuthority the security authority that will be used by this login renderer
   */
  public AndroidLoginRenderer(SecurityAuthority defaultSecurityAuthority) {
    androidCallListener = new AndroidCallListener();

    securityAuthority = defaultSecurityAuthority;

    authorizationHandler = new AuthorizationHandlerImpl();
  }

  /**
   * Adds the user interface related to the given protocol provider.
   *
   * @param protocolProvider the protocol provider for which we add the user interface
   */
  public void addProtocolProviderUI(ProtocolProviderService protocolProvider) {
    OperationSetBasicTelephony<?> telOpSet =
        protocolProvider.getOperationSet(OperationSetBasicTelephony.class);

    if (telOpSet != null) {
      telOpSet.addCallListener(androidCallListener);
    }

    OperationSetPresence presenceOpSet =
        protocolProvider.getOperationSet(OperationSetPresence.class);

    if (presenceOpSet != null) {
      presenceOpSet.addProviderPresenceStatusListener(androidPresenceListener);
    }
  }

  /**
   * Removes the user interface related to the given protocol provider.
   *
   * @param protocolProvider the protocol provider to remove
   */
  public void removeProtocolProviderUI(ProtocolProviderService protocolProvider) {
    OperationSetBasicTelephony<?> telOpSet =
        protocolProvider.getOperationSet(OperationSetBasicTelephony.class);

    if (telOpSet != null) {
      telOpSet.removeCallListener(androidCallListener);
    }

    OperationSetPresence presenceOpSet =
        protocolProvider.getOperationSet(OperationSetPresence.class);

    if (presenceOpSet != null) {
      presenceOpSet.removeProviderPresenceStatusListener(androidPresenceListener);
    }

    // Removes all chat session for unregistered provider
    ChatSessionManager.removeAllChatsForProvider(protocolProvider);
  }

  /**
   * Starts the connecting user interface for the given protocol provider.
   *
   * @param protocolProvider the protocol provider for which we add the connecting user interface
   */
  public void startConnectingUI(ProtocolProviderService protocolProvider) {}

  /**
   * Stops the connecting user interface for the given protocol provider.
   *
   * @param protocolProvider the protocol provider for which we remove the connecting user interface
   */
  public void stopConnectingUI(ProtocolProviderService protocolProvider) {}

  /**
   * Indicates that the given protocol provider has been connected at the given time.
   *
   * @param protocolProvider the <tt>ProtocolProviderService</tt> corresponding to the connected
   *     account
   * @param date the date/time at which the account has connected
   */
  public void protocolProviderConnected(ProtocolProviderService protocolProvider, long date) {

    OperationSetPresence presence = AccountStatusUtils.getProtocolPresenceOpSet(protocolProvider);

    if (presence != null) {
      presence.setAuthorizationHandler(authorizationHandler);
    }

    updateGlobalStatus();
  }

  /**
   * Indicates that a protocol provider connection has failed.
   *
   * @param protocolProvider the <tt>ProtocolProviderService</tt>, which connection failed
   * @param loginManagerCallback the <tt>LoginManager</tt> implementation, which is managing the
   *     process
   */
  public void protocolProviderConnectionFailed(
      final ProtocolProviderService protocolProvider, final LoginManager loginManagerCallback) {
    AccountID accountID = protocolProvider.getAccountID();

    AndroidUtils.showAlertConfirmDialog(
        JitsiApplication.getGlobalContext(),
        JitsiApplication.getResString(R.string.service_gui_ERROR),
        JitsiApplication.getResString(
            R.string.service_gui_CONNECTION_FAILED_MSG,
            accountID.getUserID(),
            accountID.getService()),
        JitsiApplication.getResString(R.string.service_gui_RETRY),
        new DialogActivity.DialogListener() {
          public boolean onConfirmClicked(DialogActivity dialog) {
            loginManagerCallback.login(protocolProvider);
            return true;
          }

          public void onDialogCancelled(DialogActivity dialog) {}
        });
  }

  /**
   * Returns the <tt>SecurityAuthority</tt> implementation related to this login renderer.
   *
   * @param protocolProvider the specific <tt>ProtocolProviderService</tt>, for which we're
   *     obtaining a security authority
   * @return the <tt>SecurityAuthority</tt> implementation related to this login renderer
   */
  public SecurityAuthority getSecurityAuthorityImpl(ProtocolProviderService protocolProvider) {
    return securityAuthority;
  }

  /** Updates Jitsi icon notification to reflect current global status. */
  public void updateJitsiIconNotification() {
    String status;
    if (getGlobalStatus().isOnline()) {
      // At least one provider is online
      status = JitsiApplication.getResString(R.string.service_gui_ONLINE);
    } else {
      // There are no active providers so we consider to be in
      // the offline state
      status = JitsiApplication.getResString(R.string.service_gui_OFFLINE);
    }

    int notificationID = OSGiService.getGeneralNotificationId();
    if (notificationID == -1) {
      logger.debug(
          "Not displaying status notification because"
              + " there's no global notification icon available.");
      return;
    }

    AndroidUtils.updateGeneralNotification(
        JitsiApplication.getGlobalContext(),
        notificationID,
        JitsiApplication.getResString(R.string.app_name),
        status,
        System.currentTimeMillis());
  }

  /**
   * Adds global status listener.
   *
   * @param l the listener to be add.
   */
  public void addGlobalStatusListener(EventListener<PresenceStatus> l) {
    globalStatusListeners.addEventListener(l);
  }

  /**
   * Removes global status listener.
   *
   * @param l the listener to remove.
   */
  public void removeGlobalStatusListener(EventListener<PresenceStatus> l) {
    globalStatusListeners.removeEventListener(l);
  }

  /**
   * Returns current global status.
   *
   * @return current global status.
   */
  public PresenceStatus getGlobalStatus() {
    if (globalStatus == null) {
      GlobalStatusService gss = AndroidGUIActivator.getGlobalStatusService();

      globalStatus = gss != null ? gss.getGlobalPresenceStatus() : GlobalStatusEnum.OFFLINE;
    }
    return globalStatus;
  }

  /** AuthorizationHandler instance used by this login renderer. */
  public AuthorizationHandlerImpl getAuthorizationHandler() {
    return authorizationHandler;
  }

  /**
   * Listens for all providerStatusChanged and providerStatusMessageChanged events in order to
   * refresh the account status panel, when a status is changed.
   */
  private class UIProviderPresenceStatusListener implements ProviderPresenceStatusListener {
    public void providerStatusChanged(ProviderPresenceStatusChangeEvent evt) {
      updateGlobalStatus();
    }

    public void providerStatusMessageChanged(PropertyChangeEvent evt) {}
  }

  /**
   * Indicates if the given <tt>protocolProvider</tt> related user interface is already rendered.
   *
   * @param protocolProvider the <tt>ProtocolProviderService</tt>, which related user interface
   *     we're looking for
   * @return <tt>true</tt> if the given <tt>protocolProvider</tt> related user interface is already
   *     rendered
   */
  public boolean containsProtocolProviderUI(ProtocolProviderService protocolProvider) {
    return false;
  }

  /** Updates the global status by picking the most connected protocol provider status. */
  private void updateGlobalStatus() {
    // Only if the GUI is active (bundle context will be null on shutdown)
    if (AndroidGUIActivator.bundleContext != null) {
      // Invalidate local status image
      localStatusRaw = null;
      // Invalidate global status
      globalStatus = null;
      globalStatusListeners.notifyEventListeners(getGlobalStatus());
    }

    updateJitsiIconNotification();
  }

  /**
   * Returns the local user avatar drawable.
   *
   * @return the local user avatar drawable.
   */
  public Drawable getLocalAvatarDrawable() {
    GlobalDisplayDetailsService displayDetailsService =
        AndroidGUIActivator.getGlobalDisplayDetailsService();

    byte[] avatarImage = displayDetailsService.getGlobalDisplayAvatar();
    // Re-create drawable only if avatar has changed
    if (avatarImage != localAvatarRaw) {
      localAvatarRaw = avatarImage;
      localAvatar = AndroidImageUtil.roundedDrawableFromBytes(avatarImage);
    }
    return localAvatar;
  }

  /**
   * Returns the local user status drawable.
   *
   * @return the local user status drawable
   */
  public synchronized Drawable getLocalStatusDrawable() {
    byte[] statusImage = StatusUtil.getContactStatusIcon(getGlobalStatus());
    if (statusImage != localStatusRaw) {
      localStatusRaw = statusImage;
      localStatusDrawable =
          localStatusRaw != null ? AndroidImageUtil.drawableFromBytes(statusImage) : null;
    }
    return localStatusDrawable;
  }
}
/**
 * This activity allows user to add new contacts.
 *
 * @author Pawel Domas
 */
public class AddContactActivity extends OSGiActivity {
  /** The logger. */
  private static final Logger logger = Logger.getLogger(AddContactActivity.class);

  /** {@inheritDoc} */
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.add_contact);

    setTitle(R.string.service_gui_ADD_CONTACT);

    initAccountSpinner();

    initContactGroupSpinner();
  }

  /** Initializes "select account" spinner with existing accounts. */
  private void initAccountSpinner() {
    Spinner accountsSpiner = (Spinner) findViewById(R.id.selectAccountSpinner);

    Iterator<ProtocolProviderService> providers = AccountUtils.getRegisteredProviders().iterator();

    List<AccountID> accounts = new ArrayList<AccountID>();

    int selectedIdx = -1;
    int idx = 0;

    while (providers.hasNext()) {
      ProtocolProviderService provider = providers.next();

      OperationSet opSet = provider.getOperationSet(OperationSetPresence.class);

      if (opSet == null) continue;

      AccountID account = provider.getAccountID();
      accounts.add(account);
      idx++;

      if (account.isPreferredProvider()) {
        selectedIdx = idx;
      }
    }

    AccountsListAdapter accountsAdapter =
        new AccountsListAdapter(
            this, R.layout.select_account_row, R.layout.select_account_dropdown, accounts, true);
    accountsSpiner.setAdapter(accountsAdapter);

    // if we have only select account option and only one account
    // select the available account
    if (accounts.size() == 1) accountsSpiner.setSelection(0);
    else accountsSpiner.setSelection(selectedIdx);
  }

  /** Initializes select contact group spinner with contact groups. */
  private void initContactGroupSpinner() {
    Spinner groupSpinner = (Spinner) findViewById(R.id.selectGroupSpinner);

    MetaContactGroupAdapter contactGroupAdapter =
        new MetaContactGroupAdapter(this, R.id.selectGroupSpinner, true, true);

    contactGroupAdapter.setItemLayout(R.layout.simple_spinner_item);
    contactGroupAdapter.setDropDownLayout(R.layout.dropdown_spinner_item);

    groupSpinner.setAdapter(contactGroupAdapter);
  }

  /**
   * Method fired when "add" button is clicked.
   *
   * @param v add button's <tt>View</tt>
   */
  public void onAddClicked(View v) {
    Spinner accountsSpiner = (Spinner) findViewById(R.id.selectAccountSpinner);

    Account selectedAcc = (Account) accountsSpiner.getSelectedItem();
    if (selectedAcc == null) {
      logger.error("No account selected");
      return;
    }

    ProtocolProviderService pps = selectedAcc.getProtocolProvider();
    if (pps == null) {
      logger.error("No provider registered for account " + selectedAcc.getAccountName());
      return;
    }

    View content = findViewById(android.R.id.content);
    String contactAddress = ViewUtil.getTextViewValue(content, R.id.editContactName);

    String displayName = ViewUtil.getTextViewValue(content, R.id.editDisplayName);
    if (displayName != null && displayName.length() > 0) {
      addRenameListener(pps, null, contactAddress, displayName);
    }

    Spinner groupSpinner = (Spinner) findViewById(R.id.selectGroupSpinner);
    ContactListUtils.addContact(
        pps, (MetaContactGroup) groupSpinner.getSelectedItem(), contactAddress);
    finish();
  }

  /**
   * Adds a rename listener.
   *
   * @param protocolProvider the protocol provider to which the contact was added
   * @param metaContact the <tt>MetaContact</tt> if the new contact was added to an existing meta
   *     contact
   * @param contactAddress the address of the newly added contact
   * @param displayName the new display name
   */
  private void addRenameListener(
      final ProtocolProviderService protocolProvider,
      final MetaContact metaContact,
      final String contactAddress,
      final String displayName) {
    AndroidGUIActivator.getContactListService()
        .addMetaContactListListener(
            new MetaContactListAdapter() {
              @Override
              public void metaContactAdded(MetaContactEvent evt) {
                if (evt.getSourceMetaContact().getContact(contactAddress, protocolProvider)
                    != null) {
                  renameContact(evt.getSourceMetaContact(), displayName);
                }
              }

              @Override
              public void protoContactAdded(ProtoContactEvent evt) {
                if (metaContact != null && evt.getNewParent().equals(metaContact)) {
                  renameContact(metaContact, displayName);
                }
              }
            });
  }

  /**
   * Renames the given meta contact.
   *
   * @param metaContact the <tt>MetaContact</tt> to rename
   * @param displayName the new display name
   */
  private void renameContact(final MetaContact metaContact, final String displayName) {
    new Thread() {
      @Override
      public void run() {
        AndroidGUIActivator.getContactListService().renameMetaContact(metaContact, displayName);
      }
    }.start();
  }
}