can you handle the callback with timecode after playback completion or stopped by user? - actions-on-google

I would like to catch the hook "actions.intent.MEDIA_STATUS" with the timecode when the user stopped the playback streaming.
the status return by this callback is only when failed or finished (https://developers.google.com/actions/reference/rest/Shared.Types/Status)
https://developers.google.com/actions/assistant/responses#handling_callback_after_playback_completion
do you think that is possible to catch the timecode media ?

There is no reliable way to do this. As you note, the event sent does not contain the timecode where it stopped, or even the cause of why it stopped (did the user stop it or did it end). Other Intents may be triggered with the user requesting an action, and you won't even get the MEDIA_STATUS event.
You can get a very rough idea of where the user stopped by including the media start time in a context or in session data when you first send the reply. When you get the next message, you can compare the time that you previously saved with the current time. This is very imperfect, however, since it doesn't account for network latency or the user pausing and resuming the audio during playback.

Related

Why isn't my firebase listener firing when the app is offline and initialized offline

I've setup a listener on my database that is only failing to respond in a weird offline scenario.
On setup I'm adding a listener to a database that should fire anytime there's an update...
let mySpots = self.databaseRefSpots.child("users").child(globalMasterUser.userUID).child("type").observe(.value, with: { snapshot in
//code that should be executed when there's an update.
Once the user takes some action that should get saved, it's saved to the firebase database using...
annotationdb.child("type").setValue("Feature")
annotationdb.child("properties").setValue(propDict)
annotationdb.child("geometry").setValue(["type":"Point"])
annotationdb.child("geometry").child("coordinates").setValue(coordinates)
This code works whenever the user is online, and when a user starts the app online and goes offline.
But, if the listener is created when the app is initialized in an offline state, it looks like the listener is setup successfully, but after my setValue's are called, the listener isn't called. If I turn the data connection on, at that point my listeners are called with the values I set with setValue.
Any idea why the listeners aren't firing in this offline state?
I've tried stepping through the firebase code to see if the listener is getting hit and it's not. I've tried creating separate listeners to catch this scenario and they wont fire either.

What does HTMLMediaElement suspend event mean?

In MDN it says "The suspend event is fired when media data loading has been suspended." But what does this actually mean? What are some examples for this event. I'm especially interested in the context of an audio stream.
docs: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/suspend_event
The suspend event occurs when the browser is intentionally not getting media data. This event is triggered when the loading of the media is suspended, suspended means when the download of a media has been completed, or it has been paused for some other reasons

Error handling in firebase-database connection

I am trying to check for errors while the app is trying to connect to the firebase-realtime-database.
My main concern is when the user fires up the app for the first time, but with no internet connection. I create the ref to the database and try to observe a single event, but the console log starts to throw error messages and none of them is captured by my code.
//------- variable declaration
var ref:DatabaseReference?
//------- inside de method
ref = Database.database().reference(withPath: "myPath")
ref?.observeSingleEvent(of: .value, with: { (snapshot) in
//I cannot even fire up the observer, so I never get here
}){(error) in
//no error is captured here also
}
Even if I comment or delete the observeSingleEvent I can see the errors getting thrown in the console, but I would like to capture them.
Does anyone know how to do that?
Thanks in advance
It is not an "error" to be offline at the time of a query. The SDK will continue trying to make the request for as along as your app is running and your code has an observer attached at that location.
If you want to detect the connection state, you can attach an observer at /.info/connected to get a callback that indicates the current state of the connection. Note that this information might be out of date, as a stalled connection doesn't immediately become fully disconnected until after a while.

How to detect absent network connection when setting Firestore document

We are building a real-time chat app using Firestore. We need to handle a situation when Internet connection is absent. Basic message sending code looks like this
let newMsgRef = database.document(“/users/\(userId)/messages/\(docId)“)
newMsgRef.setData(payload) { err in
if let error = err {
// handle error
} else {
// handle OK
}
}
When device is connected, everything is working OK. When device is not connected, the callback is not called, and we don't get the error status.
When device goes back online, the record appears in the database and callback triggers, however this solution is not acceptable for us, because in the meantime application could have been terminated and then we will never get the callback and be able to set the status of the message as sent.
We thought that disabling offline persistence (which is on by default) would make it trigger the failure callback immediately, but unexpectedly - it does not.
We also tried to add a timeout after which the send operation would be considered failed, but there is no way to cancel message delivery when the device is back online, as Firestore uses its queue, and that causes more confusion because message is delivered on receiver’s side, while I can’t handle that on sender’s side.
If we could decrease the timeout - it could be a good solution - we would quickly get a success/failure state, but Firebase doesn’t provide such a setting.
A built-in offline cache could be another option, I could treat all writes as successful and rely on Firestore sync mechanism, but if the application was terminated during the offline, message is not delivered.
Ultimately we need a consistent feedback mechanism which would trigger a callback, or provide a way to monitor the message in the queue etc. - so we know for sure that the message has or has not been sent, and when that happened.
The completion callbacks for Firestore are only called when the data has been written (or rejected) on the server. There is no callback for when there is no network connection, as this is considered a normal condition for the Firestore SDK.
Your best option is to detect whether there is a network connection in another way, and then update your UI accordingly. Some relevant search results:
Check for internet connection with Swift
How to check for an active Internet connection on iOS or macOS?
Check for internet connection availability in Swift
As an alternatively, you can check use Firestore's built-in metadata to determine whether messages have been delivered. As shown in the documentation on events for local changes:
Retrieved documents have a metadata.hasPendingWrites property that indicates whether the document has local changes that haven't been written to the backend yet. You can use this property to determine the source of events received by your snapshot listener:
db.collection("cities").document("SF")
.addSnapshotListener { documentSnapshot, error in
guard let document = documentSnapshot else {
print("Error fetching document: \(error!)")
return
}
let source = document.metadata.hasPendingWrites ? "Local" : "Server"
print("\(source) data: \(document.data() ?? [:])")
}
With this you can also show the message correctly in the UI

How to synchronize backend timer with mobile app

I am developing a app that chooses a user and has a 15 sec. timer for that user to respond. The user app queries the db every 5 sec to see if that user is chosen. If so The mobile app begins a 15 sec. timer. The problem is that the timers will never match up because the user app can be on a different timer cycle that the backend and can query the db at a later time. I use Angular, NodeJS, and expressJS + MongoDB to develop this app.
any suggestion on how I can get the timers to be synchronized?
You don't need to have two timers running at the same time. Start a timer on the front-end, then let the back-end know when the timer on the front-end started. As long as you treat one side as the single source of truth, the other side will be able to infer whether the timer has finished or not.
Although the timers might not be synchronized, time should be the same everywhere. If the back-end knows that the front-end timer started at 12:01:00, it also knows that the timer will end at 12:01:15. In this way, it can just continue to check whether the current time is before or after 12:01:15.
This is definitely a job for websockets! Websockets unlike HTTP enable two way data flow so your server and client can talk in real-time. Socket.io is a really popular framework for enabling this type of interaction and hooks really seamlessly into node/express.
http://socket.io/
Here is a tutorial to get your started http://socket.io/get-started/chat/.
The basic flow will be
Open a socket between the user and the server.
When the user is chosen (I assume on the server-side) then do a io.emit('user chosen', { userId: '<the user id>' });. This will send a message over the socket to all attached applications.
Start the timer on the server and send info that the period is over. Something like this should work. setTimeout(() => socket.emit('user chosen end', { userId: '<the user id>' }), 15000);
In your app you will be listening for the 'user_chosen' event and can check if the logged in user has the same id as the one sent over the socket. If the user id's match enable the text input for the user to set the input. Something like this: socket.on('user chosen', function(msg){ /* Enable the input */ });
The app will also be listening for the 'user_chosen_end' event and if the ids of the user again match, disable the text input or do whatever else you need to do. Again this will look like: socket.on('user chosen end', function(msg){ /* Disable the input & do anything else */ });
Hope this helps :)