Android - 如何检查您的联系人是否已在您的应用程序上注册?

Android - How to check if your contacts has registered on your app?

我正在尝试创建一个 ChatApp。所以,我想知道我的联系人列表中是否有人在我的应用程序中注册过。

如上图,有3个按键。 El7SIqgHmWTsZCl6gVaXidKGsok1 这是我和其他 2 个是我的朋友,我也有他们的 phoneNumber。所以,我想在我的应用程序中将这 2 个显示为我的朋友。但是它没有显示任何用户。

这是我试过的代码。

public class UsersFragment extends Fragment {

    RecyclerView recyclerView;
    ContactsAdapter adapter;
    List<Users> contactsList, userList;
    DatabaseReference reference;
    String userId;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_users, container, false);

        recyclerView = view.findViewById(R.id.userRecyclerView);
        recyclerView.setHasFixedSize(false);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));

        reference = FirebaseDatabase.getInstance().getReference().child("Users");
        contactsList = new ArrayList<>();
        userList = new ArrayList<>();

        FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
        userId = user.getUid();

        return view;
    }

    private void getContactList() {
        Cursor cursor = getActivity().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                null, null, null,
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
        ;
        while (cursor.moveToNext()) {
            String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
            String phone = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

            Users contacts = new Users(name, phone, "", "");
            contactsList.add(contacts);
            if (contactsList.contains(contacts)) {
                cursor.moveToNext();
            }
            getActualUsers(contacts);
        }

    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        getContactList();
    }

    private void getActualUsers(final Users contacts) {
        Query query = reference.orderByChild("number").equalTo(contacts.getPhoneNumber());
        query.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
                    Users users = dataSnapshot.getValue(Users.class);
                    userList.add(users);
                }
                Log.d("contact", String.valueOf(userList.size()));
                adapter = new ContactsAdapter(getContext(), userList);
                recyclerView.setAdapter(adapter);
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {

            }
        });
    }

}

我的模型Class

public class 用户 {

String username, phoneNumber, userId, profilephotoURL;

public  Users(){}
public Users(String username, String phoneNumber, String userId, String profilephotoURL) {
    this.username = username;
    this.phoneNumber = phoneNumber;
    this.userId = userId;
    this.profilephotoURL = profilephotoURL;
}

public String getUsername() {
    return username;
}

public String getPhoneNumber() {
    return phoneNumber;
}

public String getUserId() {
    return userId;
}

public String getProfilephotoURL() {
    return profilephotoURL;
}

}

我的适配器Class

public class UsersAdapter extends RecyclerView.Adapter<UsersAdapter.ViewHolder> {
    Context mContext;
    List<Users> mList;

    public UsersAdapter(Context mContext, List<Users> mList) {
        this.mContext = mContext;
        this.mList = mList;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.display_contacts, null);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
        final Users users = mList.get(position);
        holder.name.setText(users.getUsername());
        holder.number.setText(users.getPhoneNumber());
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(mContext, ChatActivity.class);
                intent.putExtra("name", users.getUsername());
                intent.putExtra("userid", users.getPhoneNumber());
                intent.putExtra("id", users.getUserId());
                mContext.startActivity(intent);
            }
        });
    }

    @Override
    public int getItemCount() {
        return mList.size();
    }

    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView name, number;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            name = itemView.findViewById(R.id.contactName);
            number = itemView.findViewById(R.id.contactNumber);
        }
    }
}

有任何帮助或建议吗?

不确定这是否是您问题的解决方案,但可能是,而且评论太长无法解释:

让我以压缩的方式编写您的代码并附上一些注释:

// start a loop over every local contacts on the phone
while (cursor.moveToNext()) {

  // create a local variable for this contact (the class name should be Contact. Singular.)
  Contacts contacts = new Contacts(name, phone, "");
  
  // get a contact with the same phone number from firebase.
  // the sorting is executed for every iteration of the loop -> bad performance. 
  // -> I recommend to order the reference outside of the loop.
  Query query = reference.orderByChild("number").equalTo(contacts.getNumber());

  // now you add the ValueEventListener

  // if onDataChanged is called, you iterate over all children of the new snapshot

  // you create again a local Contacts object

  // then there is this strange comparison of name and phone...don't know what that accomplishes, but ok

  // now comes the part that might cause the wrong behaviour:
  userList.add(contacts1);
  adapter = new ContactsAdapter(getContext(), userList);
  recyclerView.setAdapter(adapter);

}

因此最后 3 行似乎容易出错:

  userList.add(contacts1);
  adapter = new ContactsAdapter(getContext(), userList);
  recyclerView.setAdapter(adapter);

总的来说,它们并没有太大问题,但请记住,您基本上仍处于 getContactList() 中开始的第一个循环中 这意味着您为循环中的每个联系人创建一个全新的适配器,并将这个新适配器分配给 recyclerView。

假设您的 phone 上有 100 个联系人。这导致创建 100 个适配器并设置到 recyclerView。

我建议对您的代码进行 2 处重大更改:

  1. 覆盖 onViewCreated 并将 getContactList(); 放在那里。方法 onCreateView 应该只关注基本视图 inflation 并且可以初始化简单的视图变量。 用数据填充 视图应该在 onViewCreated 之后完成。

  2. 明确区分“为View准备数据”和“将准备好的数据放入View”。换句话说:首先创建你的最终 userList 并且仅当此列表完成后,创建适配器并将其设置为 recyclerView。

如果您想进一步改进,请查看 ViewModels 的概念。简而言之:ViewModel 正在准备其 View 想要显示的所有数据(包括过滤、转换等)。 View(在本例中是您的 Fragment)尽可能“愚蠢”-> 它一直等到 ViewModel 将数据传递给它,并且只做显示该数据。

LiveData 对于这种方法非常有用,它将使您的代码更加清晰,更易于理解和维护:)

祝你项目顺利!

我不会给你任何代码,而是给你一个关于如何实现你的目标的架构提示。根据您问题中提供的详细信息,我假设您的客户是通过 OTP 注册的。当他们登录时,您可以根据他们的 phone 号码存储他们的 UID。看看 how to save user details.

这是您的 firebase 存储注册用户的样子

registeredUsers : {
    "23492hsdfs08fv9x9" : "0X20-342234...",
    "34928304283438d8f" : "0X02-123123..."
}

现在,当您访问当前用户联系人列表时,循环遍历 firebase 中的 usrs 列表,以查看联系人列表中的哪些 phone 个号码也在 firebase 中。

您可以只使用 phone 号码列表而不添加 Firebase UID,但我建议您像上面那样做,以防您需要将联系电话映射到它的 UID,然后您可以从中获取该用户的详细信息UID也是。

希望我已经给了你如何相处的提示。

所以,我能够确定问题所在,现在我有了解决方案。所以,我发布它以防有人需要它。

这是用户片段的全部更改代码

public class UsersFragment extends Fragment {

    RecyclerView recyclerView;
    UsersAdapter adapter;

    List<String> contactsList;
    DatabaseReference reference;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_users, container, false);

        recyclerView = view.findViewById(R.id.userRecyclerView);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        recyclerView.setAdapter(adapter);

        contactsList = new ArrayList<>();

        return view;
    }


    private void getContactList() {
        Cursor cursor = getActivity().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                null, null, null,
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
        while (cursor.moveToNext()) {
            String phone = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
            if (contactsList.contains(phone)) {
                cursor.moveToNext();
            } else {
                contactsList.add(phone);

            }
        }

        getActualUser();
        Log.d("contact: ", String.valueOf(contactsList.size()));

    }

    private void getActualUser() {
        reference = FirebaseDatabase.getInstance().getReference().child("Users");
        reference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                List<Users> actualuserList = new ArrayList<>();
                actualuserList.clear();
                if (snapshot.exists()) {
                    for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
                        Users user = dataSnapshot.getValue(Users.class);
                        for (String number : contactsList){
                            if (user.getPhoneNumber().equals(number)){
                                actualuserList.add(user);
                            }
                        }
                    }
                    Log.d("actual: ", String.valueOf(actualuserList.size()));
                    adapter = new UsersAdapter(getContext(), actualuserList);
                    adapter.notifyDataSetChanged();
                    recyclerView.setAdapter(adapter);

                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {

            }
        });

    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        getContactList();

    }
}