使用Firebase聊天应用:收到新消息时获取通知 - Android

Vai*_*wal 18 notifications android firebase firebase-realtime-database

我正在使用Firebase实时数据库开发聊天应用程序.我能够正确地发送和接收消息.现在,我想在收到新消息时实现通知.为此,我创建了一个Service使用ChildEventListener和创建通知来监听数据库更改的人.问题是我在onChildAdded方法中创建通知,并且此方法为数据库中的现有节点和新节点触发.这导致每当用户从应用程序来回导航时,为同一消息多次创建通知.

以下是我如何实现它:

chatMsgsRef.orderByChild(FirebaseDBKeys.LOCATION_LAST_UPDATED).addChildEventListener(new ChildEventListener() {

            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {

                ChatMessage message = dataSnapshot.getValue(ChatMessage.class);

                if (!message.getSenderId().equals(currentUserId)) {

                    mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

                    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(NotificationsService.this)
                            .setSmallIcon(R.drawable.message)
                            .setContentTitle("New Message from " + message.getReceipientName())
                            .setContentText(message.getMessage())
                            .setOnlyAlertOnce(true)
                            .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
                    mBuilder.setAutoCancel(true);
                    mBuilder.setLocalOnly(false);


                    mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());

                }
            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {

            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {

            }

            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });
Run Code Online (Sandbox Code Playgroud)

如何以其在whatsapp等其他聊天应用程序中的工作方式实现通知?

Shm*_*uel 13

执行此操作的正确方法是在发送新聊天时向客户端发送推送数据消息.

这篇博客文章解释了如何实现这一目标.基本上,您需要设置一个服务器来监听聊天firebase ref并在更新时发送推送通知.通过这种方式,您的客户可以在应用程序中或在应用程序之外,仍然可以获得推动.

如果您使用服务,则存在许多潜在问题.

首先,你必须让手机保持清醒状态.这会耗尽电池.

其次,Android可以随时终止您的后台服务,因此您的应用可能会突然停止工作.

第三,使用Doze模式Android将阻止网络活动并阻止您的应用在后台运行.


Cha*_*ltz 6

我想到了一个更好的答案:

在这种情况下,您想要的不一定是了解新消息。知道未读消息。

在ChatMessage对象中设置一个“读取”标志(或者相反,在某个位置提供一个值,该值给出最新读取消息的时间戳或ID)。

现在,每当触发onChildAdded时,请检查是否已读取== false。如果是这样,请显示一条有关该邮件未读的通知(请记住要更新该通知(如果存在),因此将仅显示一个通知,并且将显示最新的通知-哦,还请记住在孩子收到通知后将其删除改为读取。)

如果用户在多个设备上使用您的应用程序,它将正确检查读取状态。如果他在手机上阅读了最新消息,然后转到平板电脑,它将不会显示该新消息通知。

如果需要,您甚至可以使用此功能来指示收件人阅读了您给他们的消息。

你怎么知道什么时候读?也许只是在将其添加到屏幕上时。也许您确定它在视图中(不在屏幕上滚动)并且可见几秒钟。


Cha*_*ltz 3

您尝试过 addValueEventListener 吗?

https://www.firebase.com/docs/android/guide/retrieve-data.html#section-start

// Get a reference to our posts
Firebase ref = new Firebase("https://docs-examples.firebaseio.com/web/saving-data/fireblog/posts");
// Attach an listener to read the data at our posts reference
ref.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot snapshot) {
        System.out.println(snapshot.getValue());
    }
    @Override
    public void onCancelled(FirebaseError firebaseError) {
        System.out.println("The read failed: " + firebaseError.getMessage());
    }
});
Run Code Online (Sandbox Code Playgroud)

“只要将新数据添加到我们的 Firebase 引用中,就会调用此方法,并且我们不需要编写任何额外的代码来实现这一点。”

编辑:“它会使用初始数据触发一次,每次数据更改时都会触发一次。” 我还没有尝试过,但我的想法是在该方法第一次触发时设置一个标志。然后,每当设置该方法和该标志(换句话说,第二次、第三次、第四次等)时,都会从快照中获取最新的对象。