Search in sources :

Example 1 with Bookmark

use of eu.siacs.conversations.entities.Bookmark in project Conversations by siacs.

the class XmppConnectionService method renameInMuc.

public void renameInMuc(final Conversation conversation, final String nick, final UiCallback<Conversation> callback) {
    final MucOptions options = conversation.getMucOptions();
    final Jid joinJid = options.createJoinJid(nick);
    if (options.online()) {
        Account account = conversation.getAccount();
        options.setOnRenameListener(new OnRenameListener() {

            @Override
            public void onSuccess() {
                conversation.setContactJid(joinJid);
                databaseBackend.updateConversation(conversation);
                Bookmark bookmark = conversation.getBookmark();
                if (bookmark != null) {
                    bookmark.setNick(nick);
                    pushBookmarks(bookmark.getAccount());
                }
                callback.success(conversation);
            }

            @Override
            public void onFailure() {
                callback.error(R.string.nick_in_use, conversation);
            }
        });
        PresencePacket packet = new PresencePacket();
        packet.setTo(joinJid);
        packet.setFrom(conversation.getAccount().getJid());
        String sig = account.getPgpSignature();
        if (sig != null) {
            packet.addChild("status").setContent("online");
            packet.addChild("x", "jabber:x:signed").setContent(sig);
        }
        sendPresencePacket(account, packet);
    } else {
        conversation.setContactJid(joinJid);
        databaseBackend.updateConversation(conversation);
        if (conversation.getAccount().getStatus() == Account.State.ONLINE) {
            Bookmark bookmark = conversation.getBookmark();
            if (bookmark != null) {
                bookmark.setNick(nick);
                pushBookmarks(bookmark.getAccount());
            }
            joinMuc(conversation);
        }
    }
}
Also used : Account(eu.siacs.conversations.entities.Account) OnRenameListener(eu.siacs.conversations.entities.MucOptions.OnRenameListener) MucOptions(eu.siacs.conversations.entities.MucOptions) Jid(eu.siacs.conversations.xmpp.jid.Jid) Bookmark(eu.siacs.conversations.entities.Bookmark) PresencePacket(eu.siacs.conversations.xmpp.stanzas.PresencePacket)

Example 2 with Bookmark

use of eu.siacs.conversations.entities.Bookmark in project Conversations by siacs.

the class StartConversationActivity method filterConferences.

protected void filterConferences(String needle) {
    this.conferences.clear();
    for (Account account : xmppConnectionService.getAccounts()) {
        if (account.getStatus() != Account.State.DISABLED) {
            for (Bookmark bookmark : account.getBookmarks()) {
                if (bookmark.match(this, needle)) {
                    this.conferences.add(bookmark);
                }
            }
        }
    }
    Collections.sort(this.conferences);
    mConferenceAdapter.notifyDataSetChanged();
}
Also used : Account(eu.siacs.conversations.entities.Account) Bookmark(eu.siacs.conversations.entities.Bookmark)

Example 3 with Bookmark

use of eu.siacs.conversations.entities.Bookmark in project Conversations by siacs.

the class MessageParser method onMessagePacketReceived.

@Override
public void onMessagePacketReceived(Account account, MessagePacket original) {
    if (handleErrorMessage(account, original)) {
        return;
    }
    final MessagePacket packet;
    Long timestamp = null;
    final boolean isForwarded;
    boolean isCarbon = false;
    String serverMsgId = null;
    final Element fin = original.findChild("fin", Namespace.MAM_LEGACY);
    if (fin != null) {
        mXmppConnectionService.getMessageArchiveService().processFinLegacy(fin, original.getFrom());
        return;
    }
    final boolean mamLegacy = original.hasChild("result", Namespace.MAM_LEGACY);
    final Element result = original.findChild("result", mamLegacy ? Namespace.MAM_LEGACY : Namespace.MAM);
    final MessageArchiveService.Query query = result == null ? null : mXmppConnectionService.getMessageArchiveService().findQuery(result.getAttribute("queryid"));
    if (query != null && query.validFrom(original.getFrom())) {
        Pair<MessagePacket, Long> f = original.getForwardedMessagePacket("result", mamLegacy ? Namespace.MAM_LEGACY : Namespace.MAM);
        if (f == null) {
            return;
        }
        timestamp = f.second;
        packet = f.first;
        isForwarded = true;
        serverMsgId = result.getAttribute("id");
        query.incrementMessageCount();
    } else if (query != null) {
        Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": received mam result from invalid sender");
        return;
    } else if (original.fromServer(account)) {
        Pair<MessagePacket, Long> f;
        f = original.getForwardedMessagePacket("received", "urn:xmpp:carbons:2");
        f = f == null ? original.getForwardedMessagePacket("sent", "urn:xmpp:carbons:2") : f;
        packet = f != null ? f.first : original;
        if (handleErrorMessage(account, packet)) {
            return;
        }
        timestamp = f != null ? f.second : null;
        isCarbon = f != null;
        isForwarded = isCarbon;
    } else {
        packet = original;
        isForwarded = false;
    }
    if (timestamp == null) {
        timestamp = AbstractParser.parseTimestamp(original, AbstractParser.parseTimestamp(packet));
    }
    final String body = packet.getBody();
    final Element mucUserElement = packet.findChild("x", "http://jabber.org/protocol/muc#user");
    final String pgpEncrypted = packet.findChildContent("x", "jabber:x:encrypted");
    final Element replaceElement = packet.findChild("replace", "urn:xmpp:message-correct:0");
    final Element oob = packet.findChild("x", "jabber:x:oob");
    final boolean isOob = oob != null && body != null && body.equals(oob.findChildContent("url"));
    final String replacementId = replaceElement == null ? null : replaceElement.getAttribute("id");
    final Element axolotlEncrypted = packet.findChild(XmppAxolotlMessage.CONTAINERTAG, AxolotlService.PEP_PREFIX);
    int status;
    final Jid counterpart;
    final Jid to = packet.getTo();
    final Jid from = packet.getFrom();
    final Element originId = packet.findChild("origin-id", Namespace.STANZA_IDS);
    final String remoteMsgId;
    if (originId != null && originId.getAttribute("id") != null) {
        remoteMsgId = originId.getAttribute("id");
    } else {
        remoteMsgId = packet.getId();
    }
    boolean notify = false;
    if (from == null) {
        Log.d(Config.LOGTAG, "no from in: " + packet.toString());
        return;
    }
    boolean isTypeGroupChat = packet.getType() == MessagePacket.TYPE_GROUPCHAT;
    boolean isProperlyAddressed = (to != null) && (!to.isBareJid() || account.countPresences() == 0);
    boolean isMucStatusMessage = from.isBareJid() && mucUserElement != null && mucUserElement.hasChild("status");
    if (packet.fromAccount(account)) {
        status = Message.STATUS_SEND;
        counterpart = to != null ? to : account.getJid();
    } else {
        status = Message.STATUS_RECEIVED;
        counterpart = from;
    }
    Invite invite = extractInvite(account, packet);
    if (invite != null && invite.execute(account)) {
        return;
    }
    if (query == null && extractChatState(mXmppConnectionService.find(account, counterpart.toBareJid()), isTypeGroupChat, packet)) {
        mXmppConnectionService.updateConversationUi();
    }
    if ((body != null || pgpEncrypted != null || axolotlEncrypted != null) && !isMucStatusMessage) {
        Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, counterpart.toBareJid(), isTypeGroupChat, false, query);
        final boolean conversationMultiMode = conversation.getMode() == Conversation.MODE_MULTI;
        if (serverMsgId == null) {
            serverMsgId = extractStanzaId(packet, isTypeGroupChat, conversation);
        }
        if (isTypeGroupChat) {
            if (conversation.getMucOptions().isSelf(counterpart)) {
                status = Message.STATUS_SEND_RECEIVED;
                //not really carbon but received from another resource
                isCarbon = true;
                if (mXmppConnectionService.markMessage(conversation, remoteMsgId, status, serverMsgId)) {
                    return;
                } else if (remoteMsgId == null || Config.IGNORE_ID_REWRITE_IN_MUC) {
                    Message message = conversation.findSentMessageWithBody(packet.getBody());
                    if (message != null) {
                        mXmppConnectionService.markMessage(message, status);
                        return;
                    }
                }
            } else {
                status = Message.STATUS_RECEIVED;
            }
        }
        final Message message;
        if (body != null && body.startsWith("?OTR") && Config.supportOtr()) {
            if (!isForwarded && !isTypeGroupChat && isProperlyAddressed && !conversationMultiMode) {
                message = parseOtrChat(body, from, remoteMsgId, conversation);
                if (message == null) {
                    return;
                }
            } else {
                Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": ignoring OTR message from " + from + " isForwarded=" + Boolean.toString(isForwarded) + ", isProperlyAddressed=" + Boolean.valueOf(isProperlyAddressed));
                message = new Message(conversation, body, Message.ENCRYPTION_NONE, status);
            }
        } else if (pgpEncrypted != null && Config.supportOpenPgp()) {
            message = new Message(conversation, pgpEncrypted, Message.ENCRYPTION_PGP, status);
        } else if (axolotlEncrypted != null && Config.supportOmemo()) {
            Jid origin;
            if (conversationMultiMode) {
                final Jid fallback = conversation.getMucOptions().getTrueCounterpart(counterpart);
                origin = getTrueCounterpart(query != null ? mucUserElement : null, fallback);
                if (origin == null) {
                    Log.d(Config.LOGTAG, "axolotl message in non anonymous conference received");
                    return;
                }
            } else {
                origin = from;
            }
            message = parseAxolotlChat(axolotlEncrypted, origin, conversation, status);
            if (message == null) {
                return;
            }
            if (conversationMultiMode) {
                message.setTrueCounterpart(origin);
            }
        } else {
            message = new Message(conversation, body, Message.ENCRYPTION_NONE, status);
        }
        message.setCounterpart(counterpart);
        message.setRemoteMsgId(remoteMsgId);
        message.setServerMsgId(serverMsgId);
        message.setCarbon(isCarbon);
        message.setTime(timestamp);
        message.setOob(isOob);
        message.markable = packet.hasChild("markable", "urn:xmpp:chat-markers:0");
        if (conversationMultiMode) {
            final Jid fallback = conversation.getMucOptions().getTrueCounterpart(counterpart);
            Jid trueCounterpart;
            if (message.getEncryption() == Message.ENCRYPTION_AXOLOTL) {
                trueCounterpart = message.getTrueCounterpart();
            } else if (Config.PARSE_REAL_JID_FROM_MUC_MAM) {
                trueCounterpart = getTrueCounterpart(query != null ? mucUserElement : null, fallback);
            } else {
                trueCounterpart = fallback;
            }
            if (trueCounterpart != null && trueCounterpart.toBareJid().equals(account.getJid().toBareJid())) {
                status = isTypeGroupChat ? Message.STATUS_SEND_RECEIVED : Message.STATUS_SEND;
            }
            message.setStatus(status);
            message.setTrueCounterpart(trueCounterpart);
            if (!isTypeGroupChat) {
                message.setType(Message.TYPE_PRIVATE);
            }
        } else {
            updateLastseen(account, from);
        }
        if (replacementId != null && mXmppConnectionService.allowMessageCorrection()) {
            Message replacedMessage = conversation.findMessageWithRemoteIdAndCounterpart(replacementId, counterpart, message.getStatus() == Message.STATUS_RECEIVED, message.isCarbon());
            if (replacedMessage != null) {
                final boolean fingerprintsMatch = replacedMessage.getFingerprint() == null || replacedMessage.getFingerprint().equals(message.getFingerprint());
                final boolean trueCountersMatch = replacedMessage.getTrueCounterpart() != null && replacedMessage.getTrueCounterpart().equals(message.getTrueCounterpart());
                final boolean duplicate = conversation.hasDuplicateMessage(message);
                if (fingerprintsMatch && (trueCountersMatch || !conversationMultiMode) && !duplicate) {
                    Log.d(Config.LOGTAG, "replaced message '" + replacedMessage.getBody() + "' with '" + message.getBody() + "'");
                    synchronized (replacedMessage) {
                        final String uuid = replacedMessage.getUuid();
                        replacedMessage.setUuid(UUID.randomUUID().toString());
                        replacedMessage.setBody(message.getBody());
                        replacedMessage.setEdited(replacedMessage.getRemoteMsgId());
                        replacedMessage.setRemoteMsgId(remoteMsgId);
                        replacedMessage.setEncryption(message.getEncryption());
                        if (replacedMessage.getStatus() == Message.STATUS_RECEIVED) {
                            replacedMessage.markUnread();
                        }
                        mXmppConnectionService.updateMessage(replacedMessage, uuid);
                        mXmppConnectionService.getNotificationService().updateNotification(false);
                        if (mXmppConnectionService.confirmMessages() && (replacedMessage.trusted() || replacedMessage.getType() == Message.TYPE_PRIVATE) && remoteMsgId != null && !isForwarded && !isTypeGroupChat) {
                            sendMessageReceipts(account, packet);
                        }
                        if (replacedMessage.getEncryption() == Message.ENCRYPTION_PGP) {
                            conversation.getAccount().getPgpDecryptionService().discard(replacedMessage);
                            conversation.getAccount().getPgpDecryptionService().decrypt(replacedMessage, false);
                        }
                    }
                    return;
                } else {
                    Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": received message correction but verification didn't check out");
                }
            }
        }
        long deletionDate = mXmppConnectionService.getAutomaticMessageDeletionDate();
        if (deletionDate != 0 && message.getTimeSent() < deletionDate) {
            Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": skipping message from " + message.getCounterpart().toString() + " because it was sent prior to our deletion date");
            return;
        }
        boolean checkForDuplicates = (isTypeGroupChat && packet.hasChild("delay", "urn:xmpp:delay")) || message.getType() == Message.TYPE_PRIVATE || message.getServerMsgId() != null;
        if (checkForDuplicates && conversation.hasDuplicateMessage(message)) {
            Log.d(Config.LOGTAG, "skipping duplicate message from " + message.getCounterpart().toString() + " " + message.getBody());
            return;
        }
        if (query != null && query.getPagingOrder() == MessageArchiveService.PagingOrder.REVERSE) {
            conversation.prepend(message);
        } else {
            conversation.add(message);
        }
        if (query != null) {
            query.incrementActualMessageCount();
        }
        if (query == null || query.isCatchup()) {
            //either no mam or catchup
            if (status == Message.STATUS_SEND || status == Message.STATUS_SEND_RECEIVED) {
                mXmppConnectionService.markRead(conversation);
                if (query == null) {
                    activateGracePeriod(account);
                }
            } else {
                message.markUnread();
                notify = true;
            }
        }
        if (message.getEncryption() == Message.ENCRYPTION_PGP) {
            notify = conversation.getAccount().getPgpDecryptionService().decrypt(message, notify);
        }
        if (query == null) {
            mXmppConnectionService.updateConversationUi();
        }
        if (mXmppConnectionService.confirmMessages() && (message.trusted() || message.getType() == Message.TYPE_PRIVATE) && remoteMsgId != null && !isForwarded && !isTypeGroupChat) {
            sendMessageReceipts(account, packet);
        }
        if (message.getStatus() == Message.STATUS_RECEIVED && conversation.getOtrSession() != null && !conversation.getOtrSession().getSessionID().getUserID().equals(message.getCounterpart().getResourcepart())) {
            conversation.endOtrIfNeeded();
        }
        mXmppConnectionService.databaseBackend.createMessage(message);
        final HttpConnectionManager manager = this.mXmppConnectionService.getHttpConnectionManager();
        if (message.trusted() && message.treatAsDownloadable() != Message.Decision.NEVER && manager.getAutoAcceptFileSize() > 0) {
            manager.createNewDownloadConnection(message);
        } else if (notify) {
            if (query == null) {
                mXmppConnectionService.getNotificationService().push(message);
            } else if (query.isCatchup()) {
                // mam catchup
                mXmppConnectionService.getNotificationService().pushFromBacklog(message);
            }
        }
    } else if (!packet.hasChild("body")) {
        //no body
        Conversation conversation = mXmppConnectionService.find(account, from.toBareJid());
        if (isTypeGroupChat) {
            if (packet.hasChild("subject")) {
                if (conversation != null && conversation.getMode() == Conversation.MODE_MULTI) {
                    conversation.setHasMessagesLeftOnServer(conversation.countMessages() > 0);
                    String subject = packet.findChildContent("subject");
                    conversation.getMucOptions().setSubject(subject);
                    final Bookmark bookmark = conversation.getBookmark();
                    if (bookmark != null && bookmark.getBookmarkName() == null) {
                        if (bookmark.setBookmarkName(subject)) {
                            mXmppConnectionService.pushBookmarks(account);
                        }
                    }
                    mXmppConnectionService.updateConversationUi();
                    return;
                }
            }
        }
        if (conversation != null && mucUserElement != null && from.isBareJid()) {
            for (Element child : mucUserElement.getChildren()) {
                if ("status".equals(child.getName())) {
                    try {
                        int code = Integer.parseInt(child.getAttribute("code"));
                        if ((code >= 170 && code <= 174) || (code >= 102 && code <= 104)) {
                            mXmppConnectionService.fetchConferenceConfiguration(conversation);
                            break;
                        }
                    } catch (Exception e) {
                    //ignored
                    }
                } else if ("item".equals(child.getName())) {
                    MucOptions.User user = AbstractParser.parseItem(conversation, child);
                    Log.d(Config.LOGTAG, account.getJid() + ": changing affiliation for " + user.getRealJid() + " to " + user.getAffiliation() + " in " + conversation.getJid().toBareJid());
                    if (!user.realJidMatchesAccount()) {
                        conversation.getMucOptions().updateUser(user);
                        mXmppConnectionService.getAvatarService().clear(conversation);
                        mXmppConnectionService.updateMucRosterUi();
                        mXmppConnectionService.updateConversationUi();
                        if (!user.getAffiliation().ranks(MucOptions.Affiliation.MEMBER)) {
                            Jid jid = user.getRealJid();
                            List<Jid> cryptoTargets = conversation.getAcceptedCryptoTargets();
                            if (cryptoTargets.remove(user.getRealJid())) {
                                Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": removed " + jid + " from crypto targets of " + conversation.getName());
                                conversation.setAcceptedCryptoTargets(cryptoTargets);
                                mXmppConnectionService.updateConversation(conversation);
                            }
                        }
                    }
                }
            }
        }
    }
    Element received = packet.findChild("received", "urn:xmpp:chat-markers:0");
    if (received == null) {
        received = packet.findChild("received", "urn:xmpp:receipts");
    }
    if (received != null && !packet.fromAccount(account)) {
        mXmppConnectionService.markMessage(account, from.toBareJid(), received.getAttribute("id"), Message.STATUS_SEND_RECEIVED);
    }
    Element displayed = packet.findChild("displayed", "urn:xmpp:chat-markers:0");
    if (displayed != null) {
        if (packet.fromAccount(account)) {
            Conversation conversation = mXmppConnectionService.find(account, counterpart.toBareJid());
            if (conversation != null) {
                mXmppConnectionService.markRead(conversation);
            }
        } else {
            final Message displayedMessage = mXmppConnectionService.markMessage(account, from.toBareJid(), displayed.getAttribute("id"), Message.STATUS_SEND_DISPLAYED);
            Message message = displayedMessage == null ? null : displayedMessage.prev();
            while (message != null && message.getStatus() == Message.STATUS_SEND_RECEIVED && message.getTimeSent() < displayedMessage.getTimeSent()) {
                mXmppConnectionService.markMessage(message, Message.STATUS_SEND_DISPLAYED);
                message = message.prev();
            }
        }
    }
    Element event = original.findChild("event", "http://jabber.org/protocol/pubsub#event");
    if (event != null) {
        parseEvent(event, original.getFrom(), account);
    }
    String nick = packet.findChildContent("nick", "http://jabber.org/protocol/nick");
    if (nick != null) {
        Contact contact = account.getRoster().getContact(from);
        contact.setPresenceName(nick);
    }
}
Also used : Jid(eu.siacs.conversations.xmpp.jid.Jid) XmppAxolotlMessage(eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage) Message(eu.siacs.conversations.entities.Message) Element(eu.siacs.conversations.xml.Element) Conversation(eu.siacs.conversations.entities.Conversation) Contact(eu.siacs.conversations.entities.Contact) MessagePacket(eu.siacs.conversations.xmpp.stanzas.MessagePacket) MucOptions(eu.siacs.conversations.entities.MucOptions) MessageArchiveService(eu.siacs.conversations.services.MessageArchiveService) Bookmark(eu.siacs.conversations.entities.Bookmark) HttpConnectionManager(eu.siacs.conversations.http.HttpConnectionManager)

Example 4 with Bookmark

use of eu.siacs.conversations.entities.Bookmark in project Conversations by siacs.

the class ConferenceDetailsActivity method deleteBookmark.

protected void deleteBookmark() {
    Account account = mConversation.getAccount();
    Bookmark bookmark = mConversation.getBookmark();
    bookmark.unregisterConversation();
    account.getBookmarks().remove(bookmark);
    xmppConnectionService.pushBookmarks(account);
}
Also used : Account(eu.siacs.conversations.entities.Account) Bookmark(eu.siacs.conversations.entities.Bookmark)

Example 5 with Bookmark

use of eu.siacs.conversations.entities.Bookmark in project Conversations by siacs.

the class XmppConnectionService method fetchBookmarks.

public void fetchBookmarks(final Account account) {
    final IqPacket iqPacket = new IqPacket(IqPacket.TYPE.GET);
    final Element query = iqPacket.query("jabber:iq:private");
    query.addChild("storage", "storage:bookmarks");
    final OnIqPacketReceived callback = new OnIqPacketReceived() {

        @Override
        public void onIqPacketReceived(final Account account, final IqPacket packet) {
            if (packet.getType() == IqPacket.TYPE.RESULT) {
                final Element query = packet.query();
                final HashMap<Jid, Bookmark> bookmarks = new HashMap<>();
                final Element storage = query.findChild("storage", "storage:bookmarks");
                final boolean autojoin = respectAutojoin();
                if (storage != null) {
                    for (final Element item : storage.getChildren()) {
                        if (item.getName().equals("conference")) {
                            final Bookmark bookmark = Bookmark.parse(item, account);
                            Bookmark old = bookmarks.put(bookmark.getJid(), bookmark);
                            if (old != null && old.getBookmarkName() != null && bookmark.getBookmarkName() == null) {
                                bookmark.setBookmarkName(old.getBookmarkName());
                            }
                            Conversation conversation = find(bookmark);
                            if (conversation != null) {
                                conversation.setBookmark(bookmark);
                            } else if (bookmark.autojoin() && bookmark.getJid() != null && autojoin) {
                                conversation = findOrCreateConversation(account, bookmark.getJid(), true, true);
                                conversation.setBookmark(bookmark);
                            }
                        }
                    }
                }
                account.setBookmarks(new ArrayList<>(bookmarks.values()));
            } else {
                Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not fetch bookmarks");
            }
        }
    };
    sendIqPacket(account, iqPacket, callback);
}
Also used : Account(eu.siacs.conversations.entities.Account) OnIqPacketReceived(eu.siacs.conversations.xmpp.OnIqPacketReceived) Jid(eu.siacs.conversations.xmpp.jid.Jid) Bookmark(eu.siacs.conversations.entities.Bookmark) HashMap(java.util.HashMap) Element(eu.siacs.conversations.xml.Element) Conversation(eu.siacs.conversations.entities.Conversation) IqPacket(eu.siacs.conversations.xmpp.stanzas.IqPacket)

Aggregations

Bookmark (eu.siacs.conversations.entities.Bookmark)12 Account (eu.siacs.conversations.entities.Account)7 Jid (eu.siacs.conversations.xmpp.jid.Jid)4 Conversation (eu.siacs.conversations.entities.Conversation)3 Element (eu.siacs.conversations.xml.Element)3 SuppressLint (android.annotation.SuppressLint)2 AlertDialog (android.app.AlertDialog)2 MucOptions (eu.siacs.conversations.entities.MucOptions)2 IqPacket (eu.siacs.conversations.xmpp.stanzas.IqPacket)2 PendingIntent (android.app.PendingIntent)1 ActivityNotFoundException (android.content.ActivityNotFoundException)1 DialogInterface (android.content.DialogInterface)1 OnClickListener (android.content.DialogInterface.OnClickListener)1 Intent (android.content.Intent)1 SpannableString (android.text.SpannableString)1 View (android.view.View)1 AdapterView (android.widget.AdapterView)1 AutoCompleteTextView (android.widget.AutoCompleteTextView)1 CheckBox (android.widget.CheckBox)1 Checkable (android.widget.Checkable)1