Skip to content
This repository was archived by the owner on Sep 4, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ All iOS boolean options can also be specified as `string`
| `ios.sound` | `boolean` | `false` | Optional. If `true` the device plays a sound on receipt of notification. **Note:** the value you set this option to the first time you call the init method will be how the application always acts. Once this is set programmatically in the init method it can only be changed manually by the user in Settings>Notifications>`App Name`. This is normal iOS behaviour. |
| `ios.clearBadge` | `boolean` | `false` | Optional. If `true` the badge will be cleared on app startup. |
| `ios.categories` | `Object` | `{}` | Optional. The data required in order to enable Action Buttons for iOS. See [Action Buttons on iOS](https://github.com/phonegap/phonegap-plugin-push/blob/master/docs/PAYLOAD.md#action-buttons-1) for more details. |
| `ios.critical` | `boolean` | `false` | Optional. If `true` the device can show up critical alerts. (Possible since iOS 12 with a special entitlement) **Note:** the value you set this option to the first time you call the init method will be how the application always acts. Once this is set programmatically in the init method it can only be changed manually by the user in Settings>Notifications>`App Name`. This is normal iOS behaviour. |

#### iOS GCM support

Expand Down
31 changes: 31 additions & 0 deletions docs/PAYLOAD.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,37 @@ The JSON message can contain the following fields, see [Apple developer docs](ht
}
```

### Speical Format for Critical Alerts

Since iOS 12 it's possible to send critical alerts to the users device. A critical alert will popup and play sound even when device is in DND Mode or muted. This functionallity is mainly to be used by health Apps to inform about critical states.
Instead of the name of the sound you have to send a dictionary containing further information about critical

```json
{
"aps": {
"alert": {
// alternatively just a string: "Your Message",
"title": "A short string describing the purpose of the notification",
"body": "The text of the alert message",
// localization of message is possible
"launch-image": "The filename of an image file in the app bundle, with or without the filename extension. The image is used as the launch image when users tap the action button or move the action slider"
},
"badge": 5, // Number to show at App icon
"content-available": "0", // configure background updates, see below
"category": "identifier", // Provide this key with a string value that represents the notification’s type
"thread-id": "id", // Provide this key with a string value that represents the app-specific identifier for grouping notifications
"sound": {
"critical" : 1, // When 1, the notification is handled as a critical one. The sound is played aloud even when device is in dnd mode or muted
"name" : "default", // play default sound, or custom sound, see [iOS Sound](#sound-1) section
"volume" : 1.0 // Optional: Volume. Value can between 0.0 (silent) and 1.0 (full volume)
}
},
"notId": 1,
"custom_key1": "value1",
"custom_key2": "value2"
}
```

### Using AWS-SNS with APNS

This is the JSON-encoded format you can send via AWS-SNS's web UI:
Expand Down
117 changes: 114 additions & 3 deletions src/android/com/adobe/phonegap/push/FCMService.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
import android.text.Html;
import android.text.Spanned;
import android.util.Log;
import android.media.MediaPlayer;
import android.os.Vibrator;
import android.media.AudioManager;
import android.media.AudioAttributes;
import android.os.VibrationEffect;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
Expand All @@ -53,6 +58,10 @@ public class FCMService extends FirebaseMessagingService implements PushConstant

private static final String LOG_TAG = "Push_FCMService";
private static HashMap<Integer, ArrayList<String>> messageMap = new HashMap<Integer, ArrayList<String>>();

public FCMService() {

}

public void setNotification(int notId, String message) {
ArrayList<String> messageList = messageMap.get(notId);
Expand Down Expand Up @@ -415,6 +424,8 @@ public void createNotification(Context context, Bundle extras) {
} else {
mBuilder = new NotificationCompat.Builder(context);
}

mBuilder.setCategory(NotificationCompat.CATEGORY_ALARM);

mBuilder.setWhen(System.currentTimeMillis()).setContentTitle(fromHtml(extras.getString(TITLE)))
.setTicker(fromHtml(extras.getString(TITLE))).setContentIntent(contentIntent).setDeleteIntent(deleteIntent)
Expand All @@ -425,6 +436,8 @@ public void createNotification(Context context, Bundle extras) {
String localIconColor = prefs.getString(ICON_COLOR, null);
boolean soundOption = prefs.getBoolean(SOUND, true);
boolean vibrateOption = prefs.getBoolean(VIBRATE, true);
boolean isAlarm = Boolean.parseBoolean(extras.getString(ISALARM, "false"));

Log.d(LOG_TAG, "stored icon=" + localIcon);
Log.d(LOG_TAG, "stored iconColor=" + localIconColor);
Log.d(LOG_TAG, "stored sound=" + soundOption);
Expand All @@ -434,8 +447,16 @@ public void createNotification(Context context, Bundle extras) {
* Notification Vibration
*/

setNotificationVibration(extras, vibrateOption, mBuilder);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
setNotificationVibrationExternal(extras, vibrateOption, mBuilder);
} else {
setNotificationVibration(extras, vibrateOption, mBuilder);
}




/*
* Notification Icon Color
*
Expand Down Expand Up @@ -477,7 +498,17 @@ public void createNotification(Context context, Bundle extras) {
* Notification Sound
*/
if (soundOption) {
setNotificationSound(context, extras, mBuilder);

/* Check is isAlarm Notification */

Log.d(LOG_TAG, "isAlarm = " + String.valueOf(isAlarm));

if(!isAlarm)
{

}

//setNotificationSound(context, extras, mBuilder);
}

/*
Expand Down Expand Up @@ -516,6 +547,68 @@ public void createNotification(Context context, Bundle extras) {
createActions(extras, mBuilder, resources, packageName, notId);

mNotificationManager.notify(appName, notId, mBuilder.build());

if (soundOption) {

String soundname = extras.getString(SOUNDNAME);
if (soundname == null) {
soundname = extras.getString(SOUND);
}

MediaPlayer mMediaPlayer;
try {

mMediaPlayer = new MediaPlayer();

if (SOUND_RINGTONE.equals(soundname)) {
mMediaPlayer.setDataSource(this.getApplicationContext(), android.provider.Settings.System.DEFAULT_RINGTONE_URI);
} else if (soundname != null && !soundname.contentEquals(SOUND_DEFAULT)) {
Uri sound = Uri
.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() + "/raw/" + soundname);
Log.d(LOG_TAG, sound.toString());
mMediaPlayer.setDataSource(this.getApplicationContext(), sound);
} else {
mMediaPlayer.setDataSource(this.getApplicationContext(), android.provider.Settings.System.DEFAULT_NOTIFICATION_URI);
}

if(isAlarm) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_ALARM)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
mMediaPlayer.setAudioAttributes(audioAttributes);
} else {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION_EVENT)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
mMediaPlayer.setAudioAttributes(audioAttributes);
} else {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
}
}


mMediaPlayer.setLooping(false);
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mMediaPlayer.start();
}
});
} catch (SecurityException | IOException e) {

}
}

}

private void updateIntent(Intent intent, String callback, Bundle extras, boolean foreground, int notId) {
Expand Down Expand Up @@ -633,6 +726,23 @@ private void setVisibility(Context context, Bundle extras, NotificationCompat.Bu
}
}

private void setNotificationVibrationExternal(Bundle extras, Boolean vibrateOption, NotificationCompat.Builder mBuilder) {
String vibrationPattern = extras.getString(VIBRATION_PATTERN);
if (vibrationPattern != null) {
String[] items = vibrationPattern.replaceAll("\\[", "").replaceAll("\\]", "").split(",");
long[] results = new long[items.length];
for (int i = 0; i < items.length; i++) {
try {
results[i] = Long.parseLong(items[i].trim());
} catch (NumberFormatException nfe) {
}
}

Vibrator vibrator = (Vibrator)this.getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(VibrationEffect.createWaveform(results, -1));
}
}

private void setNotificationVibration(Bundle extras, Boolean vibrateOption, NotificationCompat.Builder mBuilder) {
String vibrationPattern = extras.getString(VIBRATION_PATTERN);
if (vibrationPattern != null) {
Expand Down Expand Up @@ -728,6 +838,7 @@ private void setNotificationMessage(int notId, Bundle extras, NotificationCompat
}
}


private void setNotificationSound(Context context, Bundle extras, NotificationCompat.Builder mBuilder) {
String soundname = extras.getString(SOUNDNAME);
if (soundname == null) {
Expand Down Expand Up @@ -947,4 +1058,4 @@ private boolean isAvailableSender(String from) {

return from.equals(savedSenderID) || from.startsWith("/topics/");
}
}
}
2 changes: 2 additions & 0 deletions src/android/com/adobe/phonegap/push/PushConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public interface PushConstants {
public static final String SOUND = "sound";
public static final String SOUND_DEFAULT = "default";
public static final String SOUND_RINGTONE = "ringtone";
public static final String SOUND_NONE = "none";
public static final String VIBRATE = "vibrate";
public static final String ACTIONS = "actions";
public static final String CALLBACK = "callback";
Expand Down Expand Up @@ -102,4 +103,5 @@ public interface PushConstants {
public static final String ONGOING = "ongoing";
public static final String LIST_CHANNELS = "listChannels";
public static final String CLEAR_NOTIFICATION = "clearNotification";
public static final String ISALARM = "isAlarm";
}
2 changes: 2 additions & 0 deletions src/android/com/adobe/phonegap/push/PushPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ private void createChannel(JSONObject channel) throws JSONException {
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE).build();
if (SOUND_RINGTONE.equals(sound)) {
mChannel.setSound(android.provider.Settings.System.DEFAULT_RINGTONE_URI, audioAttributes);
} else if (SOUND_NONE.equals(sound)) {
mChannel.setSound(null, null);
} else if (sound != null && sound.isEmpty()) {
// Disable sound for this notification channel if an empty string is passed.
// https://stackoverflow.com/a/47144981/6194193
Expand Down
6 changes: 6 additions & 0 deletions src/ios/PushPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ - (void)init:(CDVInvokedUrlCommand*)command;
id badgeArg = [iosOptions objectForKey:@"badge"];
id soundArg = [iosOptions objectForKey:@"sound"];
id alertArg = [iosOptions objectForKey:@"alert"];
id criticalArg = [iosOptions objectForKey:@"critical"];
id clearBadgeArg = [iosOptions objectForKey:@"clearBadge"];

if (([badgeArg isKindOfClass:[NSString class]] && [badgeArg isEqualToString:@"true"]) || [badgeArg boolValue])
Expand All @@ -218,6 +219,11 @@ - (void)init:(CDVInvokedUrlCommand*)command;
{
authorizationOptions |= UNAuthorizationOptionAlert;
}

if ((([criticalArg isKindOfClass:[NSString class]] && [criticalArg isEqualToString:@"true"]) || [criticalArg boolValue]) && @available(iOS 12.0, *))
{
authorizationOptions |= UNAuthorizationOptionCriticalAlert;
}

if (clearBadgeArg == nil || ([clearBadgeArg isKindOfClass:[NSString class]] && [clearBadgeArg isEqualToString:@"false"]) || ![clearBadgeArg boolValue]) {
NSLog(@"PushPlugin.register: setting badge to false");
Expand Down