Skip to content

Commit

Permalink
feat(LocalNotifications): add createChannel, deleteChannel and listCh…
Browse files Browse the repository at this point in the history
…annels methods (#2676)
  • Loading branch information
dwlrathod authored Apr 3, 2020
1 parent 93eb9aa commit d72e25d
Show file tree
Hide file tree
Showing 9 changed files with 215 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.getcapacitor.plugin.notification.LocalNotification;
import com.getcapacitor.plugin.notification.LocalNotificationManager;
import com.getcapacitor.plugin.notification.NotificationAction;
import com.getcapacitor.plugin.notification.NotificationChannelManager;
import com.getcapacitor.plugin.notification.NotificationStorage;

import org.json.JSONArray;
Expand All @@ -29,6 +30,7 @@
public class LocalNotifications extends Plugin {
private LocalNotificationManager manager;
private NotificationStorage notificationStorage;
private NotificationChannelManager notificationChannelManager;

public LocalNotifications() {
}
Expand All @@ -39,6 +41,7 @@ public void load() {
notificationStorage = new NotificationStorage(getContext());
manager = new LocalNotificationManager(notificationStorage, getActivity());
manager.createNotificationChannel();
notificationChannelManager = new NotificationChannelManager(getActivity());
}

@Override
Expand Down Expand Up @@ -118,5 +121,20 @@ public void areEnabled(PluginCall call) {
call.success(data);
}

@PluginMethod()
public void createChannel(PluginCall call) {
notificationChannelManager.createChannel(call);
}

@PluginMethod()
public void deleteChannel(PluginCall call) {
notificationChannelManager.deleteChannel(call);
}

@PluginMethod()
public void listChannels(PluginCall call) {
notificationChannelManager.listChannels(call);
}

}

Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
package com.getcapacitor.plugin;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.media.AudioAttributes;
import android.os.Build;
import android.os.Bundle;
import android.service.notification.StatusBarNotification;
import androidx.core.app.NotificationCompat;
import android.net.Uri;

import android.util.Log;

import com.getcapacitor.Bridge;
import com.getcapacitor.JSArray;
import com.getcapacitor.JSObject;
Expand All @@ -24,6 +17,7 @@
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginHandle;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.plugin.notification.NotificationChannelManager;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.iid.FirebaseInstanceId;
Expand All @@ -35,26 +29,15 @@
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@NativePlugin()
public class PushNotifications extends Plugin {

public static String CHANNEL_ID = "id";
public static String CHANNEL_NAME = "name";
public static String CHANNEL_DESCRIPTION = "description";
public static String CHANNEL_IMPORTANCE = "importance";
public static String CHANNEL_VISIBILITY = "visibility";
public static String CHANNEL_SOUND = "sound";
public static String CHANNEL_USE_LIGHTS = "lights";
public static String CHANNEL_LIGHT_COLOR = "lightColor";

public static Bridge staticBridge = null;
public static RemoteMessage lastMessage = null;
public NotificationManager notificationManager;

private NotificationChannelManager notificationChannelManager;

private static final String EVENT_TOKEN_CHANGE = "registration";
private static final String EVENT_TOKEN_ERROR = "registrationError";
Expand All @@ -67,6 +50,7 @@ public void load() {
fireNotification(lastMessage);
lastMessage = null;
}
notificationChannelManager = new NotificationChannelManager(getActivity(), notificationManager);
}

@Override
Expand Down Expand Up @@ -187,85 +171,17 @@ public void removeAllDeliveredNotifications(PluginCall call) {

@PluginMethod()
public void createChannel(PluginCall call) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
JSObject channel = new JSObject();
channel.put(CHANNEL_ID, call.getString(CHANNEL_ID));
channel.put(CHANNEL_NAME, call.getString(CHANNEL_NAME));
channel.put(CHANNEL_DESCRIPTION, call.getString(CHANNEL_DESCRIPTION, ""));
channel.put(CHANNEL_VISIBILITY, call.getInt(CHANNEL_VISIBILITY, NotificationCompat.VISIBILITY_PUBLIC));
channel.put(CHANNEL_IMPORTANCE, call.getInt(CHANNEL_IMPORTANCE));
channel.put(CHANNEL_SOUND, call.getString(CHANNEL_SOUND, null));
channel.put(CHANNEL_USE_LIGHTS, call.getBoolean(CHANNEL_USE_LIGHTS, false));
channel.put(CHANNEL_LIGHT_COLOR, call.getString(CHANNEL_LIGHT_COLOR, null));
createChannel(channel);
call.success();
} else {
call.unavailable();
}
notificationChannelManager.createChannel(call);
}

@PluginMethod()
public void deleteChannel(PluginCall call) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
String channelId = call.getString("id");
notificationManager.deleteNotificationChannel(channelId);
call.success();
} else {
call.unavailable();
}
notificationChannelManager.deleteChannel(call);
}

@PluginMethod()
public void listChannels(PluginCall call) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
List<NotificationChannel> notificationChannels = notificationManager.getNotificationChannels();
JSArray channels = new JSArray();
for (NotificationChannel notificationChannel : notificationChannels) {
JSObject channel = new JSObject();
channel.put(CHANNEL_ID, notificationChannel.getId());
channel.put(CHANNEL_NAME, notificationChannel.getName());
channel.put(CHANNEL_DESCRIPTION, notificationChannel.getDescription());
channel.put(CHANNEL_IMPORTANCE, notificationChannel.getImportance());
channel.put(CHANNEL_VISIBILITY, notificationChannel.getLockscreenVisibility());
channel.put(CHANNEL_SOUND, notificationChannel.getSound());
channel.put(CHANNEL_USE_LIGHTS, notificationChannel.shouldShowLights());
channel.put(CHANNEL_LIGHT_COLOR, String.format("#%06X", (0xFFFFFF & notificationChannel.getLightColor())));
Log.d(getLogTag(), "visibility " + notificationChannel.getLockscreenVisibility());
Log.d(getLogTag(), "importance " + notificationChannel.getImportance());
channels.put(channel);
}
JSObject result = new JSObject();
result.put("channels", channels);
call.success(result);
} else {
call.unavailable();
}
}

private void createChannel(JSObject channel) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel notificationChannelChannel = new NotificationChannel(channel.getString(CHANNEL_ID), channel.getString(CHANNEL_NAME), channel.getInteger(CHANNEL_IMPORTANCE));
notificationChannelChannel.setDescription(channel.getString(CHANNEL_DESCRIPTION));
notificationChannelChannel.setLockscreenVisibility(channel.getInteger(CHANNEL_VISIBILITY));
notificationChannelChannel.enableLights(channel.getBool(CHANNEL_USE_LIGHTS));
String lightColor = channel.getString(CHANNEL_LIGHT_COLOR);
if (lightColor != null) {
try {
notificationChannelChannel.setLightColor(Color.parseColor(lightColor));
} catch (IllegalArgumentException ex) {
Log.e(getLogTag(), "Invalid color provided for light color.");
}
}
String sound = channel.getString(CHANNEL_SOUND, null);
if (sound != null && !sound.isEmpty()) {
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM).build();
Uri soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + getContext().getPackageName() + "/raw/" + sound);
notificationChannelChannel.setSound(soundUri, audioAttributes);
}
notificationManager.createNotificationChannel(notificationChannelChannel);
}
notificationChannelManager.listChannels(call);
}

public void sendToken(String token) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public class LocalNotification {
private JSObject extra;
private List<LocalNotificationAttachment> attachments;
private LocalNotificationSchedule schedule;
private String channelId;

private String source;

Expand Down Expand Up @@ -157,6 +158,14 @@ public void setGroupSummary(boolean groupSummary) {
this.groupSummary = groupSummary;
}

public String getChannelId() {
return channelId;
}

public void setChannelId(String channelId) {
this.channelId = channelId;
}

/**
* Build list of the notifications from remote plugin call
*/
Expand Down Expand Up @@ -195,6 +204,7 @@ public static List<LocalNotification> buildNotificationList(PluginCall call) {
activeLocalNotification.setIconColor(notification.getString("iconColor"));
activeLocalNotification.setAttachments(LocalNotificationAttachment.getAttachments(notification));
activeLocalNotification.setGroupSummary(notification.getBoolean("groupSummary", false));
activeLocalNotification.setChannelId(notification.getString("channelId"));
try {
activeLocalNotification.setSchedule(new LocalNotificationSchedule(notification));
} catch (ParseException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ public JSObject handleNotificationActionPerformed(Intent data, NotificationStora
* Create notification channel
*/
public void createNotificationChannel() {
// TODO allow to create multiple channels
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Expand Down Expand Up @@ -155,7 +154,11 @@ public JSONArray schedule(PluginCall call, List<LocalNotification> localNotifica
// TODO media style notification support NotificationCompat.MediaStyle
// TODO custom small/large icons
private void buildNotification(NotificationManagerCompat notificationManager, LocalNotification localNotification, PluginCall call) {
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this.context, DEFAULT_NOTIFICATION_CHANNEL_ID)
String channelId = DEFAULT_NOTIFICATION_CHANNEL_ID;
if (localNotification.getChannelId() != null) {
channelId = localNotification.getChannelId();
}
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this.context, channelId)
.setContentTitle(localNotification.getTitle())
.setContentText(localNotification.getBody())
.setAutoCancel(true)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package com.getcapacitor.plugin.notification;

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.ContentResolver;
import android.content.Context;
import android.graphics.Color;
import android.media.AudioAttributes;
import android.net.Uri;
import android.util.Log;


import androidx.core.app.NotificationCompat;

import com.getcapacitor.JSArray;
import com.getcapacitor.JSObject;
import com.getcapacitor.PluginCall;

import java.util.List;

public class NotificationChannelManager {

private Context context;
private NotificationManager notificationManager;

public NotificationChannelManager(Context context) {
this.context = context;
this.notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
}

public NotificationChannelManager(Context context, NotificationManager manager) {
this.context = context;
this.notificationManager = manager;
}

private static final String TAG = "NotificationChannel: ";


private static String CHANNEL_ID = "id";
private static String CHANNEL_NAME = "name";
private static String CHANNEL_DESCRIPTION = "description";
private static String CHANNEL_IMPORTANCE = "importance";
private static String CHANNEL_VISIBILITY = "visibility";
private static String CHANNEL_SOUND = "sound";
private static String CHANNEL_USE_LIGHTS = "lights";
private static String CHANNEL_LIGHT_COLOR = "lightColor";

public void createChannel(PluginCall call) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
JSObject channel = new JSObject();
channel.put(CHANNEL_ID, call.getString(CHANNEL_ID));
channel.put(CHANNEL_NAME, call.getString(CHANNEL_NAME));
channel.put(CHANNEL_DESCRIPTION, call.getString(CHANNEL_DESCRIPTION, ""));
channel.put(CHANNEL_VISIBILITY, call.getInt(CHANNEL_VISIBILITY, NotificationCompat.VISIBILITY_PUBLIC));
channel.put(CHANNEL_IMPORTANCE, call.getInt(CHANNEL_IMPORTANCE));
channel.put(CHANNEL_SOUND, call.getString(CHANNEL_SOUND, null));
channel.put(CHANNEL_USE_LIGHTS, call.getBoolean(CHANNEL_USE_LIGHTS, false));
channel.put(CHANNEL_LIGHT_COLOR, call.getString(CHANNEL_LIGHT_COLOR, null));
createChannel(channel);
call.success();
} else {
call.unavailable();
}
}
public void createChannel(JSObject channel) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(channel.getString(CHANNEL_ID), channel.getString(CHANNEL_NAME), channel.getInteger(CHANNEL_IMPORTANCE));
notificationChannel.setDescription(channel.getString(CHANNEL_DESCRIPTION));
notificationChannel.setLockscreenVisibility(channel.getInteger(CHANNEL_VISIBILITY));
notificationChannel.enableLights(channel.getBool(CHANNEL_USE_LIGHTS));
String lightColor = channel.getString(CHANNEL_LIGHT_COLOR);
if (lightColor != null) {
try {
notificationChannel.setLightColor(Color.parseColor(lightColor));
} catch (IllegalArgumentException ex) {
Log.e(TAG, "Invalid color provided for light color.");
}
}
String sound = channel.getString(CHANNEL_SOUND, null);
if (sound != null && !sound.isEmpty()) {
if (sound.contains(".")) {
sound = sound.substring(0, sound.lastIndexOf('.'));
}
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM).build();

This comment has been minimized.

Copy link
@dibyendusaha

dibyendusaha Apr 7, 2020

Contributor

@dwlrathod , I think it is better to replace AudioAttributes.USAGE_ALARM with either AudioAttributes.USAGE_NOTIFICATION or AudioAttributes.USAGE_NOTIFICATION_RINGTONE, because what I noticed that even if my phone is in vibrate or silent mode still it is playing sound and that is because of USAGE_ALARM.
@jcesarmobile , please let me know for any further clarification or if I can raise a PR for the same.

Uri soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() + "/raw/" + sound);
notificationChannel.setSound(soundUri, audioAttributes);
}
notificationManager.createNotificationChannel(notificationChannel);
}
}

public void deleteChannel(PluginCall call) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
String channelId = call.getString("id");
notificationManager.deleteNotificationChannel(channelId);
call.success();
} else {
call.unavailable();
}
}

public void listChannels(PluginCall call) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
List<NotificationChannel> notificationChannels = notificationManager.getNotificationChannels();
JSArray channels = new JSArray();
for (NotificationChannel notificationChannel : notificationChannels) {
JSObject channel = new JSObject();
channel.put(CHANNEL_ID, notificationChannel.getId());
channel.put(CHANNEL_NAME, notificationChannel.getName());
channel.put(CHANNEL_DESCRIPTION, notificationChannel.getDescription());
channel.put(CHANNEL_IMPORTANCE, notificationChannel.getImportance());
channel.put(CHANNEL_VISIBILITY, notificationChannel.getLockscreenVisibility());
channel.put(CHANNEL_SOUND, notificationChannel.getSound());
channel.put(CHANNEL_USE_LIGHTS, notificationChannel.shouldShowLights());
channel.put(CHANNEL_LIGHT_COLOR, String.format("#%06X", (0xFFFFFF & notificationChannel.getLightColor())));
Log.d(TAG, "visibility " + notificationChannel.getLockscreenVisibility());
Log.d(TAG, "importance " + notificationChannel.getImportance());
channels.put(channel);
}
JSObject result = new JSObject();
result.put("channels", channels);
call.success(result);
} else {
call.unavailable();
}
}
}
Loading

1 comment on commit d72e25d

@dibyendusaha
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as the above comment

@dwlrathod , I think it is better to replace AudioAttributes.USAGE_ALARM with either AudioAttributes.USAGE_NOTIFICATION or AudioAttributes.USAGE_NOTIFICATION_RINGTONE, because what I noticed that even if my phone is in vibrate or silent mode still it is playing sound and that is because of USAGE_ALARM.
@jcesarmobile , please let me know for any further clarification or if I can raise a PR for the same.

Please sign in to comment.