firebase / firebase-ios-sdk

Firebase SDK for Apple App Development
https://firebase.google.com
Apache License 2.0
5.47k stars 1.43k forks source link

FR: Update iOS 16 Live Activities using FCM #10047

Open mbuchetics opened 1 year ago

mbuchetics commented 1 year ago

Feature proposal

Apple just added iOS 16 Live Activities to Xcode 14 Beta 4: https://developer.apple.com/documentation/activitykit/displaying-live-data-on-the-lock-screen-with-live-activities

Updating a Live Activity is done using remote push notifications (see "Update or end a Live Activity with a remote push notification" in the documentation). Each active Live Activity gets its own push token and is updated whenever a remote notification is sent to that token with the app-specific payload, e.g.

{
    "aps": {
        "timestamp": 1650998941,
        "event": "update",
        "content-state": {
            "driverName": "Anne Johnson",
            "estimatedDeliveryTime": 1659416400
        }
    }
}

Currently, FCM maps the APNS device token to its own registration token. It would be great to use FCM to also send pushes to the Live Activities of an app. Is there a way to use FCM to send an Apple remote notification to a specific APNS token (instead of using a FCM registration token)?

paulb777 commented 1 year ago

Adding for consideration to the Firebase 10 milestone.

cc: @leojaygoogle

meherdattaC commented 1 year ago

Are there any updates on the fix for this?

aashishpatil-g commented 1 year ago

We are still investigating a Live Activities and FCM integration. In the meantime, if you have any feedback or suggestions please feel free to follow up.

If you can share the kind of integration you are considering, that would be helpful for us to ensure that we consider all the different use cases.

mbuchetics commented 1 year ago

@aashishpatil-g we are working on Taxi.eu, a taxi booking app and would like to use Live Activities to show the user the status of the ride (approaching taxi, ...). FCM is used for all push related things and we are sending push notifications for each status change. We would like to keep using FCM for Live Activities as well but would need support to send a notification to a specific push token.

For us, it would be fine to just send the custom APNS push token with the push payload and FCM would send the push notification to that specific token and not the user's general FCM token.

ericagredo commented 1 year ago

Anyone think of a workaround for this?

bodhihawken commented 1 year ago

Would love to see a workaround for this without having to set up our own apns stuff!

aashishpatil-g commented 1 year ago

Thanks for the interest @ericagredo and @Hawki101. We are still investigating this.

If live activity support is important for you, please be sure to give a thumbs up to the original post if you haven't done so already.

bodhihawken commented 1 year ago

I attempted a workaround today generating the fcm token on the server, however, ran into Invalid [apns-push-type] set for apns platform for "apns-push-type": "liveactivity" so wasn't able to use this as a way around!

ericagredo commented 1 year ago

I have a working workaround. It’s using Firebase functions. I’ll post a write up tomorrow for everyone.

bodhihawken commented 1 year ago

Epic! currently working on a direct send via APNS instead! but interested to read through some alternatives!

ericagredo commented 1 year ago

I have a working workaround. It’s using Firebase functions. I’ll post a write up tomorrow for everyone.

To begin, you want to make sure you've gone through the process of enabling push notifications and downloaded the p8 file. https://medium.com/@syumak/how-to-send-push-notifications-to-ios-devices-via-p8-key-using-amazon-pinpoint-f08efb2a6b7 Then, create a firebase function. In our function we're going to be using the http2 and jsonwebtoken library. Here is my code with what you need:

app.post("/startTrigger", async (request, response) => {
         var amount = request.body.amount
         var deviceToken = request.body.deviceToken;
         var privateKey = fs.readFileSync('YOUR_P8_FILE.p8');
        const secondsSinceEpoch = Math.round(Date.now() / 1000)
        var payload = {
            iss: 'YOUR_TEAM_ID',
            iat: secondsSinceEpoch
         }
        var finalEncryptToken = jwt.sign(payload, privateKey, {algorithm: 'ES256', keyid: 'YOUR_KEY_ID'});
        const session = http2.connect('https://api.sandbox.push.apple.com:443/3/device/' + deviceToken);
       const body = {
            "aps": {
            "timestamp": secondsSinceEpoch,
            "event": "update",
            "content-state": {
                 'value': amount
              }
        }
    };
    functions.logger.log("token:", finalEncryptToken);

    var buffer = new Buffer.from(JSON.stringify(body));

    const req = session.request({
      ":method": "POST",
      ":path": "/3/device/" + deviceToken,
      "authorization": "bearer " + finalEncryptToken,
      "apns-push-type": "liveactivity",
      "apns-topic": "YOUR_BUNDLE_ID.push-type.liveactivity",
      "Content-Type": 'application/json',
      "Content-Length": buffer.length
    });
    functions.logger.log()
    req.on('response', (headers) => {
      console.log(headers[http2.constants.HTTP2_HEADER_STATUS]);
    });
    let data = '';
    req.setEncoding('utf8');
    req.on('data', (chunk) => data += chunk);
    req.on('end', () => {
      console.log(`The server says: ${data}`);
    });
    req.end(JSON.stringify(body));

};

When you create your p8 file, you'll see that you get the file but on the page you downloaded it they'll also give you a KEY ID. That's what you use to fill in for KEY_ID. "YOUR_P8_FILE" is the path to your downloaded p8 file. My p8 file was deployed with my function. You also need your team ID, which you get from the developer page and should be under your name. Device token is the activity push token that your activity produces. You need to send that to the function as a post request. Follow this guide as well to make sure you have the payload just like your content state https://developer.apple.com/documentation/activitykit/update-and-end-your-live-activity-with-remote-push-notifications

twhitt14 commented 1 year ago

I have a working workaround. It’s using Firebase functions. I’ll post a write up tomorrow for everyone.

To begin, you want to make sure you've gone through the process of enabling push notifications and downloaded the p8 file. https://medium.com/@syumak/how-to-send-push-notifications-to-ios-devices-via-p8-key-using-amazon-pinpoint-f08efb2a6b7 Then, create a firebase function. In our function we're going to be using the http2 and jsonwebtoken library. Here is my code with what you need:

app.post("/startTrigger", async (request, response) => {
         var amount = request.body.amount
         var deviceToken = request.body.deviceToken;
         var privateKey = fs.readFileSync('YOUR_P8_FILE.p8');
        const secondsSinceEpoch = Math.round(Date.now() / 1000)
        var payload = {
            iss: 'YOUR_TEAM_ID',
            iat: secondsSinceEpoch
         }
        var finalEncryptToken = jwt.sign(payload, privateKey, {algorithm: 'ES256', keyid: 'YOUR_KEY_ID'});
        const session = http2.connect('https://api.sandbox.push.apple.com:443/3/device/' + deviceToken);
       const body = {
            "aps": {
            "timestamp": secondsSinceEpoch,
            "event": "update",
            "content-state": {
                 'value': amount
              }
        }
    };
    functions.logger.log("token:", finalEncryptToken);

    var buffer = new Buffer.from(JSON.stringify(body));

    const req = session.request({
      ":method": "POST",
      ":path": "/3/device/" + deviceToken,
      "authorization": "bearer " + finalEncryptToken,
      "apns-push-type": "liveactivity",
      "apns-topic": "YOUR_BUNDLE_ID.push-type.liveactivity",
      "Content-Type": 'application/json',
      "Content-Length": buffer.length
    });
    functions.logger.log()
    req.on('response', (headers) => {
      console.log(headers[http2.constants.HTTP2_HEADER_STATUS]);
    });
    let data = '';
    req.setEncoding('utf8');
    req.on('data', (chunk) => data += chunk);
    req.on('end', () => {
      console.log(`The server says: ${data}`);
    });
    req.end(JSON.stringify(body));

};

When you create your p8 file, you'll see that you get the file but on the page you downloaded it they'll also give you a KEY ID. That's what you use to fill in for KEY_ID. "YOUR_P8_FILE" is the path to your downloaded p8 file. My p8 file was deployed with my function. You also need your team ID, which you get from the developer page and should be under your name. Device token is the activity push token that your activity produces. You need to send that to the function as a post request. Follow this guide as well to make sure you have the payload just like your content state https://developer.apple.com/documentation/activitykit/update-and-end-your-live-activity-with-remote-push-notifications

@ericagredo This is awesome! So you just included your p8 file in the functions folder (e.g. next to index.js) & it will be uploaded & read just like that? I'm not really a Node dev so I don't know if that's how it will work. You also reference api.sandbox.push.apple.com but I'm guessing we should use api.push.apple.com for production? Sorry, I've never read all the APNs docs & don't know how much I can just copy/paste. Thanks again for posting your solution!

ericagredo commented 1 year ago

I have a working workaround. It’s using Firebase functions. I’ll post a write up tomorrow for everyone.

To begin, you want to make sure you've gone through the process of enabling push notifications and downloaded the p8 file. https://medium.com/@syumak/how-to-send-push-notifications-to-ios-devices-via-p8-key-using-amazon-pinpoint-f08efb2a6b7 Then, create a firebase function. In our function we're going to be using the http2 and jsonwebtoken library. Here is my code with what you need:

app.post("/startTrigger", async (request, response) => {
         var amount = request.body.amount
         var deviceToken = request.body.deviceToken;
         var privateKey = fs.readFileSync('YOUR_P8_FILE.p8');
        const secondsSinceEpoch = Math.round(Date.now() / 1000)
        var payload = {
            iss: 'YOUR_TEAM_ID',
            iat: secondsSinceEpoch
         }
        var finalEncryptToken = jwt.sign(payload, privateKey, {algorithm: 'ES256', keyid: 'YOUR_KEY_ID'});
        const session = http2.connect('https://api.sandbox.push.apple.com:443/3/device/' + deviceToken);
       const body = {
            "aps": {
            "timestamp": secondsSinceEpoch,
            "event": "update",
            "content-state": {
                 'value': amount
              }
        }
    };
    functions.logger.log("token:", finalEncryptToken);

    var buffer = new Buffer.from(JSON.stringify(body));

    const req = session.request({
      ":method": "POST",
      ":path": "/3/device/" + deviceToken,
      "authorization": "bearer " + finalEncryptToken,
      "apns-push-type": "liveactivity",
      "apns-topic": "YOUR_BUNDLE_ID.push-type.liveactivity",
      "Content-Type": 'application/json',
      "Content-Length": buffer.length
    });
    functions.logger.log()
    req.on('response', (headers) => {
      console.log(headers[http2.constants.HTTP2_HEADER_STATUS]);
    });
    let data = '';
    req.setEncoding('utf8');
    req.on('data', (chunk) => data += chunk);
    req.on('end', () => {
      console.log(`The server says: ${data}`);
    });
    req.end(JSON.stringify(body));

};

When you create your p8 file, you'll see that you get the file but on the page you downloaded it they'll also give you a KEY ID. That's what you use to fill in for KEY_ID. "YOUR_P8_FILE" is the path to your downloaded p8 file. My p8 file was deployed with my function. You also need your team ID, which you get from the developer page and should be under your name. Device token is the activity push token that your activity produces. You need to send that to the function as a post request. Follow this guide as well to make sure you have the payload just like your content state https://developer.apple.com/documentation/activitykit/update-and-end-your-live-activity-with-remote-push-notifications

@ericagredo This is awesome! So you just included your p8 file in the functions folder (e.g. next to index.js) & it will be uploaded & read just like that? I'm not really a Node dev so I don't know if that's how it will work. You also reference api.sandbox.push.apple.com but I'm guessing we should use api.push.apple.com for production? Sorry, I've never read all the APNs docs & don't know how much I can just copy/paste. Thanks again for posting your solution!

yes for both questions. https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns

inkytibbs commented 1 year ago

Bump for supporting Live Activities via FCM, would really help with a feature we're working on.

@paulb777 👋🏼

charlotteliang commented 1 year ago

@inkytibbs Make sure to upvote the OP at the top.

ericagredo commented 1 year ago

Bump for supporting Live Activities via FCM, would really help with a feature we're working on.

@paulb777 👋🏼

@inkytibbs why not just use firebase functions like I showed above? It works perfectly fine.

inkytibbs commented 1 year ago

Bump for supporting Live Activities via FCM, would really help with a feature we're working on. @paulb777 👋🏼

@inkytibbs why not just use firebase functions like I showed above? It works perfectly fine.

We're going to give that solution a shot. Just thought it would be cool for FCM to officially support Live Activities with documentation and support (assuming Live Activities becomes a popular Apple API).

Thanks for sharing this workaround!

mbuchetics commented 1 year ago

any news here @aashishpatil-g @paulb777 ?

shevzoom commented 1 year ago

FCM doesnt work with apns type = liveactivity in headers? @ericagredo Is there such a life hack with С# libs? may be you know?

dejanr commented 1 year ago

It's really bad that FCM still doesn't have a plan to support live activity, and that we have to change a provider because of this, all other providers support it for months now.

Any update on this that i have missed?

vscafuto87 commented 1 year ago

Any news here @eldhosembabu ?

Azeem00786 commented 1 year ago

@here I am writing to inquire about your plans to support the new feature introduced in iOS 16 live activity. As a Firebase user, I am interested in utilising this feature in my app, and I would greatly appreciate it if Firebase could provide support for it. can you please guys give any timeline?

paulb777 commented 1 year ago

Sorry. We can't say anything about future plans on this feature. Please keep adding 👍 to help us with prioritization.

ambogatyrev commented 1 year ago

there's no progress on that yet?

kalmicka commented 1 year ago

Since Live Activities are expanding on the iOS ecosystem (iOS 17) it would totally make sense to bump up the prioritisation of this feature 😌 Would love to get an update on any plans 🙂

Azeem00786 commented 1 year ago

@here I fully understand that implementing new features takes time and effort. I want to express my unwavering trust in Firebase and its exceptional service. While I appreciate the ongoing commitment and value Firebase brings to my app's development, I kindly request any information you can provide regarding a potential timeline for the support of the 'live activity' feature. This will help me plan and align my app's roadmap accordingly. Thank you for your attention and ongoing commitment to improving Firebase. I look forward to any information or updates you can provide regarding the support for the "live activity" feature in iOS 16.

rlee1990 commented 10 months ago

It's now over a year since this post was created. I would really love to see some updates from Firebase about this. Apple is really pushing this feature so it would be nice to have it supported.

MichaelTendoSsemwanga commented 9 months ago

++1

usamaeltmsah commented 8 months ago

Please prioritize it!!

eminsr commented 8 months ago

Based on previous comments the prioritization (partly) determined by a thumbs-up for the issue, although this has been the most requested feature for a long time, there is not even an update is shared.

To me, it seems like they don't want to lose users by bluntly saying, we don't want to implement or spend time on an iOS only feature because we are Google which makes sense, implementing this only helps iOS because it will open the doors for a cool future. I guess until they come up with something like a temporary widget for Android, this future is not going to be implemented.

I'd love to be wrong, please prove me wrong at any point.

PS: This comment is not about any individual or firebase itself. Merely a reality check for anyone who is waiting and eagerly checking this issue.

peterfriese commented 8 months ago

Hi Emin,

this has nothing to do with this being an iOS-only feature. We've got plenty of iOS/Apple only features (such as Codable support, SwiftUI view modifiers for Analytics, the @FirestoreQuery property wrapper, and many more), and our decisions are not gated in any way by whether or not a feature can also be made available on Android.

There is a bunch of backend work that needs to be done for this feature, and the SDK depends on this work to be finished before we can make it available.

Thanks for caring - we hear you, and Paul and I are personally advocating for this feature.

Please bear with us while we work behind the scenes.

Thanks, Peter

laxnyc commented 6 months ago

Having read all the meekly worded comments above, I’m going to be a little more blunt:

As of writing, there have been 535 days - or 362 business days - since the original request.

The fact that Live Activities have been marketed by Apple and matured as an integral part of the iOS experience to support and enable the use cases of the real-time economy, let’s recognize that with just 100 days till iOS 18 arrives, the Firebase team has skipped TWO iOS versions.

Let that sink in.

And for those keeping count, that’s three iOS versions, assuming support is not forthcoming by June.

Every single person at Firebase who has touched on this topic and decided not to move the needle should be absolutely ashamed of themselves.

It’s not laziness. If not incompetence, it’s complicity in some diabolical strategic decision making to stunt developers’ execution of emerging features of iOS that are not just tangential to Firebase’s service, but are in fact core to it. After 2 years, there is no third possibility.

The response in mid-January 2024, “Please bear with us while we work behind the scenes”, after waiting two years, simply doesn’t cut it. It’s pathetic.

Either we switch platforms, or build our own solution, that is the juncture we’re STILL at after two long years, and soon three iOS versions.

Any good will faith we’ve had in you has been lost.

You should be ashamed.

kurtguenther commented 4 months ago

Hi Emin,

Thanks for caring - we hear you, and Paul and I are personally advocating for this feature.

Please bear with us while we work behind the scenes.

Thanks, Peter

It's been 6 months since this last message, is there any update of when Firebase will commit to supporting Live Activities?

astronaute77 commented 3 months ago

Can we get an update please? An approximate ETA would be enough or if you're not actively working on it, please let us know so we can start looking for alternatives.

ericagredo commented 3 months ago

Can we get an update please? An approximate ETA would be enough or if you're not actively working on it, please let us know so we can start looking for alternatives.

I have commented a solution above that has worked for me. I currently support live activities and still use firebase.

biene2020 commented 1 month ago

I'm currently using Firebase 10.24 for Analytics and Crashlytics; but not for Cloud Messaging. Can google give indication if there is plan for this feature (i.e. support for apns-push-type liveactivity) in your milestone? It'll help developer to decide on using FCM. Thanks!

peterfriese commented 1 month ago

We're working on this. You can follow along the frontend work in #12964 (bearing in mind that the API might change). There is a bunch of work do be done in the backend, too.

We don't have a firm date yet when this feature will land, but in the meantime, we're curious to hear what your use cases are - e.g. are you planning to send updates mostly to individual users (say, for tracking food deliveries or ride hailing), or larger groups of people (e.g. for sports events).

AristideVB commented 1 month ago

@peterfriese Our use case in our company is to send updates to individual users (such as for tracking food deliveries or ride hailing, electrical car recharge... ⚡️)

Looking forward for this update !

ostatnicky commented 1 month ago

@peterfriese Great news! My use case is for example this: I have a Pomodoro timer that's running on Live Activity. I need to refresh the activity every minute to update the progress bar.

eminsr commented 1 month ago

Hi Peter, Our use case is also sending updates to individual users. At least that is the case for the apps that awaits on the live activity implementation in our stack.

biene2020 commented 1 month ago

@peterfriese, thanks for the good news! My use case is to send push notification to specific live activity of an individual user (User A). In my use case, User A can start more than one live activities (triggered by specific timer activity started by the user); these timer activities are shared and synced to User B and can later be stopped by User B. When User B stops the timer activity in the app, the app also send push notification to end the respective live activity on device of User A (i.e. send push notification request from device to device). Looking forward to implement FCM soon. Cheers!

MrVermond commented 1 month ago

Hi @peterfriese , its awesome to hear that you started to work on that and of course its hard to come up with a timeline, but could you at least narrow it down, like this year or next decade?

astronaute77 commented 1 month ago

Our usecase is to send live notification to individual users as well. Please let us know when we can expect this, it's a pretty important feature. Let's try to have it ready before the next big update from Apple to avoid being stuck permanently two cycles behind.

biene2020 commented 1 month ago

For developers who wants this feature, it is listed by Paul in Firebase Feature Requests Portal for voting.