WatchOS: how can i play sound when watch going on lock screen? - ios

I am developing apple watch application. my application working like every second it's notify sound and vibrate on my watch app.
Otherwise How can i stop watch from going to lock screen after 15 second?
My code is as follows.
- (void)willActivate {
[super willActivate];
soundAlert = [NSTimer scheduledTimerWithTimeInterval:1.2f target:self selector:#selector(SoundAlertNotification) userInfo:nil repeats:YES];
}
- (void)SoundAlertNotification
{
if (!isRechableFlag) {
[self playsound];
}
}
#pragma mark - Play Sound Methods -
- (void) playsound
{
[[WKInterfaceDevice currentDevice] playHaptic:WKHapticTypeRetry];
}
But when watch is going to lockscreen around 15 secode my sound method stop to call rather then it's work well.
What am I doing wrong?

This is a user preference setting, https://www.imore.com/how-keep-your-apple-watch-screen-longer
Otherwise you have to set your application up as a workout app to keep the screen from hibernating, but if it is not actually a workout app then it will get denied when you try to publish to the app store.

Related

iOS Screen recording detection

I tried to detect if screen capture is on for the application for iOS 11, to detect this the UIScreen.mainScreen.isCaptured property is used to check if it is recorded.
It works fine for the first launch, when the app is terminated and launched again, then the API returns NO though the screen capture is on.
Code:
//In viewWillAppear block
__block ViewController *weakSelf = self;
[NSTimer scheduledTimerWithTimeInterval:2.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
[weakSelf screenCaptureDetection];
}];
- (void) screenCaptureDetection {
if (#available(iOS 11.0, *)) {
for (UIScreen *screen in [UIScreen screens]) {
if([screen performSelector:#selector(isCaptured)]){
//Detected YES
}
}
}
Use case scenario:
Launch the app
Start screen recorder using the apple screen recording option
The screen recorder is detected
Terminate the app
Repeat the step 1 and 2
The screen recording is not detected, the API UIScreen.mainScreen.isCaptured returns NO
Please suggest
You should check for recording repeatedly.
I used this code and it worked for me.
check it out:
https://gist.github.com/abhimuralidharan/8db55dff9023028867b719f251372bd7#file-screenrecordingdetector-m

Unable to print out logs when app goes to background in test device

I am trying to implement certain app feature when app goes to background. But i saw a strange issue that if i do NSLog after every 2 seconds using NSTimer in "applicationDidEnterBackground", using simulator it works, but when i tested it in actual device, it doesn't print. Below is my code from "AppDelegate.m":
- (void)printLog
{
NSLog(#"logging after 2 sec.");
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
bckTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(printLog) userInfo:nil repeats:YES];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[bckTimer invalidate];
}
Please let me know why it's happening like this and may be any tips you would like to share while working with background app feature execution.
Thanks

How to re-trigger a process repeatedly in background in xcode

I'am working on an application in xcode-5, I need to upload some data in background mode, I need a set of code to be repeated till the device terminates the background process. I am able to do it once but I need to repeat again and again so that i can check the connectivity and perform the upload. I doing the same thing when the application comes in active mode.
Currently I'm using Timers with the following code :
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[bgrdTimer_ActiveMode invalidate];
bgrdTimer_ActiveMode=nil;
self.backgroundTask=[application beginBackgroundTaskWithExpirationHandler:^{
self.backgroundTask=UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
bgrdTimer_BackGroundMode=[NSTimer scheduledTimerWithTimeInterval:40.00 target:self selector:#selector(repeatUploadProcess_BackGroundMode) userInfo:nil repeats:YES];
});
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[bgrdTimer_BackGroundMode invalidate];
bgrdTimer_BackGroundMode=nil;
bgrdTimer_ActiveMode=[NSTimer scheduledTimerWithTimeInterval:40.00 target:self selector:#selector(repeatUploadProcess_ActiveMode) userInfo:nil repeats:YES];
}
repeatUploadProcess_ActiveMode and repeatUploadProcess_BackGroundMode are the methods containing the set of code which is suppose to be repeated
the problem is when I invalidate the bgrdTimer_ActiveMode the other timer dosn't gets invoked.
Have you enabled the background fetch mode? Click on the project target, and under the capabilities tab select "background fetch".
Theoretically you should also be setting [application endBackgroundTask:bgTask]. It sounds like you know, but if it never ends, iOS will end up killing your app.

How change UIImageView in external screen on background mode

I need show changes in external screen with UIImageView when my ios app is on background mode.
I use this code to change the UIImageView
campaingTimer = [NSTimer scheduledTimerWithTimeInterval:timeFirstAd target:self selector:#selector(changeImage) userInfo:nil repeats:NO];
This works when my app is active, but when in background, enters the changeImage method, but not change the picture.
NSTimer selectors are not guaranteed to fire off in the background. Unless you're registering for specific permissions, such as playing music in the background, and whatever you're actually doing in the background is directly related to the permission you asked for, you should work under the assumption you will not be able to execute code while the app is backgrounded, as that'll set you up to succeed much better than trying to find workarounds.
In this scenario, it seems like you want to change the image after so much time passes. That NSTimer you have (assuming your methods are written correctly) will work while the app is in the foreground, but to deal with background I recommend listening for the appDidEnterBackground and appWillEnterForeground and posting notifications (see sample code below).
AppDelegate.m
================
- (void)applicationDidEnterBackground:(UIApplication *)application
{
self.currentTime = [NSDate date];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationNameForBecameActive object:nil userInfo:#{kUserInfoForBecameActive: self.currentTime}];
}
================
ViewController.m
================
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didBecomeActive:) name:kNotificationNameForBecameActive object:nil];
}
- (void)didBecomeActive:(NSNotification *)notification
{
NSDate *sleepDate = notification.userInfo[kUserInfoForBecameActive];
NSTimeInterval secondsPassed = [[NSDate date] timeIntervalSinceDate:sleepDate];
if (secondsPassed >= timeFirstAd)
{
[self changeImage];
}
// reinitialize NSTimer
}
================
Alternatively, you could post notifications for both appDidEnterBackground and appWillEnterForeground and save the time there, along with invalidating your NSTimer and restarting it.

iOS reading data from server regularly

I need to create a iOS app where the app has to continuously check for the updates from the server(may be every 30 secs). But only when the app is running on the foreground.
I know this will drain the battery, but this will run on a environment where there's no internet. So we can't use push notifications.
Only option I can think of is sending a request to the server every 30 secs or so and get the updates. What is the best way to do this? Using NSTimer and NSURLConnection or any other better approaches?
Also if I use a timer, when the app goes to the background will it pause and will it start running as it comes to the foreground again? Is there a chance that app get killed while its on background?
Thanks
Using NSTimer and NSURLConnection or any other better approaches?
My first thought was also to use NSTimer and NSURLConnection.
Also if I use a timer, when the app goes to the background will it pause and will it start running as it comes to the foreground again?
Yes, it will. It doesn't exactly pause, but based on my testing in the simulator, the effect is similar. Let's say the timer is set to go off at 00:00:00, 00:00:30, 00:00:60, ... and you background the app at 00:00:15 and resume it at 00:00:45. The timer that was supposed to fire at 00:00:30 fires immediately when you resume (at 00:00:45), and the next firing (at 00:00:60) and subsequent firings are back on schedule.
Is there a chance that app get killed while its on background?
Yes, there is. But if you start the timer whenever the app launches, this shouldn't be a problem, right?
Your best bet is to setup a separate object that manages these operations on a background thread. Then in your app delegate, when
- (void)applicationWillResignActive:(UIApplication *)application
is called, have this special object stop all of it's synchronizing and clean up anything it needs to.
Then when:
- (void)applicationDidBecomeActive:(UIApplication *)application
gets called as the app gets active again, signal your object to query / poll on its background thread again.
Your custom object could have an interface like this
#interface PollingObject : NSObject
{
NSTimer* _timer;
NSUinteger _interval;
BOOL _cancel;
BOOL _isPolling;
dispatch_queue_t _pollQueue;
}
- (void)startPolling;
- (void)stopPolling;
#end
The implementation can be something like this:
#implementation PollingObject : NSObject
- (id)init
{
if (self = [super init])
{
_interval = 1; // 1 second interval
_cancel = NO; // default to NO
_isPolling = NO; // default to NO
// init your background queue
_pollQueue = dispatch_queue_create("com.yourconame.yourappname.pollQueue", NULL);
}
return self;
}
- (void)heartbeat
{
if (_cancel)
{
// stop the timer
[_timer invalidate];
_isPolling = NO;
return;
}
// Runs the polling method ONCE on a background queue
dispatch_async(_pollQueue, ^{
[self pollingMethod];
});
}
- (void)pollingMethod
{
// Do actual network polling work here...but only run it once. (don't loop)
}
- (void)startPolling
{
_cancel = NO;
if (_isPolling)
{
NSLog(#"Already polling");
return;
}
// schedule the method heartbeat to run every second
_timer = [NSTimer scheduledTimerWithTimeInterval:_interval target:self selector:#selector(heartbeat) userInfo:nil repeats:YES];
}
- (void)stopPolling
{
// we set the flag here and the next second the heartbeat will stop the timer
_cancel = YES;
}
#end
Look at Rocket real-time networking which looks easy to setup through AFNetworking 2.0.
https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-2.0-Migration-Guide
See the last part of this wiki. I have not used it but it would be something I would try if I had your requirements.

Resources