0

내 잡지 앱의 경우 Firebase 서비스를 사용하고 있습니다.이 안드로이드 앱의 한 기능은 새 문서가 게시 될 때마다 하나의 기능으로 모든 장치에 새로운 알림이 전송됩니다 . FCMToken :Firebase Cloud 등록 된 모든 장치에 알림 전송을위한 메시징

이 같은 DB에있는 모든 장치 토큰을 저장하고있다 : 새로운 노드가 중포 기지 DB에서 "게시"키에 추가됩니다 그래서 때마다

는, FCM 기능이 실행됩니다 { 사용자 ID deviceToken } 및 메시지가 모든 장치에 전송됩니다

다음

는 FCM 기능을위한 자바 스크립트에 내 코드입니다 : 어떤 이유

'use strict' 
const functions = require('firebase-functions'); 
const admin = require('firebase-admin'); 
admin.initializeApp(functions.config().firebase); 
exports.sendNotification = functions.database.ref('/published/{msg_id}').onWrite(event => { 
    const snapshot = event.data; 
    // Only send a notification when a new message has been created. 
    if (snapshot.previous.val()) { 
    return; 
    } 
    const msg_id = event.params.msg_id; 

    const msg_val=admin.database().ref(`messages/${msg_id}`).once('value'); 
    return msg_val.then(msgResult =>{ 
    const msg_title=msgResult.val().title; 
    const user_id=msgResult.val().userId; 
    console.log('msg title is',msg_title); 
    console.log('We have a new article : ', msg_id); 
     const payload={ 

     data : { 
      title:"New Article", 
      body: msg_title, 
      msgid : msg_id, 
      userid : user_id 

     } 
    }; 


// const deviceToken = admin.database().ref('/FCMToken/{user_id}').once('value'); 
admin.database().ref('/FCMToken').on("value", function(dbsnapshot) 
{ 
    dbsnapshot.forEach(function(childSnapshot) { 
    //var childKey = childSnapshot.key; 
    const childData = childSnapshot.val(); 
    const deviceToken=console.log("device token" + childSnapshot.val()); 


    return admin.messaging().sendToDevice(childData,payload).then(response=>{ 
     console.log("This was notification feature") 
     console.log("response: ", response); 
    }) 
    .catch(function(error) 
    { 
     console.log("error sending message",error) 
    }); 
    }); 
    }); 

    }); 

}); 

알림입니다 단 하나의 장치 (FCM 노드의 첫 번째 토큰)로만 전송됩니다. 업데이트 : 코드를 업데이트하고 약속을 사용했지만 몇 가지 이유로 여전히 작동하지 않고 첫 번째 장치 토큰에 알림을 보냅니다.

'use strict' 
const functions = require('firebase-functions'); 
const admin = require('firebase-admin'); 
admin.initializeApp(functions.config().firebase); 
exports.sendNotification = functions.database.ref('/published/{msg_id}').onWrite(event => { 
    const snapshot = event.data; 
    // Only send a notification when a new message has been created. 
    if (snapshot.previous.val()) { 
    return; 
    } 
    const msg_id = event.params.msg_id; 

    const msg_val=admin.database().ref(`messages/${msg_id}`).once('value'); 
    return msg_val.then(msgResult =>{ 
    const msg_title=msgResult.val().title; 
    const user_id=msgResult.val().userId; 
    console.log('msg title is',msg_title); 
    console.log('We have a new article : ', msg_id); 
     const payload={ 

     data : { 
      title:"New Article", 
      body: msg_title, 
      msgid : msg_id, 
      userid : user_id 

     } 
    }; 

const promises=[]; 

// const deviceToken = admin.database().ref('/FCMToken/{user_id}').once('value'); 
admin.database().ref('/FCMToken').once('value').then(function(dbsnapshot) 
{ 

    dbsnapshot.forEach(function(childSnapshot) { 
    //var childKey = childSnapshot.key; 
    const childData = childSnapshot.val(); 
    const deviceToken=console.log("device token" + childSnapshot.val()); 


    const promise = admin.messaging().sendToDevice(childData,payload).then(response=>{ 
    promises.push(promise) 
     console.log("This was notification feature") 
     console.log("response: ", response); 
    }) 
    return Promise.all(promises) 
    .catch(function(error) 
    { 
     console.log("error sending message",error) 
    }); 
    }); 
    }); 

    }); 

}); 

응답 개체는이 출력을 제공한다 : 응답 {결과 : {오류 [개체]}] canonicalRegistrationTokenCount : 0 failureCount : 1 successCount : 0 multicastId : 6411440389982586000}

+0

모든 장치의 FCM 토큰을 사용하여 전송하면, 특정 주제에 가입 한 후 알림을 보내 대신. 더 효율적입니다. – kunwar97

답변

0

기능을 통해 약속이 올바르게 사용되지 않습니다. 두 가지가 잘못되었습니다.

첫째, 대신 on()once()을 사용하여 데이터베이스를 조회하고, 작품의 다음 항목으로 진행하기 위해 그것에서 반환 약속을 사용해야합니다 : 또한

admin.database().ref('/FCMToken').on("value") 
.then(result => /* continue your work here */) 

을, 당신은 반환 할 수 없습니다 forEach 루프 밖의 약속. 대신 함수의 마지막 단계 인 함수의 최상위 레벨에서 약속을 반환해야합니다. 이 약속은이 기능에서 의 작업이 완료 될 때 해결해야합니다. 귀하의 기능을 위해서는 모든 메시지가 전송 될 때이를 의미합니다. 배열의 모든 메시지에 대한 모든 약속을 수집 한 다음 모두 해결 될 때 해결되는 단일 약속을 반환해야합니다. 일반적인 형태는 다음과 같습니다.

const promises = [] 

dbsnapshot.forEach(function(childSnapshot) { 
    // remember each promise for each message sent 
    const promise = return admin.messaging().sendToDevice(...) 
    promises.push(promise) 
}) 

// return a single promise that resolves when everything is done 
return Promise.all(promises) 

약속 내용이 JavaScript로 작동하는지 확인하십시오. 약속을 올바르게 처리하지 않으면 효과적인 기능을 작성할 수 없습니다.

+0

도움을 주셔서 대단히 감사합니다. – user3792429

+0

안녕하세요! 제 기능을 업데이트했지만 문제가 동일하게 유지됩니다. – user3792429

0

그래서 값을 얻는 다른 방법을 알아 냈습니다. (tokensSnapshot.val()).

다음은 내 완전한 방법 :

'use strict' 
const functions = require('firebase-functions'); 
const admin = require('firebase-admin'); 
//Object.values = require('object.values'); 
admin.initializeApp(functions.config().firebase); 
exports.sendNotification = functions.database.ref('/published/{msg_id}').onWrite(event => { 
    const snapshot = event.data; 
    // Only send a notification when a new message has been created. 
    if (snapshot.previous.val()) { 
    return; 
    } 
    const msg_id = event.params.msg_id; 

    const msg_val=admin.database().ref(`messages/${msg_id}`).once('value'); 
    return msg_val.then(msgResult =>{ 
    const msg_title=msgResult.val().title; 
    const user_id=msgResult.val().userId; 
    console.log('msg title is',msg_title); 
    console.log('We have a new article : ', msg_id); 
     const payload={ 

     data : { 
      title:"New Article", 
      body: msg_title, 
      msgid : msg_id, 
      userid : user_id 

     } 
    }; 




const getDeviceTokensPromise = admin.database().ref('/FCMToken').once('value'); 
return Promise.all([getDeviceTokensPromise, msg_title]).then(results => { 


    const tokensSnapshot = results[0]; 
    const msgi = results[1]; 

    if (!tokensSnapshot.hasChildren()) { 
     return console.log('There are no notification tokens to send to.'); 
    } 
    console.log('There are', tokensSnapshot.numChildren(), 'tokens to send notifications to.'); 
    console.log("tokenslist",tokensSnapshot.val()); 
    const tokens= Object.keys(tokensSnapshot.val()).map(e => tokensSnapshot.val()[e]); 
    //var values = Object.keys(o).map(e => obj[e]) 


    return admin.messaging().sendToDevice(tokens, payload).then(response => { 
     // For each message check if there was an error. 
     const tokensToRemove = []; 
     response.results.forEach((result, index) => { 
     const error = result.error; 
     if (error) { 
      console.error('Failure sending notification to', tokens[index], error); 
      // Cleanup the tokens who are not registered anymore. 

     } 
     }); 
     return Promise.all(tokensToRemove); 
    }); 

}); 
}); 
});