My app has a battery level indicator in it, and I would like to have it update while still on the battery level indicator page. Currently, if I keep my app open to that screen and the battery level changes (by more than 5%), the app crashes. What would I need to add to my code to do that? Here is my code:
- (void)viewDidLoad {
[super viewDidLoad];
deviceType.text = [[UIDevice currentDevice] model];
[[UIDevice currentDevice] setBatteryMonitoringEnabled:YES];
[[UIDevice currentDevice] batteryLevel];
// Enable monitoring of battery status
[[UIDevice currentDevice] setBatteryMonitoringEnabled:YES];
// Request to be notified when battery charge or state changes
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(batteryStatus) name:UIDeviceBatteryLevelDidChangeNotification object:nil];
}
- (void) viewWillAppear:(BOOL)animated {
UIDevice *device = [UIDevice currentDevice];
device.batteryMonitoringEnabled = YES;
LabelBatteryStatus.text = [NSString stringWithFormat:#"%.0f%%", device.batteryLevel * 100];
[device addObserver:self forKeyPath:#"batteryLevel" options:0x0 context:nil];
[super viewWillAppear:animated];
}
- (void) viewDidDisappear:(BOOL)animated {
UIDevice *device = [UIDevice currentDevice];
device.batteryMonitoringEnabled = NO;
[device removeObserver:self forKeyPath:#"batteryLevel"];
[super viewDidDisappear:animated];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
UIDevice *device = [UIDevice currentDevice];
if ([object isEqual:device] && [keyPath isEqual:#"batteryLevel"]) {
LabelBatteryStatus.text = [NSString stringWithFormat:#"%.0f%%", device.batteryLevel * 100];
}
}
This code works with my app when I load and unload the page, but I want it to work when on the page as well.
Thank you in advanced.
Related
I've tried to write my own module to detect is torch turned on/off.
According to documentation I've tried to run KVC as below
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == torchActiveObservationContext) {
AVCaptureDevice *thisDevice = (AVCaptureDevice*)object;
[self sendEventWithName:#"TorchEvent" body:#{#"isTorchActive": thisDevice.isTorchActive ? #"ACTIVE" : #"INACTIVE"}];
NSLog( #"Current torch level: %f", thisDevice.torchLevel);
}
else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
NSLog( #"ABCDEF");
}
}
-(id) init {
if (self = [super init]) {
NSLog( #"Start Initialization");
AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
[videoDevice addObserver:self forKeyPath:#"isTorchActive" options:NSKeyValueObservingOptionNew context:torchActiveObservationContext];
NSLog( #"End Initialization");
// whatever other initialization code ...
}
return self;
}
But I noticed that any change is recorded if i try to turn on the torch in Control Panel. So i tried to do it much easier and check the current torch state manually. I created simple method:
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(isTorchActive)
{
AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCapturePhotoSettings *photosettings = [AVCapturePhotoSettings photoSettings];
NSLog( videoDevice.isTorchActive ? #"on" : #"off");
NSLog( #"Level : %f", videoDevice.torchLevel);
return videoDevice.isTorchActive ? #"on" : #"off";
}
But it returns "off" all the time, even if torch is initially flashed. Torch level is 0.0.
What am I doing wrong?
Replace videoDevice.isTorchActive with videoDevice.torchMode == AVCaptureTorchModeOn If torch was previously activated from Control Center, you can get AVCaptureTorchModeOff, when running this code first time.
How to turn On Off Notificiation form app with using component UISwitch.
From setting if user turn On/Off Notification of any specific application UISwitch is turn On/Off using
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(applicationEnteredForeground:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
- (void)applicationEnteredForeground:(NSNotification *)notification {
NSLog(#"Application Entered Foreground");
[self notificationEnableDisable];
}
-(void)notificationEnableDisable{
NSString *iOSversion = [[UIDevice currentDevice] systemVersion];
NSString *prefix = [[iOSversion componentsSeparatedByString:#"."] firstObject];
float versionVal = [prefix floatValue];
if (versionVal >= 8)
{
if ([[UIApplication sharedApplication] currentUserNotificationSettings].types != UIUserNotificationTypeNone)
{
NSLog(#" Notification ON");
[self.switch_DailyNotification setOn:YES];
}
else
{
[self.switch_DailyNotification setOn:NO];
NSLog(#" Notification OFF");
}
}
else
{
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
if (types != UIRemoteNotificationTypeNone)
{
NSLog(#"Notification ON");
[self.switch_DailyNotification setOn:YES];
}
else
{
[self.switch_DailyNotification setOn:NO];
NSLog(#" Notification OFF");
}
}
}
This above code work fine when user turn On/Off Notification from IPhone setting.
How to implement from application to turn On/Off Notification which is in IPhone setting?
Note: This is for LocalNotification not for PushNotification!
You can't do that due to apple restrictions it doesn't matter if its local or push notification:
https://stackoverflow.com/a/10510610/8873550
I think my coding on done button is not working as i am changing my screen orientation when video is starting and when video is finished i need to come back to my normal orientation my coding is.
vid = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
//[self presentModalViewController:vid animated:YES];
[self presentMoviePlayerViewControllerAnimated:vid];
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(donebutton) name:MPMoviePlayerDidExitFullscreenNotification object:vid];
and then the coding done button method
-(void) donebutton{
NSLog(#"done");
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}
Hope this code will help you to change device orientation when a video playing is completed.
-(void)playVideo {
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
[moviePlayer setFullscreen:YES animated:YES];
}
- (void)moviePlayBackDidFinish:(NSNotification *)notification {
moviePlayer = [notification object];
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
// If the moviePlayer.view was added to full screen, it needs to be removed
moviePlayer.fullscreen = NO;
}
I've been trying to register my AVQueuePlayer items for KVO at the time of initializing. Below, the items in itemArray have all been properly created with URLs. After the code the queueList is added to a AVQueuePlayer. The player plays fine, with each item playing in order, but only observers for the first item trigger the response. The AVPlayerItemDidPlayToEnd works for all items, however.
I'm fairly new to KVO. Any help would be appreciated.
for(AVPlayerItem *i in itemArray)
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(nextSong)
name:AVPlayerItemDidPlayToEndTimeNotification object:i];
[i addObserver:self forKeyPath:#"status" options:0 context:nil];
[i addObserver:self forKeyPath:#"playbackBufferEmpty" options:0 context:nil];
[i addObserver:self forKeyPath:#"playbackLikelyToKeepUp" options:0 context:nil];
[queueList addObject:item];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
AVPlayerItem *thisItem = (AVPlayerItem *)object;
if ([keyPath isEqualToString:#"rate"]) {
if ([self.player rate]!=0) {
[self setPlayButtonAsPlaying:YES];
NSLog(#"PLAYING");
}
else {
[self setPlayButtonAsPlaying:NO];
NSLog(#"PAUSED");
}
}
else if ([keyPath isEqualToString:#"status"])
{
if(thisItem.status==AVPlayerItemStatusFailed)
{
NSLog(#"failed");
[self setPlayButtonAsPlaying:NO];
[player pause];
}
}
else if ([keyPath isEqualToString:#"playbackBufferEmpty"])
{
if(thisItem.playbackBufferEmpty)
{
[player pause];
[self setPlayButtonAsPlaying:NO];
}
}
else if ([keyPath isEqualToString:#"playbackLikelyToKeepUp"])
{
if(!thisItem.playbackLikelyToKeepUp)
{
[player pause];
[self setPlayButtonAsPlaying:NO];
}
else
{
[player play];
[self setPlayButtonAsPlaying:YES];
}
}
}
EDIT: I also have a button which triggers this command, which I use to test the state of these properties.
NSLog(player.currentItem.playbackBufferEmpty ? #"Yes" : #"No");
NSLog(player.currentItem.playbackLikelyToKeepUp ? #"Yes" : #"No");
Specifically, playbackLikelyToKeepUp is false (which I manually cause by disconnecting my wifi). Interestingly, the playBackBufferEmpty is also false.
- (IBAction)buttonPressed:(id)sender
{
UIDevice *device = [UIDevice currentDevice];
device.batteryMonitoringEnabled = YES;
if ([[UIDevice currentDevice] isMultitaskingSupported]) {
[self beingBackgroundUpdateTask];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(batteryChanged:) name:#"UIDeviceBatteryLevelDidChangeNotification" object:device];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(batteryChanged:) name:#"UIDeviceBatteryStateDidChangeNotification" object:device];
[self currentBatteryState];
}
- (void) beingBackgroundUpdateTask
{
self->backgroundUpdateTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundUpdateTask];
}];
}
- (void) endBackgroundUpdateTask
{
[[UIApplication sharedApplication] endBackgroundTask: self->backgroundUpdateTask];
self->backgroundUpdateTask = UIBackgroundTaskInvalid;
}
For some reason, the notification's are not being observed. Am i doing something wrong? I want to observe for unto 10 minutes when unplugged
You shouldn't be calling endBackgroundUpdateTask in your buttonPressed: method, since that cancels your background task. Try removing this code:
if ([[UIDevice currentDevice] isMultitaskingSupported]) {
[self endBackgroundUpdateTask];
}
Also, you should pass the UIDeviceBatteryLevelDidChangeNotification constant to the "name" parameter, not the string. It should look like this (note the lack of double quotes):
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(batteryChanged:) name:UIDeviceBatteryLevelDidChangeNotification object:device];
(It's also possible that UIDevice simply doesn't send those notifications in the background.)
Have you added the applicable backgrounding code to your AppDelegate? Here are backgrounding instructions in the iOS Programming Guide