Compare commits

...

13 Commits

Author SHA1 Message Date
Dave Umrysh
361358a458 revert back to android support lib 2021-02-23 13:15:43 -07:00
Nathan Kerr
df990e762f Merged in kerr/migrate-to-androidx (pull request #6)
Change from support library to androidx
2020-11-16 18:37:13 +00:00
Nathan Kerr
b33044c8e5 Merge branch 'master' of bitbucket.org:TheBosZ/cordova-plugin-run-in-background 2020-06-08 12:19:15 -07:00
Nathan Kerr
4d98947310 Add fix for moveToForeground. Requires new permission for Android 10 2020-06-08 12:19:04 -07:00
Jesper Charles Balslev
77767cab9b Merged in JesperBalslev/cordova-plugin-run-in-background (pull request #5)
Prevent sound/music from stopping when opening the app on iOS. Also prevents embedded videos (youtube) from pausing when unmuted.

* Previous fix wasn't backwards compatible with versions older than 12.2. This fixes it.

* Fixes iOS issues with backgroundMode.onactivate and backgroundMode.ondeactivate

* Prevent sound/music from stopping when opening the app on iOS. Also prevents embedded videos (youtube) from pausing when unmuted.

Approved-by: Nathan Kerr <nathankerr@gmail.com>
2020-03-24 14:00:17 +00:00
Jesper Charles Balslev
1dab2de6ec Merged in JesperBalslev/cordova-plugin-run-in-background (pull request #4)
Fixes iOS issues with backgroundMode.onactivate and backgroundMode.ondeactivate
2019-12-12 17:28:49 +00:00
Nathan Kerr
5f50704564 Merge branch 'master' of bitbucket.org:TheBosZ/cordova-plugin-run-in-background 2019-11-08 07:45:51 -08:00
Nathan Kerr
8d523e638e Don't get the engine to get the view 2019-11-08 07:45:16 -08:00
Jesper Balslev
abb6b30cf8 Merged in JesperBalslev/cordova-plugin-run-in-background/Jesper-Balslev/previous-fix-wasnt-backwards-compatible--1572444052573 (pull request #3)
Previous fix wasn't backwards compatible with versions older than 12.2. This fixes it.

This fixes it.
2019-10-30 14:07:52 +00:00
Nathan Kerr
8ad9802ea6 Fall back to application's icon
Closes #10
2019-08-29 14:20:15 -07:00
Menardi
53f3278722 Merged in Menardi/cordova-plugin-run-in-background/android_optimization (pull request #2)
Add more Android battery optimisation functions

- Go to Battery Optimization settings screen
- Add function to check if battery optimization is enabled or not
2019-08-21 20:18:23 +00:00
Menardi
0da2006f7c Merged in Menardi/cordova-plugin-run-in-background/visibility (pull request #1)
Add ability to set Android notification visibility
2019-08-20 15:40:21 +00:00
Nathan Kerr
a3063aed68 Add information about battery optimizations 2019-07-31 18:48:02 +00:00
7 changed files with 189 additions and 13 deletions

View File

@ -79,7 +79,9 @@ cordova.plugins.backgroundMode.un('EVENT', function);
## Android specifics ## Android specifics
### 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();
@ -120,6 +122,37 @@ cordova.plugins.backgroundMode.wakeUp();
cordova.plugins.backgroundMode.unlock(); cordova.plugins.backgroundMode.unlock();
``` ```
### 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.
This method will show a permission prompt for the user (only if the app hasn't been granted permission) to ignore the optimization.
```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();
});
```
### Notification ### Notification
To indicate that the app is executing tasks in background and being paused would disrupt the user, the plug-in has to create a notification while in background - like a download progress bar. To indicate that the app is executing tasks in background and being paused would disrupt the user, the plug-in has to create a notification while in background - like a download progress bar.
@ -141,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))
}) })
``` ```
@ -166,7 +200,7 @@ Various APIs like playing media or tracking GPS position in background might not
```js ```js
cordova.plugins.backgroundMode.on('activate', function() { cordova.plugins.backgroundMode.on('activate', function() {
cordova.plugins.backgroundMode.disableWebViewOptimizations(); cordova.plugins.backgroundMode.disableWebViewOptimizations();
}); });
``` ```

View File

@ -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",
@ -42,4 +42,4 @@
"url": "https://github.com/katzer/cordova-plugin-background-mode/issues" "url": "https://github.com/katzer/cordova-plugin-background-mode/issues"
}, },
"homepage": "https://github.com/katzer/cordova-plugin-background-mode#readme" "homepage": "https://github.com/katzer/cordova-plugin-background-mode#readme"
} }

View File

@ -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

View 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.

View File

@ -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.
* *

View File

@ -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];
@ -221,8 +224,8 @@ 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];

View File

@ -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
}; };
/** /**