Onactivate, ondeactivate & onfailure callbacks

This commit is contained in:
Sebastián Katzer 2014-12-14 00:04:12 +01:00
parent 1c289f7d01
commit 5fa96556ae
7 changed files with 269 additions and 73 deletions

View File

@ -1,6 +1,7 @@
## ChangeLog ## ChangeLog
#### Version 0.6.0 (not yet released) #### Version 0.6.0 (not yet released)
- [feature:] Android support - [feature:] Android support
- [feature:] `onactivate`, `ondeactivate` and `onfailure` callbacks.
- [___change___:] Disabled by default - [___change___:] Disabled by default
- [enhancement:] iOS does not require user permissions, internet connection and geo location anymore. - [enhancement:] iOS does not require user permissions, internet connection and geo location anymore.

View File

@ -22,7 +22,7 @@ The plugin focuses on enterprise-only distribution and may not compliant with al
1. [Supported Platforms](#supported-platforms) 1. [Supported Platforms](#supported-platforms)
2. [Installation](#installation) 2. [Installation](#installation)
3. [ChangeLog](#changelog) 3. [ChangeLog](#changelog)
4. [Using the plugin](#using-the-plugin) 4. [Usage](#usage)
5. [Examples](#examples) 5. [Examples](#examples)
6. [Platform specifics](#platform-specifics) 6. [Platform specifics](#platform-specifics)
@ -65,6 +65,7 @@ More informations can be found [here][PGB_plugin].
## ChangeLog ## ChangeLog
#### Version 0.6.0 (not yet released) #### Version 0.6.0 (not yet released)
- [feature:] Android support - [feature:] Android support
- [feature:] `onactivate`, `ondeactivate` and `onfailure` callbacks.
- [___change___:] Disabled by default - [___change___:] Disabled by default
- [enhancement:] iOS does not require user permissions, internet connection and geo location anymore. - [enhancement:] iOS does not require user permissions, internet connection and geo location anymore.
@ -72,13 +73,19 @@ More informations can be found [here][PGB_plugin].
- The former `plugin.backgroundMode` namespace has been deprecated and will be removed with the next major release. - The former `plugin.backgroundMode` namespace has been deprecated and will be removed with the next major release.
- See [CHANGELOG.md][changelog] to get the full changelog for the plugin. - See [CHANGELOG.md][changelog] to get the full changelog for the plugin.
#### Known issues
- Plug-in is broken on Windows Phone 8.1 platform.
## Using the plugin
## Usage
The plugin creates the object ```cordova.plugins.backgroundMode``` with the following methods: The plugin creates the object ```cordova.plugins.backgroundMode``` with the following methods:
1. [backgroundMode.enable][enable] 1. [backgroundMode.enable][enable]
2. [backgroundMode.disable][disable] 2. [backgroundMode.disable][disable]
2. [backgroundMode.configure][configure] 2. [backgroundMode.configure][configure]
3. [backgroundMode.onactivate][onactivate]
4. [backgroundMode.ondeactivate][ondeactivate]
5. [backgroundMode.onfailure][onfailure]
### Plugin initialization ### Plugin initialization
The plugin and its methods are not available before the *deviceready* event has been fired. The plugin and its methods are not available before the *deviceready* event has been fired.
@ -110,16 +117,49 @@ The background mode can be disabled through the `backgroundMode.disable` interfa
cordova.plugins.backgroundMode.disable(); cordova.plugins.backgroundMode.disable();
``` ```
### Get informed when the background mode has been activated
The `backgroundMode.onactivate` interface can be used to get notified when the background mode has been activated.
```javascript
cordova.plugins.backgroundMode.onactivate = function() {};
```
### Get informed when the background mode has been deactivated
The `backgroundMode.ondeactivate` interface can be used to get notified when the background mode has been deactivated.
#### Further informations
- Once the mode has been deactivated the app will be paused soon after the callback has been fired.
```javascript
cordova.plugins.backgroundMode.ondeactivate = function() {};
```
### Get informed when the background mode could not been activated
The `backgroundMode.onfailure` interface can be used to get notified when the background mode could not been activated.
The listener has to be a function and takes the following arguments:
- errorCode: Error code which describes the error
```javascript
cordova.plugins.backgroundMode.onfailure = function(errorCode) {};
```
## Examples ## Examples
The following example demonstrates how to enable the background mode after device is ready. The mode itself will be activated when the app has entered the background. The following example demonstrates how to enable the background mode after device is ready. The mode itself will be activated when the app has entered the background.
```javascript ```javascript
document.addEventListener('deviceready', function () { document.addEventListener('deviceready', function () {
// Enable background mode
cordova.plugins.backgroundMode.enable();
// Android customization // Android customization
cordova.plugins.backgroundMode.configure({ text:'Doing heavy tasks.'}); cordova.plugins.backgroundMode.configure({ text:'Doing heavy tasks.'});
// Enable background mode
cordova.plugins.backgroundMode.enable();
// Called when background mode has been activated
cordova.plugins.backgroundMode.onactivate = function () {
setInterval(function () {
console.log('App is running in background');
});
}
}, false); }, false);
``` ```
@ -170,8 +210,11 @@ This software is released under the [Apache 2.0 License][apache2_license].
[PGB]: http://docs.build.phonegap.com/en_US/index.html [PGB]: http://docs.build.phonegap.com/en_US/index.html
[PGB_plugin]: https://build.phonegap.com/plugins/490 [PGB_plugin]: https://build.phonegap.com/plugins/490
[changelog]: CHANGELOG.md [changelog]: CHANGELOG.md
[enable]: #prevent-the-app-from-going-to-sleep-in-background [enable]: #prevent_the_app_from_going_to_sleep_in_background
[disable]: #pause-the-app-while-in-background [disable]: #pause_the_app_while_in_background
[configure]: #android-customization [configure]: #android_customization
[onactivate]: #get_informed_when_the_background_mode_has_been_activated
[ondeactivate]: #get_informed_when_the_background_mode_has_been_deactivated
[onfailure]: #get_informed_when_the_background_mode_could_not_been_activated
[apache2_license]: http://opensource.org/licenses/Apache-2.0 [apache2_license]: http://opensource.org/licenses/Apache-2.0
[appplant]: http://appplant.de [appplant]: http://appplant.de

View File

@ -75,9 +75,7 @@
* it to be something the user is actively aware of and thus not a * it to be something the user is actively aware of and thus not a
* candidate for killing when low on memory. * candidate for killing when low on memory.
--> -->
<service <service android:name="de.appplant.cordova.plugin.background.ForegroundService" />
android:name="de.appplant.cordova.plugin.background.ForegroundService"
android:enabled="true" />
</config-file> </config-file>
@ -95,8 +93,7 @@
<platform name="wp8"> <platform name="wp8">
<config-file target="config.xml" parent="/*"> <config-file target="config.xml" parent="/*">
<feature name="BackgroundMode"> <feature name="BackgroundMode">
<param name="wp-package" value="BackgroundMode" onload="true" /> <param name="wp-package" value="BackgroundMode" />
<param name="onload" value="true" />
</feature> </feature>
</config-file> </config-file>

View File

@ -37,6 +37,11 @@ import android.util.Log;
public class BackgroundMode extends CordovaPlugin { public class BackgroundMode extends CordovaPlugin {
// Event types for callbacks
private enum Event {
ACTIVATE, DEACTIVATE, FAILURE
}
// Flag indicates if the app is in background or foreground // Flag indicates if the app is in background or foreground
private boolean inBackground = false; private boolean inBackground = false;
@ -55,12 +60,11 @@ public class BackgroundMode extends CordovaPlugin {
@Override @Override
public void onServiceConnected(ComponentName name, IBinder binder) { public void onServiceConnected(ComponentName name, IBinder binder) {
// Nothing to do here // Nothing to do here
Log.d("BackgroundMode", "Service connected");
} }
@Override @Override
public void onServiceDisconnected(ComponentName name) { public void onServiceDisconnected(ComponentName name) {
Log.w("BackgroundMode", "Service disrupted"); // Nothing to do here
} }
}; };
@ -79,7 +83,7 @@ public class BackgroundMode extends CordovaPlugin {
*/ */
@Override @Override
public boolean execute (String action, JSONArray args, public boolean execute (String action, JSONArray args,
CallbackContext callback) throws JSONException { CallbackContext callback) throws JSONException {
if (action.equalsIgnoreCase("configure")) { if (action.equalsIgnoreCase("configure")) {
setSettings(args.getJSONObject(0)); setSettings(args.getJSONObject(0));
@ -188,10 +192,16 @@ public class BackgroundMode extends CordovaPlugin {
return; return;
} }
context.bindService( try {
intent, connection, Context.BIND_AUTO_CREATE); context.bindService(
intent, connection, Context.BIND_AUTO_CREATE);
context.startService(intent); context.startService(intent);
fireEvent(Event.ACTIVATE, null);
} catch (Exception e) {
fireEvent(Event.FAILURE, e.getMessage());
}
isBind = true; isBind = true;
} }
@ -207,6 +217,7 @@ public class BackgroundMode extends CordovaPlugin {
context, ForegroundService.class); context, ForegroundService.class);
if (isBind) { if (isBind) {
fireEvent(Event.DEACTIVATE, null);
context.unbindService(connection); context.unbindService(connection);
} }
@ -214,4 +225,32 @@ public class BackgroundMode extends CordovaPlugin {
isBind = false; isBind = false;
} }
/**
* Fire vent with some parameters inside the web view.
*
* @param event
* The name of the event
* @param params
* Optional arguments for the event
*/
private void fireEvent (Event event, String params) {
String eventName;
switch (event) {
case ACTIVATE:
eventName = "activate"; break;
case DEACTIVATE:
eventName = "deactivate"; break;
default:
eventName = "failure";
}
String js = String.format("setTimeout('cordova.plugins.backgroundMode" +
".on%s(%s)',0)",
eventName, params);
webView.loadUrl("javascript:" + js);
}
} }

View File

@ -23,6 +23,11 @@
@implementation APPBackgroundMode @implementation APPBackgroundMode
NSString *const kAPPBackgroundModeNamespace = @"cordova.plugins.backgroundMode";
NSString *const kAPPBackgroundModeActivateEvent = @"activate";
NSString *const kAPPBackgroundModeDeactivateEvent = @"deactivate";
NSString *const kAPPBackgroundModeFailureEvent = @"failure";
#pragma mark - #pragma mark -
#pragma mark Initialization methods #pragma mark Initialization methods
@ -99,6 +104,7 @@
- (void) keepAwake { - (void) keepAwake {
if (enabled) { if (enabled) {
[audioPlayer play]; [audioPlayer play];
[self fireEvent:kAPPBackgroundModeActivateEvent withParams:NULL];
} }
} }
@ -111,6 +117,10 @@
NSLog(@"BackgroundMode: On simulator apps never pause in background!"); NSLog(@"BackgroundMode: On simulator apps never pause in background!");
} }
if (audioPlayer.isPlaying) {
[self fireEvent:kAPPBackgroundModeDeactivateEvent withParams:NULL];
}
[audioPlayer pause]; [audioPlayer pause];
} }
@ -149,11 +159,26 @@
[session setActive:YES error:NULL]; [session setActive:YES error:NULL];
}; };
#pragma mark -
#pragma mark Helper methods
/** /**
* Restart playing sound when interrupted by phone calls. * Restart playing sound when interrupted by phone calls.
*/ */
- (void) handleAudioSessionInterruption:(NSNotification*)notification { - (void) handleAudioSessionInterruption:(NSNotification*)notification {
[self fireEvent:kAPPBackgroundModeDeactivateEvent withParams:NULL];
[self keepAwake]; [self keepAwake];
} }
/**
* Method to fire an event with some parameters in the browser.
*/
- (void) fireEvent:(NSString*)event withParams:(NSString*)params
{
NSString* js = [NSString stringWithFormat:@"setTimeout('%@.on%@(%@)',0)",
kAPPBackgroundModeNamespace, event, params];
[self.commandDelegate evalJs:js];
}
@end @end

View File

@ -21,6 +21,9 @@
using WPCordovaClassLib.Cordova.Commands; using WPCordovaClassLib.Cordova.Commands;
using Windows.Devices.Geolocation; using Windows.Devices.Geolocation;
using Microsoft.Phone.Shell;
using System;
using WPCordovaClassLib.Cordova;
namespace Cordova.Extension.Commands namespace Cordova.Extension.Commands
{ {
@ -30,97 +33,167 @@ namespace Cordova.Extension.Commands
public class BackgroundMode : BaseCommand public class BackgroundMode : BaseCommand
{ {
/// </summary> /// </summary>
/// Flag gibt an, ob die App im Hintergrund wach gehalten werden soll /// Event types for callbacks
/// </summary> /// </summary>
private static bool IsEnabled = true; enum Event {
ACTIVATE, DEACTIVATE, FAILURE
}
#region Instance variables
/// </summary> /// </summary>
/// Lokalisiert das Smartphone /// Flag indicates if the plugin is enabled or disabled
/// </summary>
private bool IsDisabled = true;
/// </summary>
/// Geolocator to monitor location changes
/// </summary> /// </summary>
private static Geolocator Geolocator { get; set; } private static Geolocator Geolocator { get; set; }
/// </summary> #endregion
/// Registriert die Listener für die (sleep/resume) Events und startet
/// bzw. stoppt die Geo-Lokalisierung #region Interface methods
/// </summary>
public BackgroundMode ()
{
Activate();
}
/// </summary> /// </summary>
/// @js-interface /// Enable the mode to stay awake when switching
/// Setzt den Flag, dass die App im Hintergrund wach gehalten werden soll /// to background for the next time.
/// </summary> /// </summary>
public void enable (string args) public void enable (string args)
{ {
Enable(); IsDisabled = false;
} }
/// </summary> /// </summary>
/// @js-interface /// Disable the background mode and stop
/// Entfernt den Flag, sodass die App im Hintergrund pausiert wird /// being active in background.
/// </summary> /// </summary>
public void disable (string args) public void disable (string args)
{ {
Disable(); IsDisabled = true;
}
/// </summary>
/// Setzt den Flag, dass die App im Hintergrund wach gehalten werden soll
/// </summary>
public static void Enable ()
{
IsEnabled = true;
}
/// </summary>
/// Entfernt den Flag, sodass die App im Hintergrund pausiert wird
/// </summary>
public static void Disable ()
{
IsEnabled = false;
Deactivate(); Deactivate();
} }
/// </summary> #endregion
/// Startet das Aktualisieren des Standpunktes
/// </summary>
public static void Activate ()
{
if (Geolocator == null && IsEnabled && IsServiceAvailable())
{
Geolocator = new Geolocator();
Geolocator.DesiredAccuracy = PositionAccuracy.Default; #region Core methods
Geolocator.MovementThreshold = 100000;
Geolocator.PositionChanged += geolocator_PositionChanged; /// </summary>
/// Keep the app awake by tracking
/// for position changes.
/// </summary>
private void Activate()
{
if (IsDisabled || Geolocator != null)
return;
if (!IsServiceAvailable())
{
FireEvent(Event.FAILURE, null);
return;
} }
Geolocator = new Geolocator();
Geolocator.DesiredAccuracy = PositionAccuracy.Default;
Geolocator.MovementThreshold = 100000;
Geolocator.PositionChanged += geolocator_PositionChanged;
FireEvent(Event.ACTIVATE, null);
} }
/// </summary> /// </summary>
/// Beendet das Aktualisieren des Standpunktes /// Let the app going to sleep.
/// </summary> /// </summary>
public static void Deactivate () private void Deactivate ()
{ {
if (Geolocator != null) if (Geolocator == null)
{ return;
Geolocator.PositionChanged -= geolocator_PositionChanged;
Geolocator = null; FireEvent(Event.DEACTIVATE, null);
}
Geolocator.PositionChanged -= geolocator_PositionChanged;
Geolocator = null;
} }
private static void geolocator_PositionChanged (Geolocator sender, PositionChangedEventArgs args) {} #endregion
#region Helper methods
/// </summary> /// </summary>
/// Gibt an, ob der Lokalisierungsdienst verfügbar ist /// Determine if location service is available and enabled.
/// </summary> /// </summary>
private static bool IsServiceAvailable() private bool IsServiceAvailable()
{ {
Geolocator geolocator = (Geolocator == null) ? new Geolocator() : Geolocator; Geolocator geolocator = (Geolocator == null) ? new Geolocator() : Geolocator;
return !(geolocator.LocationStatus == PositionStatus.Disabled || geolocator.LocationStatus == PositionStatus.NotAvailable); PositionStatus status = geolocator.LocationStatus;
if (status == PositionStatus.Disabled)
return false;
if (status == PositionStatus.NotAvailable)
return false;
return true;
} }
/// <summary>
/// Fires the given event.
/// </summary>
private void FireEvent(Event Event, string Param)
{
string EventName;
switch (Event) {
case Event.ACTIVATE:
EventName = "activate"; break;
case Event.DEACTIVATE:
EventName = "deactivate"; break;
default:
EventName = "failure"; break;
}
string js = String.Format("cordova.plugins.backgroundMode.on{0}({1})", EventName, Param);
PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, js);
pluginResult.KeepCallback = true;
DispatchCommandResult(pluginResult);
}
#endregion
#region Delegate methods
private void geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
// Nothing to do here
}
#endregion
#region Lifecycle methods
/// <summary>
/// Occurs when the application is being deactivated.
/// </summary>
public override void OnPause(object sender, DeactivatedEventArgs e)
{
Activate();
}
/// <summary>
/// Occurs when the application is being made active after previously being put
/// into a dormant state or tombstoned.
/// </summary>
public override void OnResume(object sender, ActivatedEventArgs e)
{
Deactivate();
}
#endregion
} }
} }

View File

@ -87,6 +87,24 @@ exports.configure = function (options) {
} }
}; };
/**
* Called when the background mode has been activated.
*/
exports.onactivate = function () {};
/**
* Called when the background mode has been deaktivated.
*/
exports.ondeactivate = function () {};
/**
* Called when the background mode could not been activated.
*
* @param {Integer} errorCode
* Error code which describes the error
*/
exports.onfailure = function () {};
/** /**
* @private * @private
* *