Firebase onMessageReceived ไม่ถูกเรียกเมื่อแอปอยู่ในพื้นหลัง


233

ฉันทำงานกับ Firebase และทดสอบการส่งการแจ้งเตือนไปยังแอปของฉันจากเซิร์ฟเวอร์ของฉันในขณะที่แอปอยู่ในพื้นหลัง การแจ้งเตือนถูกส่งสำเร็จมันยังปรากฏบนศูนย์การแจ้งเตือนของอุปกรณ์ แต่เมื่อการแจ้งเตือนปรากฏขึ้นหรือแม้ว่าฉันคลิกที่มันเมธอด onMessageReceived ภายใน FCMessagingService ของฉันจะไม่ถูกเรียกใช้

เมื่อฉันทดสอบสิ่งนี้ในขณะที่แอปของฉันอยู่เบื้องหน้าเมธอด onMessageReceived ถูกเรียกใช้และทุกอย่างทำงานได้ดี ปัญหาเกิดขึ้นเมื่อแอปทำงานในพื้นหลัง

นี่เป็นพฤติกรรมที่ตั้งใจหรือมีวิธีที่ฉันสามารถแก้ไขได้หรือไม่

นี่คือ FBMessagingService ของฉัน:

import android.util.Log;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

public class FBMessagingService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.i("PVL", "MESSAGE RECEIVED!!");
        if (remoteMessage.getNotification().getBody() != null) {
            Log.i("PVL", "RECEIVED MESSAGE: " + remoteMessage.getNotification().getBody());
        } else {
            Log.i("PVL", "RECEIVED MESSAGE: " + remoteMessage.getData().get("message"));
        }
    }
}

นอกจากเนื้อความ json แล้วรหัสonTokenRefreshของคุณอยู่ที่ไหน คุณติดตั้ง Androidเสร็จแล้วหรือยัง?
Kato

4
คุณหมายถึงอะไร json เนื้อหาของการแจ้งเตือน? นอกจากนี้รหัส onTokenRefresh ของฉันยังอยู่ในบริการ FirebaseInstanceID ของฉัน
Cyogenos

คุณสามารถโพสต์ตัวอย่างน้ำหนักบรรทุกที่คุณกำลังส่งได้หรือไม่?
อัล


คุณสามารถตรวจสอบกระทู้นี้stackoverflow.com/questions/39046270/…
Md. Sajedul Karim

คำตอบ:


144

สิ่งนี้ทำงานได้ตามที่คาดไว้ข้อความแจ้งเตือนจะถูกส่งไปยังการเรียกกลับของคุณเมื่อรับข้อความเท่านั้นเมื่อแอปของคุณอยู่เบื้องหน้า หากแอปของคุณอยู่ในพื้นหลังหรือปิดข้อความแจ้งเตือนจะปรากฏในศูนย์การแจ้งเตือนและข้อมูลใด ๆจากข้อความนั้นจะถูกส่งไปยังเจตนาที่เปิดตัวซึ่งเป็นผลมาจากการที่ผู้ใช้แตะที่การแจ้งเตือน

คุณสามารถระบุ click_action เพื่อระบุเจตนาที่ควรเปิดใช้เมื่อผู้ใช้แตะที่การแจ้งเตือน กิจกรรมหลักจะใช้หากไม่มีการระบุ click_action

เมื่อมีการเปิดใช้งานเจตนาคุณสามารถใช้

getIntent().getExtras();

เพื่อดึงข้อมูลชุดที่จะรวมข้อมูลใด ๆ ที่ส่งไปพร้อมกับข้อความแจ้งเตือน

สำหรับข้อมูลเพิ่มเติมเกี่ยวข้อความแจ้งเตือนดูเอกสาร


6
มีวิธีการตั้งค่าclick_actionเมื่อฉันใช้คอนโซลการแจ้งเตือนของ Firebase หรือไม่?
Nii Laryea

6
ตกลง แต่จะทำอย่างไรถ้าแอปถูกฆ่า (ไม่มีเบื้องหน้าหรือพื้นหลัง)
michalu

3
แต่วิธีการปิดการแจ้งเตือนผู้ใช้ยกเลิก? เพราะถ้าผู้ใช้ทิ้งไปนั่นหมายความว่าข้อมูลทั้งหมดจะถูกข้าม ... ใช่ไหม
Aleksey Timoshchenko

4
แก้ไข! ดังนั้นเมื่อส่งข้อความแจ้งเตือนไปยัง Android ข้อมูลประกอบควรเป็นข้อมูลที่ช่วยยกระดับประสบการณ์การแจ้งเตือน ไม่ควรเป็นข้อมูลสำคัญของแอพใช้ข้อความข้อมูลสำหรับข้อมูลที่แอปพลิเคชันต้องการแม้ว่าผู้ใช้จะยกเลิกการแจ้งเตือน
Arthur Thompson

3
สิ่งนี้ไม่ถูกต้องทั้งหมด หากข้อความมีข้อมูลเพียงอย่างเดียวและไม่ใช่ข้อมูลแจ้งเตือนข้อความจะถูกส่งไปยัง onMessageReceive เสมอหากแอปอยู่ในเบื้องหน้าหรือไม่
JacksOnF1

125

ลบnotificationฟิลด์ออกจากคำขอเซิร์ฟเวอร์ของคุณโดยสมบูรณ์ ส่งเท่านั้นdataและจัดการมันในonMessageReceived()อย่างอื่นของคุณonMessageReceived()จะไม่ถูกเรียกเมื่อแอปอยู่ในพื้นหลังหรือถูกฆ่า

อย่าลืมที่จะรวม"priority": "high"เขตข้อมูลในคำขอการแจ้งเตือนของคุณ ตามเอกสารประกอบ: ข้อความข้อมูลจะถูกส่งตามลำดับความสำคัญปกติดังนั้นข้อความเหล่านั้นจะไม่มาถึงในทันที มันอาจเป็นปัญหา

นี่คือสิ่งที่ฉันกำลังส่งจากเซิร์ฟเวอร์

{
  "data":{
    "id": 1,
    "missedRequests": 5
    "addAnyDataHere": 123
  },
  "to": "fhiT7evmZk8:APA91bFJq7Tkly4BtLRXdYvqHno2vHCRkzpJT8QZy0TlIGs......",
  "priority": "high"
}

ดังนั้นคุณสามารถรับข้อมูลของคุณในรูปonMessageReceived(RemoteMessage message)แบบนี้ .... สมมุติว่าฉันต้องได้รับ ID

Object obj = message.getData().get("id");
        if (obj != null) {
            int id = Integer.valueOf(obj.toString());
        }

9
ฉันพบว่าถ้าฉันส่งข้อความข้อมูลเท่านั้นแอปที่ถูกลบจากตัวจัดการงานจะไม่สามารถรับการแจ้งเตือนนี่เป็นพฤติกรรมที่ตั้งใจหรือไม่
Prabhjot Singh

2
นี่เป็นทางออกสำหรับฉันที่จะรับข้อความในพื้นหลัง!
Ray Hulha

5
ใน Oreo เมื่อแอพถูกฆ่า onMessageReceived จะไม่ถูกเรียก ฉันเพิ่งมีน้ำหนักบรรทุกพร้อมข้อมูลเท่านั้น คุณมีอัพเดตอะไรบ้าง?
Samir Mangroliya

2
ทำงานเหมือนจับใจ!
ssk

3
รักคุณมากสำหรับคำตอบนี้: p
Ahmad Arslan

63

วิธีนี้ handleIntent () ได้รับการคิดค่าเสื่อมราคาดังนั้นการจัดการการแจ้งเตือนสามารถทำได้ดังนี้:

  1. สถานะแถวหน้า: การคลิกที่การแจ้งเตือนจะไปที่กิจกรรมของ Intent ที่ค้างอยู่ซึ่งคุณกำลังให้บริการในขณะที่สร้างการแจ้งเตือนตามหลักไวยากรณ์ตามที่สร้างขึ้นโดยทั่วไปด้วยข้อมูลที่บรรทุกของการแจ้งเตือน

  2. ประวัติความเป็นมา / สถานะที่ถูกฆ่า - ที่นี่ระบบจะสร้างการแจ้งเตือนตามอัตราการแจ้งเตือนและการคลิกที่การแจ้งเตือนนั้นจะนำคุณไปยังกิจกรรมตัวเรียกใช้งานของแอปพลิเคชันที่คุณสามารถดึงข้อมูลเจตนาในวิธีใดก็ตาม


ขอบคุณ!!! ฉันเสียสองสามวันกับปัญหานี้และสิ่งนี้ช่วยฉัน
Igor Janković

โซลูชั่นที่สมบูรณ์แบบจริงๆ!
EduXavier

4
ฉันกำลังจัดการตรรกะการแสดงการแจ้งเตือนใน handleIntent (เจตนาเจตนา) อย่างไรก็ตามเมื่อแอปอยู่ในพื้นหลังจะมีการแจ้งเตือนปรากฏขึ้น 2 รายการอันที่ฉันได้สร้างขึ้นและอื่น ๆ ตามค่าเริ่มต้นซึ่งมีข้อความทั้งหมดจากการแจ้งเตือน
Joyson

5
เยี่ยมมาก แต่ฉันไม่เห็นประโยชน์ใด ๆOnMessageReceivedในกรณีนี้!
Alaa AbuZarifa

8
ฉันมี com.google.firebase: firebase-messaging: 11.6.2 & handleIntent ถือเป็นที่สิ้นสุดแล้วตอนนี้ตรวจสอบstackoverflow.com/questions/47308155/…
Ronak Poriya

31

นี่คือแนวคิดที่ชัดเจนมากขึ้นเกี่ยวกับข้อความ firebase ฉันพบจากทีมสนับสนุนของพวกเขา

Firebase มีข้อความสามประเภท :

ข้อความแจ้งเตือน : ข้อความแจ้งเตือนทำงานบนพื้นหลังหรือเบื้องหน้า เมื่อแอปอยู่ในพื้นหลังข้อความแจ้งเตือนจะถูกส่งไปที่ซิสเต็มเทรย์ หากแอปอยู่เบื้องหน้าข้อความจะถูกจัดการonMessageReceived()หรือdidReceiveRemoteNotificationโทรกลับ สิ่งเหล่านี้เป็นสิ่งที่เรียกว่าข้อความการแสดงผล

ข้อความข้อมูล : บนแพลตฟอร์ม Android ข้อความข้อมูลสามารถทำงานบนพื้นหลังและเบื้องหน้า ข้อความข้อมูลจะถูกจัดการโดย onMessageReceived () หมายเหตุเฉพาะแพลตฟอร์มที่นี่จะเป็น: บน Android สามารถโหลดข้อมูลได้ใน Intent ที่ใช้เพื่อเริ่มกิจกรรมของคุณ ทำอย่างละเอียดถ้าคุณมี"click_action":"launch_Activity_1"คุณสามารถดึงนี้ผ่านความตั้งใจที่จะเริ่มต้นเพียงgetIntent()Activity_1

ข้อความที่มีทั้งการแจ้งเตือนและข้อมูลที่รับส่งข้อมูล : เมื่ออยู่ในพื้นหลังแอปจะได้รับการแจ้งข้อมูลในถาดการแจ้งเตือนและจัดการเฉพาะข้อมูลที่รับส่งข้อมูลเมื่อผู้ใช้แตะที่การแจ้งเตือน เมื่ออยู่เบื้องหน้าแอปของคุณจะได้รับออบเจกต์ข้อความพร้อมเพย์โหลดทั้งสองที่มีอยู่ ประการที่สองพารามิเตอร์ click_action มักใช้ในเพย์โหลดการแจ้งเตือนไม่ใช่ในเพย์โหลดข้อมูล หากใช้ภายใน data payload พารามิเตอร์นี้จะถือว่าเป็นคู่ของคีย์ - ค่าที่กำหนดเองดังนั้นคุณจะต้องใช้ตรรกะที่กำหนดเองเพื่อให้มันทำงานตามที่ต้องการ

นอกจากนี้ฉันขอแนะนำให้คุณใช้เมธอด onMessageReceived (ดูที่ Data data) เพื่อแยกบันเดิลข้อมูล จากตรรกะของคุณฉันตรวจสอบวัตถุบันเดิลและไม่พบเนื้อหาข้อมูลที่คาดหวัง นี่คือการอ้างอิงถึงกรณีที่คล้ายกันซึ่งอาจให้ความชัดเจนมากขึ้น

จากฝั่งเซิร์ฟเวอร์การแจ้งเตือน firebase ควรจัดรูปแบบต่อไปนี้ :

ฝั่งเซิร์ฟเวอร์ควรส่งวัตถุ"แจ้งเตือน" ขาดของ "การแจ้งเตือน" วัตถุที่อยู่ในของฉันข้อความไม่ได้รับใช้TargetActivitygetIntent()

รูปแบบข้อความที่ถูกต้องจะได้รับร้อง:

{
 "data": {
  "body": "here is body",
  "title": "Title"
 },
"notification": {
  "body": "here is body",
  "title": "Title",
  "click_action": "YOUR_ACTION"
 },
 "to": "ffEseX6vwcM:APA91bF8m7wOF MY FCM ID 07j1aPUb"
}

นี่คือแนวคิดที่ชัดเจนมากขึ้นเกี่ยวกับข้อความ firebase ฉันพบจากทีมสนับสนุนของพวกเขา

สำหรับข้อมูลเพิ่มเติมโปรดเยี่ยมชมหัวข้อของฉันและหัวข้อนี้


3
มูลค่าการกล่าวขวัญว่า "ข้อความข้อมูล" จะไม่ได้รับหากอุปกรณ์อยู่ในโหมดหลับลึก (แนะนำใน Android 7.0) ระวังด้วย!
Sameer J

30

ผมมีปัญหาเหมือนกัน. ง่ายต่อการใช้ 'ข้อความข้อมูล' แทน 'การแจ้งเตือน' ข้อความข้อมูลจะโหลดคลาสที่ onMessageReceived เสมอ

ในชั้นเรียนนั้นคุณสามารถทำการแจ้งเตือนของคุณเองด้วยเครื่องมือสร้างการแจ้งเตือน

ตัวอย่าง:

 @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        sendNotification(remoteMessage.getData().get("title"),remoteMessage.getData().get("body"));
    }

    private void sendNotification(String messageTitle,String messageBody) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,0 /* request code */, intent,PendingIntent.FLAG_UPDATE_CURRENT);

        long[] pattern = {500,500,500,500,500};

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

        NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_stat_name)
                .setContentTitle(messageTitle)
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setVibrate(pattern)
                .setLights(Color.BLUE,1,1)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
    }

7
ขอบคุณ .. ฉันเปลี่ยนรหัสเซิร์ฟเวอร์ของฉันและใช้ "data" แทน "การแจ้งเตือน" และตอนนี้มันทำงานได้อย่างสมบูรณ์แบบ
Mahesh Kavathiya

5
@ ให้ใช้งานได้ก็ต่อเมื่อแอปอยู่ในเบื้องหน้าไม่ได้อยู่ในพื้นหลัง คุณสามารถช่วยฉันเรียกกิจกรรมนี้ได้ทั้งสองกรณีหรือไม่?
อนันต์ชาห์

@AnantShah POST ของคุณไปยังเซิร์ฟเวอร์ Firebase เป็นอย่างไร
Koot

3
จริงๆมีสามกรณีที่เป็นไปได้ที่นี่ 1) แอปอยู่เบื้องหน้า 2) แอปในพื้นหลัง 3) แอปไม่ทำงาน อย่างที่คุณพูดข้อความ 'data' จะได้รับในสองกรณีแรก แต่ไม่ใช่ในกรณีที่สามเมื่อแอปไม่ทำงาน หากต้องการรองรับทั้งสามกรณีคุณต้องตั้งค่าฟิลด์ 'การแจ้งเตือน' ในข้อความ (เป็นความคิดที่ดีถ้าคุณต้องการสนับสนุน iOS เช่นเดียวกับไคลเอนต์ Android)
สตีฟมอสลีย์

1
แม้ในแอพจะไม่ทำงานฉันยังได้รับข้อความจากเซิร์ฟเวอร์บนฟังก์ชันที่รับมา ฉันเห็นด้วยกับคุณว่าควรใช้ 'การแจ้งเตือน' หากคุณต้องการสนับสนุน iOS ด้วย
Koot

21

ตามเอกสาร Firebase Cloud Messaging - หากกิจกรรมอยู่ในเบื้องหน้าแล้ว onMessageReceived จะได้รับการเรียก หากกิจกรรมอยู่ในพื้นหลังหรือปิดข้อความแจ้งเตือนจะปรากฏในศูนย์การแจ้งเตือนสำหรับกิจกรรมตัวเรียกใช้งานแอป คุณสามารถโทรหากิจกรรมที่คุณกำหนดเองได้โดยคลิกที่การแจ้งเตือนหากแอปของคุณอยู่ในพื้นหลังโดยการโทรหาส่วนบริการ api สำหรับการส่งข้อความ firebase ดังนี้

URL- https://fcm.googleapis.com/fcm/send

ประเภทวิธี - POST

Header- Content-Type:application/json
Authorization:key=your api key

ตัวถังรถ / อัตรา:

{ "notification": {
    "title": "Your Title",
    "text": "Your Text",
     "click_action": "OPEN_ACTIVITY_1" // should match to your intent filter
  },
    "data": {
    "keyname": "any value " //you can get this data as extras in your activity and this data is optional
    },
  "to" : "to_id(firebase refreshedToken)"
} 

และด้วยสิ่งนี้ในแอปของคุณคุณสามารถเพิ่มโค้ดด้านล่างในกิจกรรมที่จะเรียกว่า:

<intent-filter>
                <action android:name="OPEN_ACTIVITY_1" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

ฉันจะสร้างความตั้งใจและเปิดกิจกรรมเฉพาะได้ที่ไหน ฉันรู้ว่าสิ่งนี้ลงทะเบียนเจตนาของ OPEN_ACTIVITY_1 ในรายการ แต่ฉันจะเรียกมันว่าที่ไหน
Cyogenos

1
ตรวจสอบเรื่องนี้: firebase.google.com/docs/cloud-messaging/...
Ankit Adlakha

เราควรเรียกกิจกรรมจากตัวกรองเจตนาหรือไม่? หรือเริ่มต้นด้วยตนเองในonMessageReceived?
CoolMind

14

onMessageReceived (RemoteMessage remoteMessage)วิธีการที่เรียกว่าขึ้นอยู่กับกรณีดังต่อไปนี้

  • การตอบสนอง FCMด้วยการแจ้งเตือนและบล็อกข้อมูล :
{
  
"to": "device token list",
  "notification": {
    "body": "Body of Your Notification",
    "title": "Title of Your Notification"
  },
  "data": {
    "body": "Body of Your Notification in Data",
    "title": "Title of Your Notification in Title",
    "key_1": "Value for key_1",
    "image_url": "www.abc.com/xyz.jpeg",
    "key_2": "Value for key_2"
  }
}
  1. แอปในเบื้องหน้า:

onMessageReceived (RemoteMessage remoteMessage)เรียกว่าแสดง LargeIcon และ BigPicture ในแถบการแจ้งเตือน เราสามารถอ่านเนื้อหาจากทั้งการ แจ้งเตือนและบล็อกข้อมูล

  1. แอปในพื้นหลัง:

onMessageReceived (RemoteMessage remoteMessage)ไม่ได้เรียกถาดระบบจะได้รับข้อความและอ่านเนื้อหาและชื่อจากบล็อกการแจ้งเตือนและแสดงข้อความเริ่มต้นและชื่อในแถบการแจ้งเตือน

  • การตอบสนอง FCMด้วยบล็อกข้อมูลเท่านั้น:

ในกรณีนี้ให้ลบบล็อคการแจ้งเตือนออกจาก json

{
  
"to": "device token list",
  "data": {
    "body": "Body of Your Notification in Data",
    "title": "Title of Your Notification in Title",
    "key_1": "Value for key_1",
    "image_url": "www.abc.com/xyz.jpeg",
    "key_2": "Value for key_2"
  }
}

โซลูชันสำหรับการเรียกใช้ onMessageReceived ()

  1. แอปในเบื้องหน้า:

onMessageReceived (RemoteMessage remoteMessage)เรียกว่าแสดง LargeIcon และ BigPicture ในแถบการแจ้งเตือน เราสามารถอ่านเนื้อหาจากทั้งการ แจ้งเตือนและบล็อกข้อมูล

  1. แอปในพื้นหลัง:

onMessageReceived (RemoteMessage remoteMessage)เรียกว่าถาดระบบจะไม่ได้รับข้อความเพราะรหัสการแจ้งเตือนไม่ได้อยู่ในการตอบสนอง แสดง LargeIcon และ BigPicture ในแถบการแจ้งเตือน

รหัส

 private void sendNotification(Bitmap bitmap,  String title, String 
    message, PendingIntent resultPendingIntent) {

    NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();
    style.bigPicture(bitmap);

    Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

    NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
    String NOTIFICATION_CHANNEL_ID = mContext.getString(R.string.default_notification_channel_id);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "channel_name", NotificationManager.IMPORTANCE_HIGH);

        notificationManager.createNotificationChannel(notificationChannel);
    }
    Bitmap iconLarge = BitmapFactory.decodeResource(mContext.getResources(),
            R.drawable.mdmlogo);
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(mContext, NOTIFICATION_CHANNEL_ID)
            .setSmallIcon(R.drawable.mdmlogo)
            .setContentTitle(title)
            .setAutoCancel(true)
            .setSound(defaultSound)
            .setContentText(message)
            .setContentIntent(resultPendingIntent)
            .setStyle(style)
            .setLargeIcon(iconLarge)
            .setWhen(System.currentTimeMillis())
            .setPriority(Notification.PRIORITY_MAX)
            .setChannelId(NOTIFICATION_CHANNEL_ID);


    notificationManager.notify(1, notificationBuilder.build());


}

ลิงค์อ้างอิง:

https://firebase.google.com/docs/cloud-messaging/android/receive


ส่วนที่สำคัญที่สุดสำหรับคนที่ทุกข์ทรมานจากปัญหาพื้นหลังคือการลบคุณสมบัติ "การแจ้งเตือน" จาก JSON ที่ถูกส่งโดยเซิร์ฟเวอร์ วิธีนี้จะช่วยแก้ปัญหา ขอบคุณมาก.
Ramy M. Mousa

13

ฉันได้รับปัญหาเดียวกัน หากแอปนี้ทำงานเบื้องหน้า - มันจะเปิดบริการพื้นหลังของฉันซึ่งฉันสามารถอัปเดตฐานข้อมูลของฉันตามประเภทการแจ้งเตือน แต่แอปจะไปที่พื้นหลัง - บริการแจ้งเตือนเริ่มต้นจะได้รับการดูแลให้แสดงการแจ้งเตือนแก่ผู้ใช้

นี่คือโซลูชันของฉันในการระบุแอปในพื้นหลังและเรียกใช้บริการพื้นหลังของคุณ

public class FirebaseBackgroundService extends WakefulBroadcastReceiver {

  private static final String TAG = "FirebaseService";

  @Override
  public void onReceive(Context context, Intent intent) {
    Log.d(TAG, "I'm in!!!");

    if (intent.getExtras() != null) {
      for (String key : intent.getExtras().keySet()) {
        Object value = intent.getExtras().get(key);
        Log.e("FirebaseDataReceiver", "Key: " + key + " Value: " + value);
        if(key.equalsIgnoreCase("gcm.notification.body") && value != null) {
          Bundle bundle = new Bundle();
          Intent backgroundIntent = new Intent(context, BackgroundSyncJobService.class);
          bundle.putString("push_message", value + "");
          backgroundIntent.putExtras(bundle);
          context.startService(backgroundIntent);
        }
      }
    }
  }
}

ใน manifest.xml

<receiver android:exported="true" android:name=".FirebaseBackgroundService" android:permission="com.google.android.c2dm.permission.SEND">
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            </intent-filter>
        </receiver>

ทดสอบวิธีการแก้ปัญหานี้ใน Android 8.0 รุ่นล่าสุด ขอบคุณ


ต้องการใช้คลาส FirebaseBackgroundService นี้หรือไม่? @Nagendra Badiganti

ที่จะใช้รหัสนี้คลาสสาธารณะ FirebaseBackgroundService ขยาย WakefulBroadcastReceiver @Nagendra Badiganti

สร้างคลาสบริการในแพ็คเกจของคุณและลงทะเบียนใน manifest.xml ของคุณ ตรวจสอบให้แน่ใจว่าคุณมีตัวกรองสำหรับการแจ้งเตือนของคุณ เนื่องจากบริการเริ่มต้นสำหรับการแจ้งเตือน GCM ทุกครั้ง
Nagendra Badiganti

firebase.google.com/docs/cloud-messaging/android/…ฉันติดตามลิงค์นี้ฉันต้องเพิ่มคลาสนี้เพื่อรับการแจ้งเตือน เพิ่งส่งข้อความจาก firebase ข้อความแรก .. มันบอกว่าเสร็จแล้ว แต่ไม่ได้รับการแจ้งเตือน @Nagendra Badiganti

1
WakefulBroadcastReceiverเลิกใช้แล้วตั้งแต่ระดับ API 26.1.0
Minoru

12

หากแอปอยู่ในโหมดพื้นหลังหรือไม่ใช้งาน (ถูกฆ่า) และคุณคลิกที่การแจ้งเตือนคุณควรตรวจสอบน้ำหนักบรรทุกใน LaunchScreen (ในหน้าจอเปิดตัวเคสของฉันคือ MainActivity.java)

ดังนั้นในMainActivity.javaบนonCreateตรวจสอบExtras :

    if (getIntent().getExtras() != null) {
        for (String key : getIntent().getExtras().keySet()) {
            Object value = getIntent().getExtras().get(key);
            Log.d("MainActivity: ", "Key: " + key + " Value: " + value);
        }
    }

ฉันจะรับชื่อการแจ้งเตือนเนื้อหาและข้อมูลได้อย่างไร
Md.Tarikul Islam

1
ขอบคุณนี่คือคำตอบ @ Md.Tarikul อิสลามใช้ onMessageReceived () ตามที่กล่าวไว้ในคำถามนี้
felixwcf

7

แทนที่handleIntentวิธีการFirebaseMessageServiceทำงานสำหรับฉัน

ที่นี่รหัสในC # (Xamarin)

public override void HandleIntent(Intent intent)
{
    try
    {
        if (intent.Extras != null)
        {
            var builder = new RemoteMessage.Builder("MyFirebaseMessagingService");

            foreach (string key in intent.Extras.KeySet())
            {
                builder.AddData(key, intent.Extras.Get(key).ToString());
            }

            this.OnMessageReceived(builder.Build());
        }
        else
        {
            base.HandleIntent(intent);
        }
    }
    catch (Exception)
    {
        base.HandleIntent(intent);
    }
}

และนั่นคือรหัสในJava

public void handleIntent(Intent intent)
{
    try
    {
        if (intent.getExtras() != null)
        {
            RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService");

            for (String key : intent.getExtras().keySet())
            {
                builder.addData(key, intent.getExtras().get(key).toString());
            }

            onMessageReceived(builder.build());
        }
        else
        {
            super.handleIntent(intent);
        }
    }
    catch (Exception e)
    {
        super.handleIntent(intent);
    }
}

handleIntent () ถือเป็นที่สิ้นสุด
Ettore

@Ettore ฉันจะเรียกใช้ฟังก์ชัน handleIntent ได้อย่างไร
Hiroto

วิธีการที่เรียกว่าเมื่อคุณได้รับข้อความจาก Firebase แต่คุณไม่สามารถแทนที่เพราะวิธีการจะประกาศขั้นสุดท้าย (Firebase 11.6.0)
Ettore

5

ตามค่าเริ่มต้นกิจกรรมตัวเรียกใช้ในแอปของคุณจะเปิดขึ้นเมื่อแอปของคุณอยู่ในพื้นหลังและคุณคลิกการแจ้งเตือนหากคุณมีส่วนข้อมูลใด ๆ ที่มีการแจ้งเตือนคุณสามารถจัดการได้ในกิจกรรมเดียวกันดังต่อไปนี้

if(getIntent().getExtras()! = null){
  //do your stuff
}else{
  //do that you normally do
}

หากฉันนำทางจาก mainActivity การนำทางกลับไปยังกิจกรรมใดจะทำงานอย่างไร
Mac_Play

@Uzair getIntent (). getExtras () รับ null เสมอคุณมีวิธีแก้ไขปัญหาอื่น ๆ หรือไม่เมื่อแอปพลิเคชั่น bacground บนเมธอด
เมสเสจเรคคอร์ด

3

หากแอปอยู่ในพื้นหลังไฟฐานโดยการแจ้งเตือนการจัดการเริ่มต้น แต่ถ้าเราต้องการการแจ้งเตือนที่กำหนดเองของเรากว่าที่เราต้องเปลี่ยนฝั่งเซิร์ฟเวอร์ของเราซึ่งมีหน้าที่รับผิดชอบในการส่งข้อมูลที่กำหนดเองของเรา

ลบเพย์โหลดการแจ้งเตือนออกจากคำขอเซิร์ฟเวอร์ของคุณโดยสมบูรณ์ ส่งข้อมูลเท่านั้นและจัดการใน onMessageReceived () มิฉะนั้น onMessageReceived ของคุณจะไม่ถูกทริกเกอร์เมื่อแอปอยู่ในพื้นหลังหรือถูกฆ่า

ตอนนี้รูปแบบโค้ดฝั่งเซิร์ฟเวอร์ของคุณดูเหมือนว่า

{
  "collapse_key": "CHAT_MESSAGE_CONTACT",
  "data": {
    "loc_key": "CHAT_MESSAGE_CONTACT",
    "loc_args": ["John Doe", "Contact Exchange"],
    "text": "John Doe shared a contact in the group Contact Exchange",
    "custom": {
      "chat_id": 241233,
      "msg_id": 123
    },
    "badge": 1,
    "sound": "sound1.mp3",
    "mute": true
  }
}

บันทึก : ดูบรรทัดนี้ในรหัสด้านบน
"text": "John Doe แบ่งปันผู้ติดต่อในกลุ่ม Contact Exchange" ใน data payload คุณควรใช้พารามิเตอร์ "text" แทนพารามิเตอร์ "body" หรือ "message" สำหรับคำอธิบายข้อความหรืออะไรก็ตามที่คุณ ต้องการใช้ข้อความ

onMessageReceived ()

@Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.e(TAG, "From: " + remoteMessage.getData().toString());

        if (remoteMessage == null)
            return;

        // Check if message contains a data payload.
        if (remoteMessage.getData().size() > 0) {
           /* Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString());*/
            Log.e(TAG, "Data Payload: " + remoteMessage);

            try {

                Map<String, String> params = remoteMessage.getData();
                JSONObject json = new JSONObject(params);
                Log.e("JSON_OBJECT", json.toString());


                Log.e(TAG, "onMessageReceived: " + json.toString());

                handleDataMessage(json);
            } catch (Exception e) {
                Log.e(TAG, "Exception: " + e.getMessage());
            }
        }
    }

2

เพียงเรียกสิ่งนี้ในวิธี onCreate ของ MainActivity ของคุณ:

if (getIntent().getExtras() != null) {
           // Call your NotificationActivity here..
            Intent intent = new Intent(MainActivity.this, NotificationActivity.class);
            startActivity(intent);
        }

ถ้าฉันนำทางจาก mainActivity การนำทางกลับไปยังกิจกรรมใดจะทำงาน
Mac_Play

2

ตามการแก้ปัญหาจาก t3h Exi ฉันต้องการโพสต์รหัสสะอาดที่นี่ เพียงแค่ใส่ไว้ใน MyFirebaseMessagingService และทุกอย่างทำงานได้ดีหากแอปอยู่ในโหมดเบื้องหลัง คุณต้องรวบรวมอย่างน้อย com.google.firebase: firebase-messaging: 10.2.1

 @Override
public void handleIntent(Intent intent)
{
    try
    {
        if (intent.getExtras() != null)
        {
            RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService");

            for (String key : intent.getExtras().keySet())
            {
                builder.addData(key, intent.getExtras().get(key).toString());
            }



           onMessageReceived(builder.build());
        }
        else
        {
            super.handleIntent(intent);
        }
    }
    catch (Exception e)
    {
        super.handleIntent(intent);
    }
}

ฉันพยายามที่จะใช้วิธีการแก้ปัญหาของคุณ แต่ handleIntent () วิธีการเป็นขั้นสุดท้ายในรุ่น SDK ของฉัน (SDK 27) ดังนั้นฉันไม่สามารถแทนที่มันในการให้บริการของฉัน ...
matdev

ใช่ แต่นั่นไม่ใช่ความผิดของฉันหรือเหตุผลใด ๆ ที่ให้ -1 !!! หยิ่งมาก มันทำงานได้จนถึง firebase 11.4.2 จากนั้น google ก็เปลี่ยนมัน (ทำให้วิธีนี้เป็นขั้นสุดท้าย) ดังนั้นตอนนี้คุณต้องตั้งโปรแกรมการแก้ปัญหาของคุณเองด้วยการแจ้งเตือน
Frank

ฉันไม่ได้ให้ -1 แต่เป็น +1!
matdev

คุณช่วยงานของฉัน: P
amitabha2715

2

ลองสิ่งนี้:

public void handleIntent(Intent intent) {
    try {
        if (intent.getExtras() != null) {
            RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService");
            for (String key : intent.getExtras().keySet()) {
            builder.addData(key, intent.getExtras().get(key).toString());
        }
            onMessageReceived(builder.build());
        } else {
            super.handleIntent(intent);
        }
    } catch (Exception e) {
        super.handleIntent(intent);
    }
}

handleIntent ไม่ได้ใช้ใน firebase อีกต่อไป: 11.8.0 และสูงกว่า
Shihab Uddin

1

ฉันมีปัญหานี้ (แอปไม่ต้องการเปิดเมื่อคลิกการแจ้งเตือนหากแอปอยู่ในพื้นหลังหรือปิด) และปัญหานั้นไม่ถูกต้องclick_actionในเนื้อหาการแจ้งเตือนลองลบหรือเปลี่ยนเป็นสิ่งที่ถูกต้อง


1

จุดที่สมควรได้รับการเน้นคือคุณต้องใช้ข้อความข้อมูล - คีย์ข้อมูลเท่านั้น - เพื่อรับ onMessageReceived handler เรียกว่าแม้ว่าแอพจะอยู่ในพื้นหลัง คุณไม่ควรมีคีย์ข้อความการแจ้งเตือนอื่นใดใน payload ของคุณมิฉะนั้นตัวจัดการจะไม่ถูกเรียกหากแอปอยู่ในพื้นหลัง

มันถูกกล่าวถึง (แต่ไม่เน้นในเอกสารประกอบ FCM) ที่นี่:

https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages

ใช้เซิร์ฟเวอร์แอปและ FCM เซิร์ฟเวอร์ API: ตั้งค่าคีย์ข้อมูลเท่านั้น สามารถยุบได้หรือไม่ยุบก็ได้


1

แบ็กเอนด์ที่ฉันทำงานด้วยกำลังใช้ข้อความแจ้งเตือนไม่ใช่ข้อความข้อมูล ดังนั้นหลังจากอ่านคำตอบทั้งหมดฉันพยายามดึงความพิเศษจากชุดของเจตนาที่มาพร้อมกับกิจกรรมที่เปิดตัว แต่ไม่ว่าฉันจะพยายามดึงกุญแจใดจากgetIntent().getExtras();ค่านั้นก็จะว่างเสมอ

อย่างไรก็ตามในที่สุดฉันก็พบวิธีการส่งข้อมูลโดยใช้ข้อความแจ้งเตือนและดึงข้อมูลจากเจตนา

กุญแจสำคัญในที่นี้คือการเพิ่มปริมาณข้อมูลลงในข้อความแจ้งเตือน

ตัวอย่าง:

{
    "data": {
        "message": "message_body",
        "title": "message_title"
    },
    "notification": {
        "body": "test body",
        "title": "test title"
    },
    "to": "E4An.."
}

หลังจากที่คุณทำเช่นนี้คุณจะสามารถรับข้อมูลของคุณในลักษณะนี้:

intent.getExtras().getString("title") จะ message_title

และ intent.getExtras().getString("message") จะเป็นmessage_body

การอ้างอิง


1

หากปัญหาของคุณเกี่ยวข้องกับการแสดงภาพขนาดใหญ่เช่นถ้าคุณกำลังส่งการแจ้งเตือนแบบพุชด้วยภาพจากคอนโซลฐานไฟและมันจะแสดงภาพเฉพาะในกรณีที่แอปในเบื้องหน้า วิธีแก้ปัญหาสำหรับปัญหานี้คือการส่งข้อความแบบพุชโดยมีเพียงฟิลด์ข้อมูล บางสิ่งเช่นนี้

{ "data": { "image": "https://static.pexels.com/photos/4825/red-love-romantic-flowers.jpg", "message": "Firebase Push Message Using API" "AnotherActivity": "True" }, "to" : "device id Or Device token" }

คุณทำเครื่องหมายจุลภาคหายก่อน "กิจกรรมอื่น" Android ของฉันสั่น แต่ไม่มีอะไรแสดง (ไม่มีข้อความไม่มีภาพไม่มีการกด)
jekaby

1

เมื่อได้รับข้อความและแอปของคุณอยู่ในพื้นหลังการแจ้งเตือนจะถูกส่งไปยังเจตนาพิเศษของกิจกรรมหลัก

คุณสามารถตรวจสอบค่าพิเศษในฟังก์ชั่น oncreate () หรือ onresume () ของกิจกรรมหลัก

คุณสามารถตรวจสอบฟิลด์เช่นข้อมูลตาราง ฯลฯ (ฟิลด์ที่ระบุในการแจ้งเตือน)

เช่นฉันส่งโดยใช้ข้อมูลเป็นกุญแจสำคัญ

public void onResume(){
    super.onResume();
    if (getIntent().getStringExtra("data")!=null){
            fromnotification=true;
            Intent i = new Intent(MainActivity.this, Activity2.class);
            i.putExtra("notification","notification");
            startActivity(i);
        }

}

0

ฉันมีปัญหาเดียวกันและทำการขุดเพิ่มเติมนี้ เมื่อแอปอยู่ในพื้นหลังเป็นข้อความแจ้งเตือนจะถูกส่งไปถาดระบบ แต่ข้อความข้อมูลจะถูกส่งไปonMessageReceived()
ดูhttps://firebase.google.com/docs/cloud-messaging/downstream#monitor-token-generation_3
และ https://github.com/firebase/quickstart-android/blob/master/messaging/app/src/main/java/com/google/firebase/quickstart/fcm/MyFirebaseMessagingService.java

เพื่อให้แน่ใจว่าข้อความที่คุณกำลังส่งเอกสารพูดว่า " ใช้เซิร์ฟเวอร์แอปของคุณและเซิร์ฟเวอร์ FCM API: ตั้งค่าคีย์ข้อมูลเท่านั้นสามารถพับหรือไม่ยุบ "
ดูhttps://firebase.google.com/ เอกสาร / เมฆส่งข้อความ / แนวคิดตัวเลือก # notifications_and_data_messages


0

ข้อความมีสองประเภท: ข้อความแจ้งเตือนและข้อความข้อมูล หากคุณส่งข้อความข้อมูลเท่านั้นนั่นคือไม่มีวัตถุแจ้งเตือนในสตริงข้อความของคุณ มันจะถูกเรียกใช้เมื่อแอปของคุณอยู่ในพื้นหลัง


0

ตรวจสอบคำตอบของ @Mahesh Kavathiya สำหรับกรณีของฉันในรหัสเซิร์ฟเวอร์มีดังนี้:

{
"notification": {
  "body": "here is body",
  "title": "Title",
 },
 "to": "sdfjsdfonsdofoiewj9230idsjkfmnkdsfm"
}

คุณต้องเปลี่ยนเป็น:

{
 "data": {
  "body": "here is body",
  "title": "Title",
  "click_action": "YOUR_ACTION"
 },
"notification": {
  "body": "here is body",
  "title": "Title"
 },
 "to": "sdfjsdfonsdofoiewj9230idsjkfmnkdsfm"
}

จากนั้นในกรณีที่แอปในพื้นหลังเจตนากิจกรรมเริ่มต้นพิเศษจะได้รับ"ข้อมูล"

โชคดี!


-1

เพียงแทนที่วิธี OnCreate ของ FirebaseMessagingService มันถูกเรียกเมื่อแอพของคุณอยู่ในพื้นหลัง:

public override void OnCreate()
{
    // your code
    base.OnCreate();
}

คำตอบนี้อาจมีประโยชน์มากขึ้นถ้าคุณสามารถเพิ่มคำอธิบายและเชื่อมโยงไปยังเอกสารบางอย่าง คุณช่วยบอกเราด้วยว่ามันควรจะช่วยได้อย่างไร
kilokahn

@kilokahn คุณช่วยอธิบายสิ่งที่คุณไม่เข้าใจให้ฉันได้ไหม วิธีการที่ระบุจะต้องใส่ในรหัสที่เป็นส่วนหนึ่งของคำถามและตอบคำถามอย่างเต็มที่ รหัสนี้ใช้สำหรับ Xamarin แต่คุณสามารถแปลงเป็นจาวาได้
Renzo Ciot

AFAIK เอกสารอย่างเป็นทางการ ( firebase.google.com/docs/cloud-messaging/android/client ) ไม่ได้พูดเกี่ยวกับการเอาชนะ OnCreate ในบริการที่ขยาย FirebaseMessagingService - ถ้าคุณเข้าถึงเอกสารที่ทำคุณอาจแชร์ลิงก์ได้ไหม นอกจากนี้จากคำตอบของคุณยังไม่ชัดเจนว่าการเอาชนะ onCreate แก้ปัญหาของ onMessageReceived ไม่ได้รับการโทรเมื่อคลิกแจ้งเตือน - จึงขอข้อมูลเพิ่มเติม
kilokahn

เอกสารไม่ได้กล่าวถึงการแทนที่ของวิธี OnCreate แต่มันใช้งานได้เพราะฉันใช้มันในการผลิต รหัสที่คุณต้องการแทรกในเมธอด onMessageReceived และเห็นได้ชัดว่าทำหน้าที่ในการดำเนินการพื้นหลังบางอย่างสามารถทำได้บน OnCreate
Renzo Ciot

ในกรณีดังกล่าวการอธิบายถึงความจริงที่ว่าวิธีนี้ใช้งานได้กับคุณอาจพิสูจน์ได้ว่ามีประโยชน์มากกว่าการแสดงรายการโซลูชัน นอกจากนี้พฤติกรรมที่ไม่มีเอกสารก็น่าจะหยุดทำงานกับการอัปเดตโดยพลการและผู้ที่ใช้งานพวกเขาจะต้องเตรียมพร้อมที่จะทำใหม่โค้ดเมื่อมันทำ ข้อจำกัดความรับผิดชอบนี้จะต้องมีการวางไว้
kilokahn

-1

มี2 ประเภทของFirebaseแจ้งเตือนแบบพุช :

1- ข้อความแจ้งเตือน (ข้อความที่แสดง) -> - 1.1 หากคุณเลือกตัวแปรนี้ระบบปฏิบัติการจะสร้างการแจ้งเตือนด้วยตนเองหากแอปอยู่ในพื้นหลังและจะส่งข้อมูลในintentและจะส่งผ่านข้อมูลในส่วนจากนั้นก็ขึ้นอยู่กับลูกค้าที่จะจัดการกับข้อมูลนี้

- 1.2 หากแอปอยู่ในเบื้องหน้าการแจ้งเตือนนั้นจะได้รับผ่านทางcallback-functionในFirebaseMessagingServiceและขึ้นอยู่กับลูกค้าที่จะจัดการ

2- ข้อความข้อมูล (สูงสุด 4k data) -> ข้อความเหล่านี้ใช้เพื่อส่งข้อมูลไปยังลูกค้า (เงียบ ๆ ) และขึ้นอยู่กับไคลเอ็นต์เพื่อจัดการกับทั้งสองกรณีพื้นหลัง / เบื้องหน้าผ่านฟังก์ชันการเรียกกลับใน FirebaseMessagingService

เป็นไปตามเอกสารอย่างเป็นทางการ: https://firebase.google.com/docs/cloud-messaging/concept-options

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.