Communication between watch app and parent iphone app - ios

Requirement :My Watch app will show latest data from our server.
I tried :
To implement this thing I used
WKInterfaceController.openParentApplication(requestDict, reply: { (returnedObject, error) -> Void in
if (returnedObject != nil) {
//loading interface data here
}
})
In my app delegate function I used
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply {
// doing web service call using asynchronous nsurlconnection and replying with response dictionary
}
Problem :
Problem is that application is running fine when iPhone application is foreground but watch app not showing anything when iPhone application is running in background. I debugged it and found actually when iPhone application is running background then webservice api call(nsurlconnection) is not retuuning any data, when it's coming to foreground then it's replying data to watch app.
To solve it I used nsuserdafults to store data, but problem is that it's not always showing latest data. Let consider user opened watch app and it will go to parent application and returning old data from userdafults.
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply {
if ([userInfo[#"type"] isEqualToString:#"list"]) {
[self fetchWatchData];//it will get and store data when app will be foreground
NSDictionary *replyDict = [UtiltiyManager getWatchData];//data from userdefaults
if (replyDict) {
reply(replyDict);
}else {
NSDictionary *noDataDict = #{#"data":#"nodata"};
reply(noDataDict);
}
}
}
Problem is that watch app can't get latest data from iphone while it's in background. As there are no service call api which will work in background. I checked with NSURLConnection and NSURLSessionDataTask both are foreground api call.
Any solutions or thoughts?
Update 1 :
Apple Docs Says :
Types of Tasks Within a session, the NSURLSession class supports three
types of tasks: data tasks, download tasks, and upload tasks.
Data tasks send and receive data using NSData objects. Data tasks are
intended for short, often interactive requests from your app to a
server. Data tasks can return data to your app one piece at a time
after each piece of data is received, or all at once through a
completion handler. Because data tasks do not store the data to a
file, they are not supported in background sessions. Download tasks
retrieve data in the form of a file, and support background downloads
while the app is not running. Upload tasks send data (usually in the
form of a file), and support background uploads while the app is not
running.
Apple told data tasks is not available in background.And my data is small web service data that can be fetched using data task. so my service call is not download task. So in case of watch when iPhone app is background then how app will get web service data.
Should we use download task? But I guess it's intended to download any file.

You need to create a background task in the iPhone app otherwise the OS kills your app off before it can finish downloading the data. Here's some docs to help: https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html

Things have substantially changed since the question and answer posted previously. openParentApplication is no longer available in WatchOS 2. On the plus side, much more can now be achieved directly on the watch to update data from the server as required. Ideally, the iPhone app would also be caching for the WatchKit App Extension with the last cached data in the meantime via one of the new communication mechanisms now available, so that the WatchKit App has something to display until the latest data is downloaded, even if the iPhone app is not currently running.

Related

Save/Delete to HealthKit With WatchKit and Widget (Today Extension)?

Here is a question that I know has an answer since I see apps that do this functionality. I have tried (writing directly, using background fetch) but nothing works. I found an app currently on the app store with the functionality that I am looking for. With Background Fetch set to OFF and main app NOT running in background. I go to the Widget and add an item. I open HealthKit and I see the data there as expected.
I would like to do the same for my app. I would like my today extension (widget) and/or WatchKit extension to write to the HealthKit store even when app is not running in background.
Like I said I have tested an app that does this functionality even though in Apple documentation it says this:
The HealthKit store can only be accessed by an authorized app. You
cannot access HealthKit from extensions (like the Today view) or from
a WatchKit app.
Because the HealthKit store is encrypted, your app cannot read data
from the store when the phone is locked. This means your app may not
be able to access the store when it is launched in the background.
However, apps can still write data to the store, even when the phone
is locked. The store temporarily caches the data and saves it to the
encrypted store as soon as the phone is unlocked.
Any answers or insights are appreciated. Thanks everybody.
The Health Data Store is indeed encrypted while the device is locked. Locked is defined as requiring a passcode on the device and the screen was turned off (so a passcode or touch id is required before you can get back to the main screen). While the store is encrypted it is not possible to read any data from it, no matter if the app is running in the background or not. Even setting up observer queries while the app is running will not allow it to continue to be read from. I imagine this level of protection is done simply using the Data Protection capability with the NSFileProtectionComplete option.
What HealthKit functionality have you observed in this other app? If it was displaying step and distance data, then they are likely getting this data directly from the pedometer (CMPedometer), which is not restricted when the device is locked.
Lehn0058's comment about authorization was correct. I had to request authorization explicitly from the WatchKit and Today Extension even though authorization was already given in the app. Afterwards both are able to write to the Health Store. The comment from Apple above only has to do with Reading from the Health Store and NOT writing to the Health Store. Here is some sample code for anybody else who gets in to the same problem. Thanks again.
In WatchKit InterfaceController.m
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
// Configure interface objects here.
[[HealthKitManager sharedManager] requestHealthKitAccess];
}
In Today Extension TodayViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
[[HealthKitManager sharedManager] requestHealthKitAccess];
}

Frequent time interval background fetch made

I have developed two different applications
App1 - With Healthkit enabled.
App2 - ionic application
App1 task : Read data from healthkit which is store in the server.
App2 task : Retrieve the stored data from server and display.
I started App2 from App1 using openURLScheme. So App1 running on the background mode and also It should be continued more than 3 mins to an hour.
I tried following Scenario:
bgTask = self.applicationUI!.beginBackgroundTaskWithName("MyTask", expirationHandler: { () -> Void in
self.applicationUI!.endBackgroundTask(self.bgTask!)
self.bgTask = UIBackgroundTaskInvalid;
})
self.bgTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({ () -> Void in
self.monitorInBackground()
})
I get error : permittedBackgroundDuration: 180.000000 reason: finishTask
extent background process for next 3 minute (After IOS 7 introduce. before IOS 7, the process execution time was 10 minute).
Note :
I hope it can be feasible using APNS silent notification. But I expected better solution other than the APNS.
Apple has a good section on background execution in their documentation.
The two ways of doing this are a silent notification (as you suggest) and background fetch.
The "pro" of using a silent notification is that you can control when it happens fairly precisely as long as your user is online. (Which they probably have to be to access the server anyway.) But, yes, it adds a lot of complexity.
Background fetch works nicely, but you don't get much control over when it happens. This may or may not be a problem, depending on what your app does.
Other options that might work include background audio, location updates and VoIP, but they might get you rejected.
Just running a background task won't work -- that's designed for finishing off tasks rather than keeping them running for a long time.

iOS Newsstand download failed when shut down the app

I'm having difficulty in the download using NewsstandKit when the app shut down.
My newsstand app download does starts in Background Mode, and exit to the background or push a download notification, the download issue everything is OK, but i shut down the app then the task is downloading,the downloading task failed.
Does it has to do some thing with the Server? or others?
You need to resume your downloads when the App Launches again.
Something to the tune of this would work
// Inside App Delegate Did Finish Launching
NKLibrary *nkLib = [NKLibrary sharedLibrary];
for(NKAssetDownload *asset in [nkLib downloadingAssets]){
[asset downloadWithDelegate:newsstandDownloadDelegate];
}
If you read the documentation you will find the following paragraph detailing how you should handle app termination:
While assets are being downloaded, the application could be suspended
or even terminated entirely if, for instance, there is insufficient
memory or the user force-quits the application. The application
(assuming it has the newsstand-content property) is later relaunched
into the background to handle the completion of the download or any
authentication challenges or errors related to it. The procedure in
this case is the following:
When the application is launched, it can use the
UIApplicationLaunchOptionsNewsstandDownloadsKey key to access an array
in the launchOptions dictionary passed into the
application:didFinishLaunchingWithOptions:. If there is an array, it
contains the identifiers that caused the launch; these could be
identifiers for downloads that have finished downloading that or could
not complete downloading. It iterates through the array of
NKAssetDownload objects from the downloadingAssets property of the
NKLibrary object and calls downloadWithDelegate: on each of them. If
it wants, the application can use the asset identifiers obtained in
the previous step to check which asset downloads caused the relaunch.
The NSURLConnectionDownloadDelegate object handles the asset downloads
as it does normally. The Newsstand Kit framework expects all calls of
its methods to be made on the main thread; the NSURLConnectionDelegate
Protocol methods are also invoked on the main thread.

How to call web services in background using specific time interval?

i know that this questions may be repeated some times but i need some clarifications so i asked here.
My requirement is I got location using my iPhone every 20 sec and update my Web Application using the web services.It's also working on Background.
I know that i will got the location in background using the Background Fetch but i little confuse here.I want to update My web database every 20 sec using web services. is it possible to update Web database every 20 second using web service in Application Background mode?
Thanks in advance.
Try to use NSURLSession using its task you can do background upload and download.
After 1st request complete start timer which start the second request.
Good tutorial for NSURLSession is here..
tutsplus (its 4 part tutorial)
Here
And check the NSURLSession document here..
Its supported in iOS7+. But if user force close the application it will be stopped.
No. Minimal interval when your app "wakes up" in background mode is 6-10 minutes.
If your phone is active and unlocked. If your phone is "sleeping", this interval may be some hours.
In your project ->capabilities->background modes turn on "background fetch"
In your appDelegate
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
//Add your code here You will have 30 sec. to do all that you want in background mode
completionHandler(UIBackgroundFetchResultNewData); }

What is the proper way to handle background tasks in iOS

I have a voip app and it needs to run in the background. To my understanding these are the things I need to do:
Flag the app as voip.
Set the 'application does not run in background' flag to NO.
Set an expiration handler, a piece of code that extends the standard 10 minutes of execution time you get.
More?
I set both flags in the info.plist file and I get my 10 minutes. I tried what is suggested in this post. Here is my code:
//in didFinishLaunchingWithOptions:
expirationHandler = ^{
NSLog(#"ending background task");
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
NSLog(#"restarting background task");
bgTask = UIBackgroundTaskInvalid;
bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:expirationHandler];
NSLog(#"finished running background task");
};
//in applicationDidEnterBackground
NSLog(#"entering background mode");
bgTask = UIBackgroundTaskInvalid;
bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:expirationHandler];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// inform others to stop tasks, if you like
[[NSNotificationCenter defaultCenter] postNotificationName:#"MyApplicationEntersBackground" object:self];
//this while loop is just here for testing
inBackground = true;
while (inBackground) {
NSLog(#"stayin alive!!"); //this keeps going forever
sleep(10);
}
});
The situation:
I use a third party library that handles the communication with our webservice. The service is a CommuniGate pro server. I receive presence updates (online/offline) and instant messages from contacts via the library. The library is CommuniGate's ximss library, a protocol they made which is similar to xmpp and is used for xml-based sip requests, as well as IM and presence. When the user logs in to the app, he sees his contacts (CmmuniGate friends list) and he can choose to call one. After a ximss verification message has been sent and the other side accepted the call it logs the start time of the call and starts a facetime call.
The problem:
When the app enters the background by pressing the home button, I start seeing the 'stayin alive' message in the log and every ten minutes I see that it restarts the background task.
When the app enters the background by pressing the power button, the 'staying alive' messages start showing up for ten minutes, after that it restarts the background task and start restarting it about every 50-100 miliseconds.
I would've been fine with this for now, even it eats battery, because I have time to work on updates and our users don't own the ipads, we do. The problem for me now is that the ximss library loses it's connection (it is session-based). I could restart the session in the library, but this means quite a bit of data transfer to fetch the contacts list and some users use 3g.
I can't edit the library's source, nor can I see it, so I don't know if it creates the sockets the right way.
What do I have to do to handle both situations correctly? I don't even understand why there is a difference.
You cannot re-extend background tasks like this; your app is likely to be terminated. If this is working, it's because you have the background voip mode enabled, not because you are restarting the background task.
Once you have set the voip plist entry, iOS will attempt to keep your app alive as long as possible and restart it if it does get terminated. From Implementing a VoIP App:
Including the voip value in the UIBackgroundModes key lets the system
know that it should allow the app to run in the background as needed
to manage its network sockets. An app with this key is also relaunched
in the background immediately after system boot to ensure that the
VoIP services are always available.
In addition to setting this key, if you need to periodically run code to keep your voip connection alive, you can use the setKeepAliveTimeout:handler: method on UIApplication.
See also Tips for Developing a VoIP App:
There are several requirements for implementing a VoIP app:
Add the UIBackgroundModes key to your app’s Info.plist file. Set the value of this key to an array that includes the voip string.
Configure one of the app’s sockets for VoIP usage.
Before moving to the background, call the setKeepAliveTimeout:handler: method to install a handler to be
executed periodically. Your app can use this handler to maintain its
service connection.
Configure your audio session to handle transitions to and from active use.
To ensure a better user experience on iPhone, use the Core Telephony framework to adjust your behavior in relation to cell-based
phone calls; see Core Telephony Framework Reference.
To ensure good performance for your VoIP app, use the System Configuration framework to detect network changes and allow your app
to sleep as much as possible.
Almost all of the documentation you need is on the Apple developer site.

Resources