Add Android-specific options

Now the app can:
-Set the channel name and description
-Set the notification subtext
-Add a "Close" action to the notification, along with customizing the action text and icon

Fixed bugs:
-Icon is never used if it's in "drawable" rather than "mipmap"
-Used "Compat" library to make backwards compatibility easier
This commit is contained in:
Nathan Kerr 2019-02-04 11:18:34 -08:00
parent b5950b578d
commit 32de5cb848
11 changed files with 121 additions and 52 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.idea

View File

@ -145,11 +145,17 @@ 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
})
```

View File

@ -88,6 +88,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>
<!-- windows

View File

@ -22,13 +22,14 @@
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.JSONException;
import org.json.JSONObject;
@ -39,6 +40,8 @@ import static android.content.Context.BIND_AUTO_CREATE;
public class BackgroundMode extends CordovaPlugin {
// Event types for callbacks
private enum Event {
ACTIVATE, DEACTIVATE, FAILURE
@ -77,6 +80,24 @@ public class BackgroundMode extends CordovaPlugin {
}
};
@Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
IntentFilter filter = new IntentFilter();
filter.addAction("com.backgroundmode.close");
cordova.getActivity().registerReceiver(receiver, filter);
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
cordova.getActivity().finish();
}
};
@Override
protected void pluginInitialize() {
BackgroundExt.addWindowFlags(cordova.getActivity());

View File

@ -19,20 +19,17 @@
package de.appplant.cordova.plugin.background;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.app.*;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.drawable.Icon;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.PowerManager;
import android.app.NotificationChannel;
import org.json.JSONObject;
import android.support.v4.app.NotificationCompat;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
@ -63,7 +60,6 @@ public class ForegroundService extends Service {
// Partial wake lock to prevent the app from going to sleep when locked
private PowerManager.WakeLock wakeLock;
private final String CHANNEL_ID = "cordova-plugin-background-mode-id";
/**
* Allow clients to call on to the service.
*/
@ -153,15 +149,16 @@ public class ForegroundService extends Service {
*/
private Notification makeNotification(JSONObject settings) {
// use channelid for Oreo and higher
if(Build.VERSION.SDK_INT >= 26){
String CHANNEL_ID = "cordova-plugin-background-mode-id";
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// The user-visible name of the channel.
CharSequence name = "cordova-plugin-background-mode";
CharSequence name = settings.optString("channelName", "cordova-plugin-background-mode");
// The user-visible description of the channel.
String description = "cordova-plugin-background-moden notification";
String description = settings.optString("channelDescription", "cordova-plugin-background-moden notification");
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel mChannel = new NotificationChannel(this.CHANNEL_ID, name,importance);
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, importance);
// Configure the notification channel.
mChannel.setDescription(description);
@ -171,20 +168,30 @@ public class ForegroundService extends Service {
String title = settings.optString("title", NOTIFICATION_TITLE);
String text = settings.optString("text", NOTIFICATION_TEXT);
boolean bigText = settings.optBoolean("bigText", false);
String subText = settings.optString("subText", "");
Context context = getApplicationContext();
String pkgName = context.getPackageName();
Intent intent = context.getPackageManager()
.getLaunchIntentForPackage(pkgName);
Notification.Builder notification = new Notification.Builder(context)
NotificationCompat.Builder notification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setContentTitle(title)
.setContentText(text)
.setOngoing(true)
.setSmallIcon(getIconResId(settings));
if(Build.VERSION.SDK_INT >= 26){
notification.setChannelId(this.CHANNEL_ID);
if (!subText.equals("")) {
notification.setSubText(subText);
}
if (settings.optBoolean("allowClose", false)) {
final Intent clostAppIntent = new Intent("com.backgroundmode.close");
final PendingIntent closeIntent = PendingIntent.getBroadcast(context, 1337, clostAppIntent, 0);
final String closeIconName = settings.optString("closeIcon", "power");
NotificationCompat.Action.Builder closeAction = new NotificationCompat.Action.Builder(getIconResId(closeIconName), settings.optString("closeTitle", "Close"), closeIntent);
notification.addAction(closeAction.build());
}
if (settings.optBoolean("hidden", true)) {
@ -193,7 +200,7 @@ public class ForegroundService extends Service {
if (bigText || text.contains("\n")) {
notification.setStyle(
new Notification.BigTextStyle().bigText(text));
new NotificationCompat.BigTextStyle().bigText(text));
}
setColor(notification, settings);
@ -229,6 +236,31 @@ public class ForegroundService extends Service {
}
/**
* Retrieves the resource ID of the sent icon name
*
* @param name Name of the resource to return
*/
private int getIconResId(String name) {
// cordova-android 6 uses mipmaps
int resId = getIconResId(name, "mipmap");
if (resId == 0) {
resId = getIconResId(name, "drawable");
}
if (resId == 0) {
resId = getIconResId("icon", "mipmap");
}
if (resId == 0) {
resId = getIconResId("icon", "drawable");
}
return resId;
}
/**
* Retrieves the resource ID of the app icon.
*
@ -237,14 +269,7 @@ public class ForegroundService extends Service {
private int getIconResId(JSONObject settings) {
String icon = settings.optString("icon", NOTIFICATION_ICON);
// cordova-android 6 uses mipmaps
int resId = getIconResId(icon, "mipmap");
if (resId == 0) {
resId = getIconResId(icon, "drawable");
}
return resId;
return getIconResId(icon);
}
/**
@ -259,13 +284,7 @@ public class ForegroundService extends Service {
Resources res = getResources();
String pkgName = getPackageName();
int resId = res.getIdentifier(icon, type, pkgName);
if (resId == 0) {
resId = res.getIdentifier("icon", type, pkgName);
}
return resId;
return res.getIdentifier(icon, type, pkgName);
}
/**
@ -275,7 +294,7 @@ public class ForegroundService extends Service {
* @param settings A JSON dict containing the color definition (red: FF0000)
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void setColor(Notification.Builder notification,
private void setColor(NotificationCompat.Builder notification,
JSONObject settings) {
String hex = settings.optString("color", null);

Binary file not shown.

After

Width:  |  Height:  |  Size: 734 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
android:pathData="M13,3h-2v10h2L13,3zM17.83,5.17l-1.42,1.42C17.99,7.86 19,9.81 19,12c0,3.87 -3.13,7 -7,7s-7,-3.13 -7,-7c0,-2.19 1.01,-4.14 2.58,-5.42L6.17,5.17C4.23,6.82 3,9.26 3,12c0,4.97 4.03,9 9,9s9,-4.03 9,-9c0,-2.74 -1.23,-5.18 -3.17,-6.83z"/>
</vector>

View File

@ -384,12 +384,18 @@ exports._isActive = false;
exports._defaults = {
title: 'App is running in background',
text: 'Doing heavy tasks.',
subText: '',
bigText: false,
resume: true,
silent: false,
hidden: true,
color: undefined,
icon: 'icon'
icon: 'icon',
channelName: 'cordova-plugin-background-mode',
channelDescription: 'cordova-plugin-background-moden notification',
allowClose: false,
closeIcon: 'power',
closeTitle: 'Close'
};
/**