首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >FCM android客户端随机停止接收数据消息。

FCM android客户端随机停止接收数据消息。
EN

Stack Overflow用户
提问于 2021-01-21 10:10:39
回答 2查看 326关注 0票数 2

我已经用Android客户端在服务器上实现了FCM,并且工作了一段时间。突然,客户端一次停止接收5到10分钟的通知,然后它将立即获得所有挂起的通知。日志显示服务器正在正确地发送消息。当消息队列被卡住时,甚至连Firebase控制台的测试消息都不能通过。

我在官方文档中找到的唯一相关的东西是关于消息的生命周期

如果设备未连接到FCM,则将消息存储到连接建立为止(再次遵守折叠密钥规则)。建立连接后,FCM将所有挂起的消息传递给设备。

但是我的网络运行良好,这个问题也出现在其他网络和客户端上。当我刚安装应用程序时,将生成一个新的令牌,并由我的服务器成功地接收。只是服务器对客户端的消息没有经过。

如何确定连接是否已建立并修复?或者还有什么原因呢?

这是我的客户端代码

AndroidManifest.xml

代码语言:javascript
运行
复制
        <application
        android:name=".App"
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:largeHeap="true"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:usesCleartextTraffic="true"
        tools:ignore="GoogleAppIndexingWarning">
        <service
            android:name=".service.NotificationService"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>

NotificationService.java

代码语言:javascript
运行
复制
public class NotificationService extends FirebaseMessagingService {

    private static final String TAG = "NotificationService";
    private static String token;

    public NotificationService() {
        token = PreferenceManager
                .getDefaultSharedPreferences(App.getContext())
                .getString("firebase-token", null);
    }

    @Override
    public void onNewToken(@NonNull String s) {
        super.onNewToken(s);
        FirebaseInstanceId.getInstance().getInstanceId()
                .addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
                    @Override
                    public void onComplete(@NonNull Task<InstanceIdResult> task) {
                        if (!task.isSuccessful()) {
                            Log.w(TAG, "getInstanceId failed", task.getException());
                            return;
                        }
                        token = task.getResult().getToken();
                        Log.d(TAG, "onComplete: token = " + token);
                        PreferenceManager
                                .getDefaultSharedPreferences(App.getContext())
                                .edit()
                                .putString("firebase-token", token)
                                .apply();
                    }
                });
    }

    @Override
    public void onMessageReceived(final RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        Log.d(TAG, "Received message of size " + remoteMessage.getData().size());
        if (remoteMessage.getData().size() > 0) {
            Log.d(TAG, "Message data payload: " + remoteMessage.getData());

            Handler h = new Handler(Looper.getMainLooper());
            h.post(new Runnable() {
                public void run() {
                    int left = -1, right = -1;
                    if (remoteMessage.getData().get("left") != null) {
                        left = Integer.parseInt(Objects.requireNonNull(remoteMessage.getData()
                                .get("left")));
                    }
                    if (remoteMessage.getData().get("right") != null) {
                        right = Integer.parseInt(Objects.requireNonNull(remoteMessage.getData()
                                .get("right")));
                    }


                    if (remoteMessage.getData().get("REFRESH") != null) {
                        Util.sendTitleBroadcast(getApplicationContext(),
                                left, right,
                                Util.REFRESH_TITLE);
                    } else {
                        Util.sendTitleBroadcast(getApplicationContext(),
                                left, right,
                                Util.TITLE_DATA_RECEIVED);
                    }
                }
            });
        }
    }

    public static String getToken() {
        if (token == null) {
            token = PreferenceManager
                    .getDefaultSharedPreferences(App.getContext())
                    .getString("firebase-token", null);
        }
        return token;
    }
}

服务器端FirebaseMessagingService.java代码

代码语言:javascript
运行
复制
public class FirebaseMessagingService {

    private static final Logger logger = Logger
            .getLogger(FirebaseMessagingService.class);
    private static FirebaseMessagingService instance;

    /**
     * Path to resource file that contains the credentials for Admin SDK.
     */
    private final String keyPath = "firebase-adminsdk.json";

    /**
     * Maps a token list to each topic Object.
     */
    private static Map<Object, List<String>> topicTokenMap;

    public synchronized static FirebaseMessagingService getInstance() {
        if (instance == null) {
            instance = new FirebaseMessagingService();
        }
        return instance;
    }

    private FirebaseMessagingService() {
        init();
    }

    /**
     * Initializes the Firebase service account using the credentials from the
     * json file found at keyPath.
     */
    private void init() {
        try {
            InputStream serviceAccount
                    = getClass().getClassLoader().getResourceAsStream(keyPath);
            if (serviceAccount != null) {
                FirebaseOptions options = new FirebaseOptions.Builder()
                        .setCredentials(GoogleCredentials
                                .fromStream(serviceAccount))
                        .setDatabaseUrl(databaseUrl)
                        .build();

                FirebaseApp.initializeApp(options);
                logger.debug("FirebaseMessagingService: init successful");
            } else {
                logger.debug("FirebaseMessagingService: Input stream null from"
                        + " path: " + keyPath);
            }
        } catch (IOException ex) {
            logger.debug("FirebaseMessagingService: Failed to get credentials "
                    + "from inputStream." + ex.getMessage());
        }
    }

    /**
     * Sends the messages given as parameters to the list of tokens mapped to
     * the given topic Object.
     *
     * @param topic
     * @param messages
     */
    public void sendMessage(Object topic,
            Map<String, String> messages) {
        logger.debug("FirebaseMessagingService: sending Message "
                + messages.toString());
        try {
            if (topicTokenMap != null) {
                List<String> tokenList = topicTokenMap.get(topic);
                if (tokenList != null) {
                    tokenList.removeAll(Collections.singleton(null));
                    MulticastMessage message = MulticastMessage.builder()
                            .putAllData(messages)
                            .addAllTokens(tokenList)
                            .build();
                    FirebaseMessaging.getInstance().sendMulticast(message);
                    logger.debug("FirebaseMessagingService: message sent successfully");
                }
            }
        } catch (FirebaseMessagingException ex) {
            logger.debug(ex.getMessage());
        }
    }

    /**
     * Registers the token given as a parameter to the topic Object.
     *
     * @param topic
     * @param token
     */
    public void registerTokenToTopic(Object topic, String token) {
        if (topicTokenMap == null) {
            topicTokenMap = new HashMap<Object, List<String>>();
        }
        List<String> tokens = topicTokenMap.get(topic);
        if (tokens == null) {
            tokens = new ArrayList<String>();
        }
        if (!tokens.contains(token)) {
            tokens.add(token);
        }
        topicTokenMap.put(topic, tokens);
    }

    /**
     * Unregisters all instances of the token given as a parameter from the topic
     * given.
     *
     * @param topic
     * @param token
     */
    public void unregisterTokenFromTopic(Object topic, String token) {
        if (topicTokenMap != null) {
            List<String> tokens = topicTokenMap.get(topic);
            if (tokens != null) {
                tokens.removeAll(Collections.singleton(token));
            }
        }
    }

    /**
     * Looks for a topic that has a field with the name equal to topicFieldName
     * and the value equal to topicFieldValue and sends a notification to the
     * tokens subscribed to that topic, telling them to ask for an update.
     *
     * @param topicFieldName
     * @param topicFieldValue
     */
    public void notifyChangeForTopicField(String topicFieldName,
            Object topicFieldValue) {
        logger.debug("FirebaseMessagingService: notifyChangeForTopicField: "
                + "topicFieldValue = " + topicFieldValue.toString());

        Map<String, String> messageMap = new HashMap<String, String>();
        messageMap.put("REFRESH", "true");

        if (topicTokenMap != null
                && topicTokenMap.entrySet() != null
                && topicTokenMap.entrySet().size() > 0) {
            Iterator it = topicTokenMap.entrySet().iterator();
            while (it.hasNext()) {
                try {
                    Map.Entry pair = (Map.Entry) it.next();
                    Object topic = pair.getKey();
                    logger.debug("FirebaseMessagingService: "
                            + "notifyChangeForTopicField topic = " + topic.toString());
                    Field field = topic.getClass().getDeclaredField(topicFieldName);
                    logger.debug("FirebaseMessagingService: "
                            + "notifyChangeForTopicField field = " + field.toString());
                    field.setAccessible(true);
                    logger.debug("FirebaseMessagingService: "
                            + "notifyChangeForTopicField field contains topic: "
                            + (field.get(topic) != null ? "true" : "false"));
                    if (field.get(topic) != null
                            && field.get(topic).equals(topicFieldValue)) {
                        sendMessage(topic, messageMap);
                        break;
                    }
                    it.remove();
                } catch (NoSuchFieldException ex) {
                    java.util.logging.Logger.getLogger(FirebaseMessagingService.class.getName()).log(Level.SEVERE, null, ex);
                } catch (SecurityException ex) {
                    java.util.logging.Logger.getLogger(FirebaseMessagingService.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IllegalArgumentException ex) {
                    java.util.logging.Logger.getLogger(FirebaseMessagingService.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IllegalAccessException ex) {
                    java.util.logging.Logger.getLogger(FirebaseMessagingService.class.getName()).log(Level.SEVERE, null, ex);
                }
            }

        }
    }
}

编辑:经过几次测试后,我发现当一个客户端停止工作时,其他客户端接收消息的效果很好,

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-11-15 13:12:24

我在这里找到了答案:https://stackoverflow.com/a/23902751/10702209,发生的事情是,我在5分钟后随机地得到路由器超时。我修正了这个问题,在4分钟后手动发送心跳到FCM,而不是默认的15分钟。

代码语言:javascript
运行
复制
context.sendBroadcast(new Intent("com.google.android.intent.action.GTALK_HEARTBEAT"));
context.sendBroadcast(new Intent("com.google.android.intent.action.MCS_HEARTBEAT"));

几个月前,我已经实现了这个修复程序,此后就再也没有出现过这个问题了。

票数 0
EN

Stack Overflow用户

发布于 2021-01-21 10:43:59

你的onMessageReceived()在我看来有点过分了。我认为您不必创建自己的Handler来处理数据。只需继续使用Firebase示例:FirebaseExample

代码语言:javascript
运行
复制
override fun onMessageReceived(remoteMessage: RemoteMessage) {
    if (remoteMessage.data.isNotEmpty()) {
        Log.d(TAG, "Message data payload: ${remoteMessage.data}")
        if (/* Check if data needs to be processed by long running job */ true) {
          // For long-running tasks (10 seconds or more) use WorkManager.
          scheduleJob()
        } else {
            // Handle message within 10 seconds
            handleNow()
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65825170

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档