Wednesday, March 3, 2010

Battery Information using iPhone's Cocoa Touch

I have done something similar (although on a smaller scale) to this but for the Android platform. For the iPhone platform, the main class used is UIDevice. Below is the header used:
#import <UIKit/UIKit.h>


@interface BatteryInformationViewController : UIViewController {
    IBOutlet UITextView *batteryLevel;
    IBOutlet UITextView *chargingState;
    // Used to format the battery level
    NSNumberFormatter *numberFormatter; 
}

@property (nonatomic, retain) UITextView *batteryLevel;
@property (nonatomic, retain) UITextView *chargingState;
@property (nonatomic, retain, readonly) NSNumberFormatter *numberFormatter;

@end 
There are two UI elements (text views), namely the battery level and the battery charging state. The corresponding implementation file is next:
#import "BatteryInformationViewController.h"

@interface BatteryInformationViewController ()

- (void)displayBatteryLevel;
- (void)displayBatteryStatus;

@end

@implementation BatteryInformationViewController

@synthesize batteryLevel, chargingState;


- (NSNumberFormatter *)numberFormatter
{
    if (numberFormatter == nil)
    {
        // Used for formatting the battery level
        numberFormatter = [[NSNumberFormatter alloc] init];
        [numberFormatter setNumberStyle:NSNumberFormatterPercentStyle];
        [numberFormatter setMaximumFractionDigits:1];
    }
    return numberFormatter;
}

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
    
    // Register for battery level and state change notifications.
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(batteryLevelDidChange:)
                                                 name:UIDeviceBatteryLevelDidChangeNotification object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(batteryStateDidChange:)
                                                 name:UIDeviceBatteryStateDidChangeNotification object:nil];
    
    [self displayBatteryLevel];
    
    [self displayBatteryStatus];
    
}

#pragma mark Battery Info

- (void)displayBatteryLevel {
    float batteryLevelLocal = [UIDevice currentDevice].batteryLevel;
    if (batteryLevelLocal < 0.0)
    {
        // -1.0 means battery state is UIDeviceBatteryStateUnknown
        self.batteryLevel.text = NSLocalizedString(@"Unknown", @"");
    }
    else {
        NSNumber *levelObj = [NSNumber numberWithFloat:batteryLevelLocal];
        
        // Using the numberFormatter property lazily creates that object the
        // first time it's used. 
        self.batteryLevel.text = [self.numberFormatter stringFromNumber:levelObj];
    }    
}

- (void)displayBatteryStatus {
    // Get battery state
    switch ([UIDevice currentDevice].batteryState) {
        case UIDeviceBatteryStateUnknown:
        {
            self.chargingState.text = NSLocalizedString(@"Unknown", @"");
            break;
        }
        case UIDeviceBatteryStateUnplugged:
        {
            self.chargingState.text = NSLocalizedString(@"Unplugged", @"");
            break;
        }
        case UIDeviceBatteryStateCharging:
        {
            self.chargingState.text = NSLocalizedString(@"Charging", @"");
            break;
        }
        case UIDeviceBatteryStateFull:
        {
            self.chargingState.text = NSLocalizedString(@"Full", @"");
            break;
        }
    }    
}

#pragma mark Battery Notifications

// Called when the battery level has changed
- (void)batteryLevelDidChange:(NSNotification *)notification
{
    [self displayBatteryLevel];
}

// Clalled when the battery status has changed
- (void)batteryStateDidChange:(NSNotification *)notification
{
    [self displayBatteryStatus];
}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    self.batteryLevel = nil;
    self.chargingState = nil;
}

- (void)viewDidDisappear:(BOOL)animated {
    [[NSUserDefaults standardUserDefaults] setInteger:2 forKey:@"WhichView"];
}


- (void)dealloc {
    [batteryLevel release];
    [chargingState release];
    [numberFormatter release];
    [super dealloc];
}


@end 
The above code is commented, so it should be pretty obvious what it does. I first register for change notifications for battery level and battery status change, and display the initial values for those properties.

There is a really good example from Apple called BatteryStatus. It should give you anything you need regarding battery information.

I hope you find it useful!