RemotePlaybackClient resume session on Chromecast - sessionid

I am trying to use the RemotePlaybackClient to resume a Chromecast session created by the same Android app. I'm able to use this RPC vs the full Cast SDK to play, pause, resume, seek, and stop playback on the Chromecast device. My current test is in closing the Android app and using the sessionId from the session to try to reload the app and resume control of the playback. Upon closing the Android app, we are not terminating playback or the session, it keeps going.
Here is the code I'm using:
// attempt resume
mRemotePlaybackClient = new RemotePlaybackClient(getApplicationContext(), ccRoute);
// ccRoute is the selected ChromeCast RouteInfo device - same as previous
System.out.println(mRemotePlaybackClient.isSessionManagementSupported()); // true
System.out.println(mRemotePlaybackClient.hasSession()); // false
mRemotePlaybackClient.setSessionId(saved_sessionId); // saved_sessionId is the sessionId saved from the mRemotePlaybackClient.play command in success reply.
System.out.println(mRemotePlaybackClient.hasSession()); // true
mRemotePlaybackClient.startSession(null, ccStart); // callback returns error 0
mRemotePlaybackClient.setStatusCallback(ccSessionStatus); // callback returns error 0
I've asked some others familiar with the RemotePlaybackClient and the Chromecast, including those within Google but did not get an answer. Also, I seem to be seeing some of the same issues #Commonsware is seeing in that some callbacks don't reply at all. In addition, with images, metadata is not returned and the status callback returns an error whereas video returns ok (position info etc).
Really, I'd just like to resume the session for now vs having to wire up the full Cast SDK.

Related

ProgressNotification callback not triggered without an initial download in Realm 10

We are using MongoDB Realm in our app.
The first time the user is connected to the app, the ProgressNotifcation callback is triggered correctly, and it will work and trigger whenever a new download is coming.
Even if no download is pending, the ProgressNotification callback will be triggered (the Progress object pass in the callback will contain values from the last download) at least once(when creating it). I supposed this is due to the fact that we are downloading the first data set of the user.
But after killing the app and launching it again, the ProgressNotification callback is not triggered anymore until new data are received by the app. And from this point, the callback will be called every time we need it.
It seems that now, the framework needs a first download since the app is launch to make ProgressNotification callback to be triggered every time we need it.
This was working in the previous version of Realm (5.X.X). We just finished the migration to Realm 10 and discover this issue.
I am a bit stuck here, do not know if this is an intended change or a bug on my part. But I am pretty sure this was working in the previous version of the SDK.
Can anyone help me with this? Thanks
Note: this is no more working in both mode : .forCurrentlyOutstandingWork and .reportIndefinitely
Example
self.token = syncSession.addProgressNotification(for: .download, mode: .forCurrentlyOutstandingWork) { progress in
.......Some code........ <- this part of the code is not triggered anymore
}
EDIT - 21/12/2020
For clarification, the token returned contains a value and the .invalidate is not being called.
There is no error in the session and any new download is triggering the callback. After an initial download, everything works as expected. This means that when I add a progressNotifcation later on, the callback is triggered immediately with the progress of the previous download. But if there is not an initial download, the callback is never called.
For the scope, this method is actually in the custom publisher that I created and it is not deallocated.
Realm 10.5.0
iOS 14.3

Firestore Timeout [duplicate]

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

Android BLE - BT stack alarm errors

I'm trying to get basic Bluetooth LE connections working in my app, but I'm running into problems. I have a couple of sensors that I can connect to just fine with the iOS version of this app, but I simply cannot connect to them with the Android version. The only thing I seem to be able to connect to is a beacon I've set to configuration mode.
After checking my ADB logs again, I noticed that whenever it fails to connect to a device, there's always four calls to bt_osi_alarm and bta_gattc_conn_cback. I'm wondering how to interpret this.
An unsuccessful connection attempt:
D/BluetoothGatt(17824): connect() - device: 00:17:E9:C0:86:14, auto: false
E/bt_osi_alarm(14357): reschedule_root_alarm alarm expiration too close for posix timers, switching to guns
...
E/bt_osi_alarm(14357): reschedule_root_alarm alarm expiration too close for posix timers, switching to guns
E/bt_osi_alarm(14357): reschedule_root_alarm alarm expiration too close for posix timers, switching to guns
E/bt_osi_alarm(14357): reschedule_root_alarm alarm expiration too close for posix timers, switching to guns
...
W/bt_btif (14357): bta_gattc_conn_cback() - cif=3 connected=0 conn_id=3 reason=0x0002
W/bt_btif (14357): bta_gattc_conn_cback() - cif=4 connected=0 conn_id=4 reason=0x0002
W/bt_btif (14357): bta_gattc_conn_cback() - cif=5 connected=0 conn_id=5 reason=0x0002
W/bt_btif (14357): bta_gattc_conn_cback() - cif=6 connected=0 conn_id=6 reason=0x0002
D/BtGatt.GattService(14357): onConnected() - clientIf=6, connId=0, address=00:17:E9:C0:86:14
D/BluetoothGatt(17824): onClientConnectionState() - status=133 clientIf=6 device=00:17:E9:C0:86:14
I/mono-stdout(17824): BLEAdapter.OnConnectionStateChange()
I/mono-stdout(17824): Gatt disconnected!
A successful connection attempt to one of those beacons does not have these sets of four bt_osi_alarm and bta_gattc_conn_cback errors. Preferably if someone knows the Android source well, hopefully they can tell me what's going on. It's a long shot I know, but I'm kinda out of options. Thanks.
Some additional information might help the community debug this issue for you. Please add the following to your original question:
Make/Model/Revision of all BLE devices that you've tested and whether or not each one works
Specific android device you have tested with
The error your app gets and at what step it fails
Are you able to get a BluetoothDevice
Does it fail when calling connectGatt()
Is your app written in java/android studio, or is this some kind of universal app that runs on both iOS and Android?
In my experience, alarm expiration too close for posix timers, switching to guns, isn't as serious as its error level suggests. On my nexus 7/marshmallow device, I see this message constantly while connected to a bluetooth device (serial profile, not BLE) so I don't think this is a bug.
I suggest checking up on the BLE device manufacturer to see if there are any firmware upgrades for them too.
More details on alarm expiration too close for posix timers, switching to guns
What's happening is some part of the android bt code is setting a very short timer. So short, that it expires before the app can measure it.
The error, alarm expiration too close for posix timers, switching to guns, was added to android source in a commit 081e4b67b44a5fd397c2d79a5566e11ae52d4aca
The commit message gives us more background on what is happening.
Ensure alarms are called back when they expire in the past
Turns out the posix timers we're dealing with aren't well behaved.
If the timer is TIMER_ABSTIME the following is supposed to be true:
"If the specified time has already passed, the function shall succeed
and the expiration notification shall be made."
But alas, this is not the case. If the expiration time happens to be
in the past (e.g. very short timer which gets hit with a context
switch before the timer can be set) the timer decides to disarm
itself. This means no more callbacks happen, and no more alarms are
processed ever.
sadness.
But thankfully, we can use timer_gettime to check the state of the
timer after timer_settime. If timer_gettime tells us the timer is
disarmed right after we armed it, we want to perform the alarm
callback ourselves.
Put all timer callbacks on the same thread (as would be the case in
the underlying timer implementation already) and used a sempahore to
signal when an alarm expires in the normal posix timer callback and
also in the timer didn't set case.
The code also includes the following comments
If next expiration was in the past (e.g. short timer that got context
switched) then the timer might have diarmed itself. Detect this case
and work around it by manually signalling the |alarm_expired|
semaphore.
It is possible that the timer was actually super short (a few
milliseconds) and the timer expired normally before we called
|timer_gettime|. Worst case, |alarm_expired| is signaled twice for
that alarm. Nothing bad should happen in that case though since the
callback dispatch function checks to make sure the timer at the head
of the list actually expired.

watchOS1 - When notification arrives, first InterfaceController loads too

Every time the Watch receives a notification (let's say local), either the static long look or the dynamic long look interface is loaded.
However, what I am observing is that every time the corresponding watch app's first interface controller is also getting loaded.
Is it something that other people have also observed?
Every time the Watch receives a notification, the watch app's first interface controller also gets run behind the scenes.
If it really does, how to distinguish when the watch app ran because user opened it and when it ran because there was a notification that came? context in awakeWithContext: is null in both cases.
Yes, I noticed too. It also seems it is in charge to handle the action methods for for local and remote Notification when tap on a button:
handleActionWithIdentifier:forLocalNotification:
I think you can use:
didReceiveRemoteNotification:withCompletion:
or
didReceiveLocalNotification::withCompletion:
to detect when your app is populated from a remote or local notification
As of watchOS 3 you can out exit of awake(withContext:) early in this scenario by inspecting the applicationState of your extension:
override func awake(withContext context: Any?) {
if #available(watchOS 3.0, *) {
if WKExtension.shared().applicationState == .background {
print("Awake with Context in background. Not processing.")
return
}
}
// otherwise, load normally
}

HKWorkoutSession isn't keeping app at front of Apple Watch

It has been stated that an app running a HKWorkoutSession will have special privileges over other watchOS 2 apps, so when a user looks at their Apple Watch, it will go to the view showing running a workout rather than the watch face.
Currently, on both my device and simulator, this is not the case. If I start a HKWorkoutSession and then leave for 5 minutes and then interact with either the Apple Watch, or the Watch Simulator, it presents the watch face.
If I then open my app, it appears to have been frozen, rather than terminated (which is what I imagine happens to other apps). As the UI will update when I need receive a response in my query.updateHandler. Also if I set it to provide haptic feedback every time my query.updateHandler receives a new HKQuantitySample it will do so, so the app must be running in the background in some form.
Has anyone else noticed this behaviour, and am I doing anything wrong, or expecting something I shouldn't?
Here is how I start my HKWorkoutSession:
self.workoutSession = HKWorkoutSession(activityType: HKWorkoutActivityType.Other, locationType: HKWorkoutSessionLocationType.Indoor)
self.healthStore.startWorkoutSession(self.workoutSession) {
success, error in
if error != nil {
print("startWorkoutSession \(error)\n")
self.printLabel.setText("startWorkoutSession \(error)")
self.printLabel.setTextColor(UIColor.redColor())
}
We're seeing that too, for the moment we've made sure 'opens last activity' is configured.
When the UI is active we start a dispatch_timer to request and process data in 1 second intervals.
Make sure you do any significant processing using the NSUserProcessInfo method though and pause the dispatch_timers whenever you are no longer active. You'll get crashes otherwise.

Resources