Skip to content
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...
1 parent 341aade commit 622b53742d35c62eba4ea0f6937441ba56f47124 @hermwong hermwong committed May 16, 2013
Showing with 308 additions and 3 deletions.
  1. +1 −1 README.md
  2. +16 −2 plugin.xml
  3. +40 −0 src/ios/CDVBattery.h
  4. +152 −0 src/ios/CDVBattery.m
  5. +99 −0 www/battery.js
View
2 README.md
@@ -1,2 +1,2 @@
cordova-plugin-battery-status
-============================
+=============================
View
18 plugin.xml
@@ -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>
View
40 src/ios/CDVBattery.h
@@ -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
View
152 src/ios/CDVBattery.m
@@ -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
View
99 www/battery.js
@@ -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.
Something went wrong with that request. Please try again.