Compare commits
12 Commits
issue/#5-f
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
361358a458 | ||
|
df990e762f | ||
|
b33044c8e5 | ||
|
4d98947310 | ||
|
77767cab9b | ||
|
1dab2de6ec | ||
|
5f50704564 | ||
|
8d523e638e | ||
|
abb6b30cf8 | ||
|
8ad9802ea6 | ||
|
53f3278722 | ||
|
0da2006f7c |
28
README.md
28
README.md
@ -81,6 +81,8 @@ cordova.plugins.backgroundMode.un('EVENT', function);
|
|||||||
### Transit between application states
|
### Transit between application states
|
||||||
Android allows to programmatically move from foreground to background or vice versa.
|
Android allows to programmatically move from foreground to background or vice versa.
|
||||||
|
|
||||||
|
Note: starting with Android 10, you must request the "Draw on Top" permission from the user or the call to `moveToForeground` will silently fail. You can request it with `cordova.plugins.backgroundMode.requestForegroundPermission();`. This permission isn't necessary for `moveToBackground`
|
||||||
|
|
||||||
```js
|
```js
|
||||||
cordova.plugins.backgroundMode.moveToBackground();
|
cordova.plugins.backgroundMode.moveToBackground();
|
||||||
// or
|
// or
|
||||||
@ -122,10 +124,33 @@ cordova.plugins.backgroundMode.unlock();
|
|||||||
|
|
||||||
### Request to disable battery optimizations
|
### Request to disable battery optimizations
|
||||||
Starting in Android 8, apps can be put to sleep to conserve battery. When this happens (usually after 5 minutes or so), the background task is killed. This will cause things like MQTT connections to break.
|
Starting in Android 8, apps can be put to sleep to conserve battery. When this happens (usually after 5 minutes or so), the background task is killed. This will cause things like MQTT connections to break.
|
||||||
|
|
||||||
This method will show a permission prompt for the user (only if the app hasn't been granted permission) to ignore the optimization.
|
This method will show a permission prompt for the user (only if the app hasn't been granted permission) to ignore the optimization.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
cordova.plugins.backgroundMode.disableBatteryOptimizations();
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also open the battery optimization settings menu directly, and get the user to set it manually. This may be a better option for devices which may ignore the prompt above.
|
||||||
|
|
||||||
|
```js
|
||||||
|
cordova.plugins.backgroundMode.openBatteryOptimizationsSettings();
|
||||||
|
```
|
||||||
|
|
||||||
|
To check if battery optimizations are disabled for the app:
|
||||||
|
|
||||||
|
```js
|
||||||
|
cordova.plugins.backgroundMode.isIgnoringBatteryOptimizations(function(isIgnoring) {
|
||||||
|
...
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Additionally, you may find that your JS code begins to run less frequently, or not at all while in the background. This can be due to the webview slowing down its execution due to being in the background. The `disableWebViewOptimizations` function can prevent that, but it's important that it is run _after_ the app goes to the background.
|
||||||
|
|
||||||
|
```js
|
||||||
|
cordova.plugins.backgroundMode.on('activate', function() {
|
||||||
cordova.plugins.backgroundMode.disableWebViewOptimizations();
|
cordova.plugins.backgroundMode.disableWebViewOptimizations();
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### Notification
|
### Notification
|
||||||
@ -149,7 +174,8 @@ cordova.plugins.backgroundMode.setDefaults({
|
|||||||
allowClose: Boolean, // add a "Close" action to the notification
|
allowClose: Boolean, // add a "Close" action to the notification
|
||||||
closeIcon: 'power', // An icon shown for the close action
|
closeIcon: 'power', // An icon shown for the close action
|
||||||
closeTitle: 'Close', // The text for the close action
|
closeTitle: 'Close', // The text for the close action
|
||||||
showWhen: Boolean //(Default: true) Show the time since the notification was created
|
showWhen: Boolean, //(Default: true) Show the time since the notification was created
|
||||||
|
visibility: String, // Android only: one of 'private' (default), 'public' or 'secret' (see https://developer.android.com/reference/android/app/Notification.Builder.html#setVisibility(int))
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cordova-plugin-background-mode",
|
"name": "cordova-plugin-background-mode",
|
||||||
"version": "0.7.2",
|
"version": "0.7.3",
|
||||||
"description": "Prevent apps from going to sleep in background.",
|
"description": "Prevent apps from going to sleep in background.",
|
||||||
"cordova": {
|
"cordova": {
|
||||||
"id": "cordova-plugin-background-mode",
|
"id": "cordova-plugin-background-mode",
|
||||||
|
@ -3,13 +3,13 @@
|
|||||||
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
|
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
id="cordova-plugin-background-mode"
|
id="cordova-plugin-background-mode"
|
||||||
version="0.7.2">
|
version="0.7.3">
|
||||||
|
|
||||||
<name>BackgroundMode</name>
|
<name>BackgroundMode</name>
|
||||||
|
|
||||||
<description>Prevent apps from going to sleep in background.</description>
|
<description>Prevent apps from going to sleep in background.</description>
|
||||||
|
|
||||||
<repo>https://github.com/katzer/cordova-plugin-background-mode.git</repo>
|
<repo>https://bitbucket.org:TheBosZ/cordova-plugin-run-in-background.git</repo>
|
||||||
|
|
||||||
<keywords>appplant, background</keywords>
|
<keywords>appplant, background</keywords>
|
||||||
|
|
||||||
@ -78,6 +78,7 @@
|
|||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||||
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||||
</config-file>
|
</config-file>
|
||||||
|
|
||||||
<source-file
|
<source-file
|
||||||
|
@ -34,6 +34,7 @@ import android.content.pm.PackageManager;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
|
import android.provider.Settings;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import org.apache.cordova.CallbackContext;
|
import org.apache.cordova.CallbackContext;
|
||||||
@ -55,6 +56,7 @@ import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
|
|||||||
import static android.os.Build.VERSION.SDK_INT;
|
import static android.os.Build.VERSION.SDK_INT;
|
||||||
import static android.os.Build.VERSION_CODES.M;
|
import static android.os.Build.VERSION_CODES.M;
|
||||||
import static android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS;
|
import static android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS;
|
||||||
|
import static android.provider.Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS;
|
||||||
import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
|
import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
|
||||||
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
|
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
|
||||||
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
|
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
|
||||||
@ -90,6 +92,12 @@ public class BackgroundModeExt extends CordovaPlugin {
|
|||||||
case "battery":
|
case "battery":
|
||||||
disableBatteryOptimizations();
|
disableBatteryOptimizations();
|
||||||
break;
|
break;
|
||||||
|
case "batterysettings":
|
||||||
|
openBatterySettings();
|
||||||
|
break;
|
||||||
|
case "optimizationstatus":
|
||||||
|
isIgnoringBatteryOptimizations(callback);
|
||||||
|
break;
|
||||||
case "webview":
|
case "webview":
|
||||||
disableWebViewOptimizations();
|
disableWebViewOptimizations();
|
||||||
break;
|
break;
|
||||||
@ -102,6 +110,9 @@ public class BackgroundModeExt extends CordovaPlugin {
|
|||||||
case "foreground":
|
case "foreground":
|
||||||
moveToForeground();
|
moveToForeground();
|
||||||
break;
|
break;
|
||||||
|
case "requestTopPermissions":
|
||||||
|
requestTopPermissions();
|
||||||
|
break;
|
||||||
case "tasklist":
|
case "tasklist":
|
||||||
excludeFromTaskList();
|
excludeFromTaskList();
|
||||||
break;
|
break;
|
||||||
@ -166,7 +177,7 @@ public class BackgroundModeExt extends CordovaPlugin {
|
|||||||
try {
|
try {
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
getApp().runOnUiThread(() -> {
|
getApp().runOnUiThread(() -> {
|
||||||
View view = webView.getEngine().getView();
|
View view = webView.getView();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Class.forName("org.crosswalk.engine.XWalkCordovaView")
|
Class.forName("org.crosswalk.engine.XWalkCordovaView")
|
||||||
@ -209,6 +220,53 @@ public class BackgroundModeExt extends CordovaPlugin {
|
|||||||
cordova.getActivity().startActivity(intent);
|
cordova.getActivity().startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the Battery Optimization settings screen
|
||||||
|
*/
|
||||||
|
private void openBatterySettings()
|
||||||
|
{
|
||||||
|
if (SDK_INT < M)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Activity activity = cordova.getActivity();
|
||||||
|
Intent intent = new Intent(ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
|
||||||
|
|
||||||
|
cordova.getActivity().startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the Battery Optimization settings screen
|
||||||
|
*
|
||||||
|
* @param callback The callback to invoke.
|
||||||
|
*/
|
||||||
|
private void isIgnoringBatteryOptimizations(CallbackContext callback)
|
||||||
|
{
|
||||||
|
if (SDK_INT < M)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Activity activity = cordova.getActivity();
|
||||||
|
String pkgName = activity.getPackageName();
|
||||||
|
PowerManager pm = (PowerManager)getService(POWER_SERVICE);
|
||||||
|
boolean isIgnoring = pm.isIgnoringBatteryOptimizations(pkgName);
|
||||||
|
PluginResult res = new PluginResult(Status.OK, isIgnoring);
|
||||||
|
|
||||||
|
callback.sendPluginResult(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void requestTopPermissions() {
|
||||||
|
if (SDK_INT >= M) {
|
||||||
|
|
||||||
|
Activity activity = cordova.getActivity();
|
||||||
|
if (Settings.canDrawOverlays(activity.getApplicationContext())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String pkgName = activity.getPackageName();
|
||||||
|
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + pkgName));
|
||||||
|
activity.startActivity(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the system settings dialog where the user can tweak or turn off any
|
* Opens the system settings dialog where the user can tweak or turn off any
|
||||||
* custom app start settings added by the manufacturer if available.
|
* custom app start settings added by the manufacturer if available.
|
||||||
|
@ -189,17 +189,23 @@ public class ForegroundService extends Service {
|
|||||||
String text = settings.optString("text", NOTIFICATION_TEXT);
|
String text = settings.optString("text", NOTIFICATION_TEXT);
|
||||||
boolean bigText = settings.optBoolean("bigText", false);
|
boolean bigText = settings.optBoolean("bigText", false);
|
||||||
String subText = settings.optString("subText", "");
|
String subText = settings.optString("subText", "");
|
||||||
|
String visibility = settings.optString("visibility", "");
|
||||||
|
|
||||||
Context context = getApplicationContext();
|
Context context = getApplicationContext();
|
||||||
String pkgName = context.getPackageName();
|
String pkgName = context.getPackageName();
|
||||||
Intent intent = context.getPackageManager()
|
Intent intent = context.getPackageManager()
|
||||||
.getLaunchIntentForPackage(pkgName);
|
.getLaunchIntentForPackage(pkgName);
|
||||||
|
|
||||||
|
int smallIcon = getIconResId(settings);
|
||||||
|
if (smallIcon == 0) { //If no icon at all was found, fall back to the app's icon
|
||||||
|
smallIcon = context.getApplicationInfo().icon;
|
||||||
|
}
|
||||||
|
|
||||||
NotificationCompat.Builder notification = new NotificationCompat.Builder(context, CHANNEL_ID)
|
NotificationCompat.Builder notification = new NotificationCompat.Builder(context, CHANNEL_ID)
|
||||||
.setContentTitle(title)
|
.setContentTitle(title)
|
||||||
.setContentText(text)
|
.setContentText(text)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
.setSmallIcon(getIconResId(settings))
|
.setSmallIcon(smallIcon)
|
||||||
.setShowWhen(settings.optBoolean("showWhen", true));
|
.setShowWhen(settings.optBoolean("showWhen", true));
|
||||||
|
|
||||||
if (!subText.equals("")) {
|
if (!subText.equals("")) {
|
||||||
@ -224,6 +230,10 @@ public class ForegroundService extends Service {
|
|||||||
new NotificationCompat.BigTextStyle().bigText(text));
|
new NotificationCompat.BigTextStyle().bigText(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!visibility.equals("")) {
|
||||||
|
notification.setVisibility(getVisibility(visibility));
|
||||||
|
}
|
||||||
|
|
||||||
setColor(notification, settings);
|
setColor(notification, settings);
|
||||||
|
|
||||||
if (intent != null && settings.optBoolean("resume")) {
|
if (intent != null && settings.optBoolean("resume")) {
|
||||||
@ -309,6 +319,23 @@ public class ForegroundService extends Service {
|
|||||||
return res.getIdentifier(icon, type, pkgName);
|
return res.getIdentifier(icon, type, pkgName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the visibility constant from a string.
|
||||||
|
*
|
||||||
|
* @param visibility one of 'public', 'private', 'secret'
|
||||||
|
*
|
||||||
|
* @return The visibility constant if a match is found, 'private' otherwise
|
||||||
|
*/
|
||||||
|
private int getVisibility (String visibility)
|
||||||
|
{
|
||||||
|
if (visibility.equals("public")) {
|
||||||
|
return Notification.VISIBILITY_PUBLIC;
|
||||||
|
} else if (visibility.equals("secret")) {
|
||||||
|
return Notification.VISIBILITY_SECRET;
|
||||||
|
} else {
|
||||||
|
return Notification.VISIBILITY_PRIVATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Set notification color if its supported by the SDK.
|
* Set notification color if its supported by the SDK.
|
||||||
*
|
*
|
||||||
|
@ -174,6 +174,9 @@ NSString* const kAPPBackgroundEventDeactivate = @"deactivate";
|
|||||||
// even another app starts playing sound
|
// even another app starts playing sound
|
||||||
[session setCategory:AVAudioSessionCategoryPlayback
|
[session setCategory:AVAudioSessionCategoryPlayback
|
||||||
error:NULL];
|
error:NULL];
|
||||||
|
// Prevent sound/music from stopping when opening the app. Also prevents embedded videos from pausing when unmuted.
|
||||||
|
[session setCategory:AVAudioSessionCategoryAmbient
|
||||||
|
error:NULL];
|
||||||
|
|
||||||
// Active the audio session
|
// Active the audio session
|
||||||
[session setActive:YES error:NULL];
|
[session setActive:YES error:NULL];
|
||||||
@ -222,7 +225,7 @@ NSString* const kAPPBackgroundEventDeactivate = @"deactivate";
|
|||||||
NSString* flag = [NSString stringWithFormat:@"%@._isActive=%@;",
|
NSString* flag = [NSString stringWithFormat:@"%@._isActive=%@;",
|
||||||
kAPPBackgroundJsNamespace, active];
|
kAPPBackgroundJsNamespace, active];
|
||||||
|
|
||||||
NSString* depFn = [NSString stringWithFormat:@"%@.on%@();",
|
NSString* depFn = [NSString stringWithFormat:@"%@.on('%@');",
|
||||||
kAPPBackgroundJsNamespace, event];
|
kAPPBackgroundJsNamespace, event];
|
||||||
|
|
||||||
NSString* fn = [NSString stringWithFormat:@"%@.fireEvent('%@');",
|
NSString* fn = [NSString stringWithFormat:@"%@.fireEvent('%@');",
|
||||||
@ -241,7 +244,16 @@ NSString* const kAPPBackgroundEventDeactivate = @"deactivate";
|
|||||||
*/
|
*/
|
||||||
+ (NSString*) wkProperty
|
+ (NSString*) wkProperty
|
||||||
{
|
{
|
||||||
NSString* str = @"YWx3YXlzUnVuc0F0Rm9yZWdyb3VuZFByaW9yaXR5";
|
NSString * str = @"";
|
||||||
|
if (@available(iOS 12.2, *)) {
|
||||||
|
// do stuff for iOS 12.2 and newer
|
||||||
|
NSLog(@"iOS 12.2+ detected");
|
||||||
|
str = @"YWx3YXlzUnVuc0F0Rm9yZWdyb3VuZFByaW9yaXR5";
|
||||||
|
} else {
|
||||||
|
// do stuff for iOS 12.1 and older
|
||||||
|
NSLog(@"iOS Below 12.2 detected");
|
||||||
|
str = @"X2Fsd2F5c1J1bnNBdEZvcmVncm91bmRQcmlvcml0eQ==";
|
||||||
|
}
|
||||||
NSData* data = [[NSData alloc] initWithBase64EncodedString:str options:0];
|
NSData* data = [[NSData alloc] initWithBase64EncodedString:str options:0];
|
||||||
|
|
||||||
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||||
|
@ -177,6 +177,38 @@ exports.disableBatteryOptimizations = function()
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the system settings screen for battery optimization, allowing the user to
|
||||||
|
* manually change the optimization settings.
|
||||||
|
*
|
||||||
|
* @return [ Void ]
|
||||||
|
*/
|
||||||
|
exports.openBatteryOptimizationsSettings = function()
|
||||||
|
{
|
||||||
|
if (this._isAndroid)
|
||||||
|
{
|
||||||
|
cordova.exec(null, null, 'BackgroundModeExt', 'batterysettings', []);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the system settings screen for battery optimization, allowing the user to
|
||||||
|
* manually change the optimization settings.
|
||||||
|
*
|
||||||
|
* @return [ Void ]
|
||||||
|
*/
|
||||||
|
exports.isIgnoringBatteryOptimizations = function(callback)
|
||||||
|
{
|
||||||
|
if (this._isAndroid)
|
||||||
|
{
|
||||||
|
cordova.exec(callback, null, 'BackgroundModeExt', 'optimizationstatus', []);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
callback(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the system settings dialog where the user can tweak or turn off any
|
* Opens the system settings dialog where the user can tweak or turn off any
|
||||||
* custom app start settings added by the manufacturer if available.
|
* custom app start settings added by the manufacturer if available.
|
||||||
@ -220,6 +252,17 @@ exports.moveToForeground = function()
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests permission to "draw on top" which is necessary for the "moveToForeground" method in Android 10+
|
||||||
|
*
|
||||||
|
* @return [ Void ]
|
||||||
|
*/
|
||||||
|
exports.requestForegroundPermission = function() {
|
||||||
|
if (this._isAndroid) {
|
||||||
|
cordova.exec(null, null, 'BackgroundModeExt', 'requestTopPermissions', []);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exclude the app from the recent tasks list (Android only).
|
* Exclude the app from the recent tasks list (Android only).
|
||||||
*
|
*
|
||||||
@ -424,7 +467,8 @@ exports._defaults = {
|
|||||||
allowClose: false,
|
allowClose: false,
|
||||||
closeIcon: 'power',
|
closeIcon: 'power',
|
||||||
closeTitle: 'Close',
|
closeTitle: 'Close',
|
||||||
showWhen: true
|
showWhen: true,
|
||||||
|
visibility: undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user