Skip to content
Permalink
Browse files
added Cordova-JS battery apis, iOS native classes & updated the plugi…
…n.xml config with js-module tag & iOS configuration
  • Loading branch information
hermwong committed May 16, 2013
1 parent 341aade commit 622b53742d35c62eba4ea0f6937441ba56f47124
Show file tree
Hide file tree
Showing 5 changed files with 308 additions and 3 deletions.
@@ -1,2 +1,2 @@
cordova-plugin-battery-status
============================
=============================
@@ -2,16 +2,30 @@

<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="org.apache.cordova.core">
id="org.apache.cordova.core.BatteryListener">
version="0.1.0">
<name>Battery</name>

<js-module src="www/battery.js" name="battery">
<clobbers target="window.battery" />
</js-module>

<!-- android -->
<platform name="android">
<config-file target="res/xml/config.xml" parent="/cordova/plugins">
<plugin name="Battery" value="org.apache.cordova.core.BatteryListener"/>
</config-file>

<source-file src="BatteryListener.java" target-dir="org/apache/cordova/core" />
</platform>
</platform>

<!-- ios -->
<platform name="ios">
<config-file target="config.xml" parent="plugins">
<plugin name="Battery" value="CDVBattery" />
</config-file>
<header-file src="src/ios/CDVBattery.h" />
<source-file src="src/ios/CDVBattery.m" />
</platform>

</plugin>
@@ -0,0 +1,40 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/

#import <Foundation/Foundation.h>
#import <Cordova/CDVPlugin.h>

@interface CDVBattery : CDVPlugin {
UIDeviceBatteryState state;
float level;
bool isPlugged;
NSString* callbackId;
}

@property (nonatomic) UIDeviceBatteryState state;
@property (nonatomic) float level;
@property (nonatomic) bool isPlugged;
@property (strong) NSString* callbackId;

- (void)updateBatteryStatus:(NSNotification*)notification;
- (NSDictionary*)getBatteryStatus;
- (void)start:(CDVInvokedUrlCommand*)command;
- (void)stop:(CDVInvokedUrlCommand*)command;
- (void)dealloc;
@end
@@ -0,0 +1,152 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/

#import "CDVBattery.h"

@interface CDVBattery (PrivateMethods)
- (void)updateOnlineStatus;
@end

@implementation CDVBattery

@synthesize state, level, callbackId, isPlugged;

/* determining type of event occurs on JavaScript side
- (void) updateBatteryLevel:(NSNotification*)notification
{
// send batterylow event for less than 25% battery
// send batterycritical event for less than 10% battery
// W3c says to send batteryStatus event when batterylevel changes by more than 1% (iOS seems to notify each 5%)
// always update the navigator.device.battery info
float currentLevel = [[UIDevice currentDevice] batteryLevel];
NSString* type = @"";
// no check for level == -1 since this api is only called when monitoring is enabled so level should be valid
if (currentLevel < 0.10){
type = @"batterycritical";
} else if (currentLevel < 0.25) {
type = @"batterylow";
} else {
float onePercent = 0.1;
if (self.level >= 0 ){
onePercent = self.level * 0.01;
}
if (fabsf(currentLevel - self.level) > onePercent){
// issue batteryStatus event
type = @"batterystatus";
}
}
// update the battery info and fire event
NSString* jsString = [NSString stringWithFormat:@"navigator.device.battery._status(\"%@\", %@)", type,[[self getBatteryStatus] JSONRepresentation]];
[super writeJavascript:jsString];
}
*/

- (void)updateBatteryStatus:(NSNotification*)notification
{
NSDictionary* batteryData = [self getBatteryStatus];

if (self.callbackId) {
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:batteryData];
[result setKeepCallbackAsBool:YES];
[self.commandDelegate sendPluginResult:result callbackId:self.callbackId];
}
}

/* Get the current battery status and level. Status will be unknown and level will be -1.0 if
* monitoring is turned off.
*/
- (NSDictionary*)getBatteryStatus
{
UIDevice* currentDevice = [UIDevice currentDevice];
UIDeviceBatteryState currentState = [currentDevice batteryState];

isPlugged = FALSE; // UIDeviceBatteryStateUnknown or UIDeviceBatteryStateUnplugged
if ((currentState == UIDeviceBatteryStateCharging) || (currentState == UIDeviceBatteryStateFull)) {
isPlugged = TRUE;
}
float currentLevel = [currentDevice batteryLevel];

if ((currentLevel != self.level) || (currentState != self.state)) {
self.level = currentLevel;
self.state = currentState;
}

// W3C spec says level must be null if it is unknown
NSObject* w3cLevel = nil;
if ((currentState == UIDeviceBatteryStateUnknown) || (currentLevel == -1.0)) {
w3cLevel = [NSNull null];
} else {
w3cLevel = [NSNumber numberWithFloat:(currentLevel * 100)];
}
NSMutableDictionary* batteryData = [NSMutableDictionary dictionaryWithCapacity:2];
[batteryData setObject:[NSNumber numberWithBool:isPlugged] forKey:@"isPlugged"];
[batteryData setObject:w3cLevel forKey:@"level"];
return batteryData;
}

/* turn on battery monitoring*/
- (void)start:(CDVInvokedUrlCommand*)command
{
self.callbackId = command.callbackId;

if ([UIDevice currentDevice].batteryMonitoringEnabled == NO) {
[[UIDevice currentDevice] setBatteryMonitoringEnabled:YES];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateBatteryStatus:)
name:UIDeviceBatteryStateDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateBatteryStatus:)
name:UIDeviceBatteryLevelDidChangeNotification object:nil];
}
}

/* turn off battery monitoring */
- (void)stop:(CDVInvokedUrlCommand*)command
{
// callback one last time to clear the callback function on JS side
if (self.callbackId) {
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self getBatteryStatus]];
[result setKeepCallbackAsBool:NO];
[self.commandDelegate sendPluginResult:result callbackId:self.callbackId];
}
self.callbackId = nil;
[[UIDevice currentDevice] setBatteryMonitoringEnabled:NO];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceBatteryStateDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceBatteryLevelDidChangeNotification object:nil];
}

- (CDVPlugin*)initWithWebView:(UIWebView*)theWebView
{
self = (CDVBattery*)[super initWithWebView:theWebView];
if (self) {
self.state = UIDeviceBatteryStateUnknown;
self.level = -1.0;
}
return self;
}

- (void)dealloc
{
[self stop:nil];
}

- (void)onReset
{
[self stop:nil];
}

@end
@@ -0,0 +1,99 @@
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/

/**
* This class contains information about the current battery status.
* @constructor
*/
var cordova = require('cordova'),
exec = require('cordova/exec');

function handlers() {
return battery.channels.batterystatus.numHandlers +
battery.channels.batterylow.numHandlers +
battery.channels.batterycritical.numHandlers;
}

var Battery = function() {
this._level = null;
this._isPlugged = null;
// Create new event handlers on the window (returns a channel instance)
this.channels = {
batterystatus:cordova.addWindowEventHandler("batterystatus"),
batterylow:cordova.addWindowEventHandler("batterylow"),
batterycritical:cordova.addWindowEventHandler("batterycritical")
};
for (var key in this.channels) {
this.channels[key].onHasSubscribersChange = Battery.onHasSubscribersChange;
}
};
/**
* Event handlers for when callbacks get registered for the battery.
* Keep track of how many handlers we have so we can start and stop the native battery listener
* appropriately (and hopefully save on battery life!).
*/
Battery.onHasSubscribersChange = function() {
// If we just registered the first handler, make sure native listener is started.
if (this.numHandlers === 1 && handlers() === 1) {
exec(battery._status, battery._error, "Battery", "start", []);
} else if (handlers() === 0) {
exec(null, null, "Battery", "stop", []);
}
};

/**
* Callback for battery status
*
* @param {Object} info keys: level, isPlugged
*/
Battery.prototype._status = function(info) {
if (info) {
var me = battery;
var level = info.level;
if (me._level !== level || me._isPlugged !== info.isPlugged) {
// Fire batterystatus event
cordova.fireWindowEvent("batterystatus", info);

// Fire low battery event
if (level === 20 || level === 5) {
if (level === 20) {
cordova.fireWindowEvent("batterylow", info);
}
else {
cordova.fireWindowEvent("batterycritical", info);
}
}
}
me._level = level;
me._isPlugged = info.isPlugged;
}
};

/**
* Error callback for battery start
*/
Battery.prototype._error = function(e) {
console.log("Error initializing Battery: " + e);
};

var battery = new Battery();

module.exports = battery;

0 comments on commit 622b537

Please sign in to comment.