获取聊天应用程序中的“上次看到" [英] Get Last Seen in chats application

查看:45
本文介绍了获取聊天应用程序中的“上次看到"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用firebase实时数据库和firebase身份验证方法创建了此聊天应用程序,但我真的很困惑,我不知道如何在聊天应用程序中最后看到用户.

I have created this chat application with firebase realtime database and firebase authentication methods but i am really confused and I don't exactly know how to get the last seen of user in a chat application.

以下是我在onCreate方法中尝试的代码.

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat_avtivity);
        mauth = FirebaseAuth.getInstance();
        currentUser = mauth.getCurrentUser();
        String onlineID = mauth.getCurrentUser().getUid();
        UserRefernce = FirebaseDatabase.getInstance().getReference().child("Users").child(onlineID);
        toolbar = findViewById(R.id.toolbar5);
        setSupportActionBar(toolbar);
        ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setDisplayShowCustomEnabled(true);
        LayoutInflater layoutInflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View actionbar = layoutInflater.inflate(R.layout.chats_custom, null);
        actionBar.setCustomView(actionbar);
        loadingbar = new ProgressDialog(this);
        mauth = FirebaseAuth.getInstance();
        senderID = mauth.getCurrentUser().getUid();
        sendbut = findViewById(R.id.sendmessage);
        mess = findViewById(R.id.editText2);
        rootRef = FirebaseDatabase.getInstance().getReference();
        messagereceveirid = getIntent().getExtras().get("user_id").toString();
        messagereceveirname = getIntent().getExtras().get("userrname").toString();
        messageImagesStorgeRef = FirebaseStorage.getInstance().getReference().child("Messages_Pictures");
        namuser = findViewById(R.id.textView3);
        lastseen = findViewById(R.id.timestamp);
        circleImageView = findViewById(R.id.imagechatsCustom);
        messageAdaptet = new MessageAdaptet(messageslists);
        usermessgerlis = findViewById(R.id.messages);
        linearLayoutManager = new LinearLayoutManager(this);
        usermessgerlis.setHasFixedSize(true);
        usermessgerlis.setLayoutManager(linearLayoutManager);
        usermessgerlis.setAdapter(messageAdaptet);
        fetchmessage();
        namuser.setText(messagereceveirname);
        rootRef.child("Users").child(messagereceveirid).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                final String online = dataSnapshot.child("online").getValue().toString();
                final String img = dataSnapshot.child("User_image").getValue().toString();
                Picasso.get().load(img).networkPolicy(NetworkPolicy.OFFLINE).into(circleImageView, new Callback() {
                    @Override
                    public void onSuccess() {
                    }

                    @Override
                    public void onError(Exception e) {
                        Picasso.get().load(img).into(circleImageView);
                    }
                });
                if (online.equals("true")) {
                    lastseen.setText("online");
                } else {
                    long time = Long.parseLong(online);
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
            }
        });
        sendbut.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendmessage();
            }
        });
    }

任何想法或其他方式将不胜感激.

Any ideas or alternative ways would be appreciated.

推荐答案

您所要求的最后看到的功能也称为presence system.好消息是,您可以在Firebase Real-time数据库中找到名为onDisconnect()的方法,可以帮助您实现这一目标.当将处理程序附加到onDisconnect()方法时,当服务器检测到客户端已断开连接时,指定的写操作将在服务器上执行.

The last seen feature that you are asking for is also known as a presence system. The good news is that you can find in the Firebase Real-time database a method named onDisconnect() that can help you achieve this. When you attach a handler to the onDisconnect() method, the write operation you specify will be executed on the server when that server detects that the client has disconnected.

在这里,您可以找到官方文档有关如何管理状态系统的信息.

Here you can find the official documentation for how to manage the presence system.

这实际上就是代码中的样子:

This is actually how it looks like in code:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference("disconnectmessage");
// Write a string when this client loses connection
rootRef.onDisconnect().setValue("Disconnected!");

这是使用onDisconnect方法在断开连接时写入数据的简单示例.

This is a straightforward example of writing data upon disconnection by using the onDisconnect method.

要为Firebase解决整个seen feature,应为每个用户添加两个新属性.第一个为isOnline,类型为布尔值,另一个为timestamp,其为map.如果要显示用户在线/离线,则很简单:

To solve the entire seen feature for Firebase, you should add to each user two new properties. The first one would be isOnline and is of type boolean and the other one is a timestamp which is map. If you want to display if a user is online/offline, it is as simple as:

String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference isOnlineRef = rootRef.child("users").child(uid).child("isOnline");
onlineRef.setValue(true);
onlineRef.onDisconnect().setValue(false);

对于第二个属性,请从此

For the second property, please see my answer from this post, where I have exaplained how you can save and retrive the timestamp from a Firebase Real-time database. To display the time from the last seen, just make a difference between the current timestamp and the timestamp from your database.

请注意,这将在简单的情况下起作用,但开始出现问题,例如当连接在用户设备上快速切换时.在这种情况下,服务器检测到客户端消失的时间可能比客户端重新连接要花费更多的时间(因为这可能取决于套接字超时),从而导致无效的false.

Note that this will work in simple cases, but will start to have problems, for istance when the connection toggles rapidly on user's device. In that case it may take the server more time to detect that the client disappears (since this may depends on the socket timing out) than it takes the client to reconnect, resulting in an invalid false.

要处理此类情况,请查看

To handle these kind of situations, please take a look at the sample presence system in the official documentation, which has more elaborate handling of edge cases.

还要注意的一件事是,服务器可以通过两种方式检测客户端的断开连接:

One more thing to note is that the server can detect the disconnecting of a client in two ways:

  1. 当完全断开连接(应用程序完全关闭,它调用goOffline())时,客户端向服务器发送一条消息,然后服务器可以立即执行onDisconnect()处理程序.

  1. When it's a clean disconnect (the app closes cleanly, it calls goOffline()), the client sends a message to the server, which can then immediately execute the onDisconnect() handlers.

当它是所谓的dirty disconnect(您驶入隧道并丢失信号,应用程序崩溃)时,服务器仅会在套接字绑定后检测到客户端已消失,这可能需要花费一些时间分钟.这是预期的行为,到目前为止,我还没有更好的选择.

When it's a so-called dirty disconnect (you drive into a tunnel and lose signal, the app crashes), the server only detects that the client is gone once the socket ties out, which can take a few minutes. This is the expected behavior, and there is no better alternative that I've learned so far.

这篇关于获取聊天应用程序中的“上次看到"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆