Skip to content

Fix app killing itself when opening deep links #517

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
  • Loading branch information
leonardo-fernandes committed Oct 25, 2020
commit e9d50f6a265a5cc06a89906b1f0f63441e0c8e1c
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.idea
53 changes: 47 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ cordova.plugins.backgroundMode.un('EVENT', function);
## Android specifics

### 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
cordova.plugins.backgroundMode.moveToBackground();
Expand Down Expand Up @@ -135,6 +137,37 @@ cordova.plugins.backgroundMode.wakeUp();
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
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.

Expand All @@ -145,11 +178,19 @@ The title, text and icon for that notification can be customized as below. Also,
cordova.plugins.backgroundMode.setDefaults({
title: String,
text: String,
icon: 'icon' // this will look for icon.png in platforms/android/res/drawable|mipmap
color: String // hex format like 'F14F4D'
subText: String, // see https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#setSubText(java.lang.CharSequence)
icon: 'icon', // this will look for icon.png in platforms/android/res/drawable|mipmap
color: String, // hex format like 'F14F4D'
resume: Boolean,
hidden: Boolean,
bigText: Boolean
bigText: Boolean,
channelName: String, // Shown when the user views the app's notification settings
channelDescription: String, // Shown when the user views the channel's settings
allowClose: Boolean, // add a "Close" action to the notification
closeIcon: 'power', // An icon shown for the close action
closeTitle: 'Close', // The text for the close action
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))
})
```

Expand All @@ -174,7 +215,7 @@ Various APIs like playing media or tracking GPS position in background might not

```js
cordova.plugins.backgroundMode.on('activate', function() {
cordova.plugins.backgroundMode.disableWebViewOptimizations();
cordova.plugins.backgroundMode.disableWebViewOptimizations();
});
```

Expand Down Expand Up @@ -205,4 +246,4 @@ Made with :yum: from Leipzig
[changelog]: CHANGELOG.md
[apache2_license]: http://opensource.org/licenses/Apache-2.0
[appplant]: http://appplant.de
[meshfields]: http://meshfields.de
[meshfields]: http://meshfields.de
10 changes: 10 additions & 0 deletions plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@

<config-file target="AndroidManifest.xml" parent="/manifest">
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
</config-file>

<source-file
Expand All @@ -89,6 +92,13 @@
<source-file
src="src/android/ForegroundService.java"
target-dir="src/de/appplant/cordova/plugin/background" />

<framework src="com.android.support:support-compat:27.1.1" />
<resource-file src="src/android/res/drawable/power.xml" target="res/drawable/power.xml" />
<resource-file src="src/android/res/drawable-hdpi/power.png" target="res/drawable-hdpi/power.png" />
<resource-file src="src/android/res/drawable-mdpi/power.png" target="res/drawable-mdpi/power.png" />
<resource-file src="src/android/res/drawable-xhdpi/power.png" target="res/drawable-xhdpi/power.png" />
<resource-file src="src/android/res/drawable-xxhdpi/power.png" target="res/drawable-xxhdpi/power.png" />
</platform>

<!-- browser -->
Expand Down
26 changes: 23 additions & 3 deletions src/android/BackgroundMode.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ Licensed to the Apache Software Foundation (ASF) under one
package de.appplant.cordova.plugin.background;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.*;
import android.os.Bundle;
import android.os.IBinder;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONObject;

Expand Down Expand Up @@ -77,6 +78,24 @@ public void onServiceDisconnected (ComponentName name)
}
};

@Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
IntentFilter filter = new IntentFilter();
filter.addAction("com.backgroundmode.close" + cordova.getContext().getPackageName());
cordova.getActivity().registerReceiver(receiver, filter);

}

private BroadcastReceiver receiver = new BroadcastReceiver() {

@Override
public void onReceive(Context context, Intent intent) {
cordova.getActivity().finish();

}
};

/**
* Executes the request.
*
Expand Down Expand Up @@ -160,6 +179,7 @@ public void onResume (boolean multitasking)
public void onDestroy()
{
stopService();
android.os.Process.killProcess(android.os.Process.myPid());
}

/**
Expand Down
60 changes: 59 additions & 1 deletion src/android/BackgroundModeExt.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Licensed to the Apache Software Foundation (ASF) under one
import android.net.Uri;
import android.os.Build;
import android.os.PowerManager;
import android.provider.Settings;
import android.view.View;

import org.apache.cordova.CallbackContext;
Expand All @@ -55,6 +56,7 @@ Licensed to the Apache Software Foundation (ASF) under one
import static android.os.Build.VERSION.SDK_INT;
import static android.os.Build.VERSION_CODES.M;
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_DISMISS_KEYGUARD;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
Expand Down Expand Up @@ -90,6 +92,12 @@ public boolean execute (String action, JSONArray args,
case "battery":
disableBatteryOptimizations();
break;
case "batterysettings":
openBatterySettings();
break;
case "optimizationstatus":
isIgnoringBatteryOptimizations(callback);
break;
case "webview":
disableWebViewOptimizations();
break;
Expand All @@ -102,6 +110,9 @@ public boolean execute (String action, JSONArray args,
case "foreground":
moveToForeground();
break;
case "requestTopPermissions":
requestTopPermissions();
break;
case "tasklist":
excludeFromTaskList();
break;
Expand Down Expand Up @@ -166,7 +177,7 @@ public void run() {
try {
Thread.sleep(1000);
getApp().runOnUiThread(() -> {
View view = webView.getEngine().getView();
View view = webView.getView();

try {
Class.forName("org.crosswalk.engine.XWalkCordovaView")
Expand Down Expand Up @@ -209,6 +220,53 @@ private void disableBatteryOptimizations()
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
* custom app start settings added by the manufacturer if available.
Expand Down
Loading