Prevent Apple Watch Turning Off - Private API - watchkit

Is there any known way to keep the Apple Watch screen on by using a private API?
My app is unlikely to be submitted to the App Store so private API usage doesn't matter. Really need to be able to keep the screen on and stop it from sleeping when wrist is lowered in app.

No, it is not possible to prevent this.
The only thing you can do is prolong the shut off time to 70 seconds. You can do that in Setting -> General -> Wake Screen. But that's probably not enough for your purpose.

Related

android - Background service

I am writing android application which will request the data from the server after every 5 minutes and will load it into the sqlite. Later on, the data from the sqlite will be displayed to the user whenever he wants to view the data. Database will contain only the data up to last 2 days and will keep deleting the older data.
I want to achieve all this functionality using Firebase JobScheduler. But before writing, I want to know if it is the right tool to go for? Is there a better way to achieve this functionality? Or any recommended way?
Thanks in advance.
Your implementation plan sounds OK to me. But I think synchronizing every 5 minutes is excessive and will cause problems for your users from constant battery drain and network usage.
You implementation is right but there is a huge drawback in this mechanism i.e. battery drainage. I think the best mechanism would be if you implement that functionality on server end.
Server checks that if there is any change in the database
If it finds any change then you just need to push the specific updated data to your mobile agent.
Advantage:
1. You dont need to worry about the battery on mobile agent
2. All the hard work and calculation is done on server end.
Enjoy !!

Need Firebase Database behaviour clarification when inside a Service

I am testing a feature which requires a Firebase database write to happen at midnight everyday. Now it is possible that at this particular time, the client app might not be connected to the internet.
I have been using Firebase with persistence off as that can potentially cause issues of stale data in another feature of mine.
From my observation, if I disconnect the app before the write and keep it this way for a minute or so, Firebase eventually reconnects when I turn on the connectivity again and performs the write.
My main questions are:
Will this behaviour be consistent even if the connectivity is lost for quite a few hours?
Will Firebase timeout?
Since it is inside a forever running service, does it still need persistence to ensure that writes are not lost? (assume that the service does not restart).
If the service does restart, will the writes get lost?
I have some experience with this exact case, and I actually do NOT recommend the use of a background service for managing your Firebase requests. In fact, I wouldn't recommend managing Firebase requests at all (explained later).
Services, even though we can make them run forever, tend to get killed by the system quite a lot actually (unless you set their CPU priority to a higher level, but even then the system still might kill them).
If you call a Firebase Write call (of any kind), and your service gets killed, the write will get lost as you said. Unless, you create a sophisticated manager in which you store requests that haven't been committed into your internal storage, and load them up each time the service is restarted - but that is a very dirty work to do, considering the fact that Firebase Developers took care of us and made .setPersistenceEnabled(true) :)
I know, you mentioned you don't want to use it, but I STRONGLY advise you to do so. It works like charm, no services required, and you don't have to worry at all about managing your write requests. Perhaps it would be better to solve the other issue you have in order to make this possible.
To sum up, here's what I would do in your case:
I would call the .setPersistenceEnabled(true) someplace at the beginning (extending the Application class and calling it from onCreate() is recommended)
I would use Android's AlarmManager and register a BroadcastReceiver to receive an alarm at midnight (repetitive or not - you decide)
Inside the BroadcastReceiver, I'd simply call a write function of Firebase and worry about nothing :)
To make sure I covered all of your questions:
will this behaviour be consistent....
No. Case-scenario: Midnight time, your service has successfully received the call and is now trying to write into Firebase. If, for example, the user has no connection until 6 AM (just a case scenario), there is a very high chance that the system will kill it during those 6 hours, and your write will get lost. Flight Time, or staying in an area with no internet coverage - both are examples of risky scenarios that could break your app's consistency
Will Firebase Timeout?
It definitely could, as mentioned. I wouldn't take the risk and make a 80-90% working app. Use persistence and have a 100% working app :)
I believe I covered the rest of the questions..
Good luck!

How to update Watch Complication only when the watch is awake, to not use up the daily budget

I have a server that keeps 2 booleans. These booleans change every 15 seconds.
Whenever I wake my Apple Watch, I want the complication to show the current state. How can I do it withough exhausting the budget early on?
The best way would be to fetch the newest state into the complication whenever I wake my watch. The only possible way I see would be to poll the server (either directly or via my phone) every 15 seconds. The problem is that I'd soon use up all the allotted time.
It would be great if I could make the complication only update when the watch was woken up. Can that be done?
Is there a way to not fetch data unless you need it?
No.
By "waking the watch," you're speaking of activating the watch either by interacting with it, or by raising your wrist. Regardless of the manner, the watch can either wake to the watch face, or to the last activity (which is controlled by the Wake Screen setting).
If it wakes to the watch face, this is independent of your app, watch extension, or complication controller. There is no notification you can use to handle that scenario.
If it wakes to an activity, it may not be your activity. If it were your activity, all you could do would be to stop updating when your watch app was active.
Either way, there is no contingency to only update the complication when the watch is awake.
If you think about what you're asking, it runs contrary to Apple's guidelines, as users expect to glance at the watch face and already see current complication data. The system expects you to provide updates when the watch is not awake, so the information will be immediately visible when the watch does wake.
Updating Complication Data
Of the available update approaches, these won't handle your requirements:
PKPushTypeComplication push notifications
This would be ideal, if you were not updating frequently and constantly throughout the day.
Apple applies a daily limit to the number of pushes of this type that you send from your server. If you exceed the limit, subsequent pushes are not delivered.
Scheduled automatic updates
The issue here is that the minimum scheduled update interval is 10 minutes, so you wouldn't have current complication info for the remaining 9-3/4 minutes.
Scheduled updates are useful for apps whose data changes at predictable times. When a scheduled update occurs, ClockKit calls the requestedUpdateDidBegin or requestedUpdateBudgetExhausted method of your data source first.
These approaches might handle your requirements, but you'd have to try them and determine which one meets your needs.
Watch extension + background NSURLSession
This may place more of a drain on battery, but it would work even if not in range of the phone.
Manual update via WCSession transferCurrentComplicationUserInfo
If you're in range of your phone, the more likely approach would be for your phone to (always) poll your server, then provide constant updates.
When your iOS app receives updated data intended for your complication, it can use the Watch Connectivity framework to update your complication right away. The transferCurrentComplicationUserInfo: method of WCSession sends a high priority message to your WatchKit extension, waking it up as needed to deliver the data. Upon receiving the data, extend or reload your timeline as needed to force ClockKit to request the new data from your data source.
Note that complication transfers are budgeted in iOS 10. This approach would not work if you were performing large numbers of updates per day.
Having said all that, an alternate approach would be to monitor these booleans on the server side, and only send out a notification if there was a problem or change. You didn't explain exactly what these booleans indicate, but there are other approaches for monitoring, which would avoid you having to constantly poll a server (from your phone or watch).
If that's not an option, you really should consider either viewing the server data on your phone, or switching to a far less frequent update interval for your complication. Apple discourages such frequent updates, and even their own (stock or weather) complications are not updating several times a minute.
Update:
What if I only wanted to update the complication when user requested it himself(=clicked the complication)? He is not really interested in the state all the time.
Can you (only) update a complication when the watch awakes? No.
Can you update an extension when the extension awakes? Yes.
The user needs to consider what a complication is meant to be. It's designed to be regularly updated to show current information. There's no mechanism to not update the complication because the user is mostly not interested in knowing the state.
Could you tap on a complication to open its app? Yes. But the complication itself would be showing stale data, and the user would have to do more than raise their wrist to see current state.
If you consider what the user is asking, they're not describing a complication (which shows current state), but a way to see the current state when they request it.
That mechanism is different from a complication. They're really describing a Glance (or an app) which the user swipes up (or opens) to see.
If they want live updates, it can be done via WCSession updateApplicationContext.
Use the updateApplicationContext:error: method to communicate recent state information to the counterpart. When the counterpart wakes, it can use this information to update its own state. Sending a new dictionary with this method overwrites the previous dictionary.
The way that works is your phone sends background updates to the watch. The watch stores the most recent update, which will be available to it when your app or Glance wakes up. The user views the app or Glance, and it displays the most recent value which the watch stored. While open, it continues to update itself as new updates arrive. While closed (e.g., inactive, asleep), the watch stores the most recent update on behalf of your app or glance.
If the user doesn't need the app or glance to update itself every 15 seconds, then you wouldn't need to poll, and you could simply use a NSURLSession to fetch the current state when the extension awakes.
If you explain to the user that there's no way to update a complication when the user raises their wrist, and that they don't care about knowing the state all the time (which a complication is meant to do), then show them what a Glance can do, you'll find it far easier to accomplish what the user seems to want, ideally without unnecessarily draining the battery.

HKWorkoutSession not resuming custom workout app if screen gets locked or active app changed

I have a watchOS 2 app that displays health data during a run. I start a workout using HKWorkoutSession as follows:
self.workoutSession = HKWorkoutSession(activityType: .Running, locationType: .Outdoor)
self.workoutSession!.delegate = self;
self.healthStore.startWorkoutSession(self.workoutSession!)
This keeps my app in the foreground when the screen shuts off for a while and the user looks at it again later.
Now lets say during the workout the user switches to a different app OR the watch screen locks (due to the watch not being secured tight enough) and then the user re-launches my running app by double clicking the digital crown. The app resumes where it left off and continues to get health data as expected, but my app won't stay in the foreground anymore. The workout is still in progress because on the watch face I can still see the workout icon at the top, and the heart rate monitor continues to collect heart rate data, but the app refuses to stay in the foreground.
Does anyone have any idea on how to have a workout app resume to the foreground during a workout even if the screen locks or a user switches to a different app?
I contacted Apple using one of my 2 yearly technical support requests. According to the representative I talked to, he believes this is a bug in watchOS. I had submitted this as a bug report way back in October, but the ticket has gotten no response so I thought I was perhaps missing something. I guess we are stuck with how this works for the time being.

Can I use blocking API on WinRT?

We are planning to use sqlite pcl library for WinRT store app using this project: https://sqlitepcl.codeplex.com/ . All the api is blocking. Will there be a problem during app store review by Microsoft, if we use it?
Of course the api will be wrapped in Task.Run, somethin glike:
public Task InsertTestSetForUser(TestItem testItem, long userid)
{
return Task.Run(() => InsertTestSetForUserInternal(testItem, userid));
}
I knwo that there is an impl of sqlite with async API, but that would not be portable out of the box for Xamarin, which we use for porting to iOS and Android.
There are a few requirements your app has to meet. The three most important ones regarding your question (imho) are these:
Your app has 5 seconds to start on the splash screen. If your database setup takes longer, consider using an extended splash screen or a background task.
The app must render the first screen or a splash screen within 5
seconds after launch.
Your app must be responsive within 20 seconds (which is basically 5 + 15 seconds).
Within 20 seconds after launch, the app must be responsive to user
input.
If there is an operation on the UI that takes more than 3 seconds to process, you have to use some kind of status indicator (e.g.: an indeterminate progress bar).
If an app performs an operation that causes the device to appear to be
unresponsive for more than three seconds, such as downloading data
over a network connection or transitioning between a screen or page,
the app must display a visual progress or busy indicator.
So you see: There is no definition what blocking really means in the certification process. Just be sure to use Tasks for long operations that are triggered from the UI and display some kind of process / status to the user when the operation takes longer than expected. As long as your app stays responsive it will not fail certification (passing the WACK test is important, though).
For more information see: http://msdn.microsoft.com/en-us/library/windows/apps/hh184840(v=vs.105).aspx

Resources