[notifications] Continue android implementation
This commit is contained in:
parent
99b4b6550b
commit
cd0ef4e3b7
|
@ -15,8 +15,8 @@ buildscript {
|
|||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 26
|
||||
buildToolsVersion "25.0.3"
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion "27.0.2"
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 26
|
||||
|
@ -82,6 +82,7 @@ rootProject.gradle.buildFinished { buildResult ->
|
|||
dependencies {
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
compile "com.facebook.react:react-native:+" // From node_modules
|
||||
compile "com.android.support:support-v4:27.0.2"
|
||||
compile 'me.leolin:ShortcutBadger:1.1.21@aar'
|
||||
compile "com.google.android.gms:play-services-base:$firebaseVersion"
|
||||
compile "com.google.firebase:firebase-core:$firebaseVersion"
|
||||
|
|
|
@ -42,23 +42,8 @@ public class RNFirebaseLocalMessagingHelper {
|
|||
sharedPreferences = mContext.getSharedPreferences(PREFERENCES_KEY, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
public void sendNotification(Bundle bundle) {
|
||||
|
||||
}
|
||||
|
||||
public void setApplicationForeground(boolean foreground){
|
||||
mIsForeground = foreground;
|
||||
}
|
||||
|
||||
private Class getMainActivityClass() {
|
||||
String packageName = mContext.getPackageName();
|
||||
Intent launchIntent = mContext.getPackageManager().getLaunchIntentForPackage(packageName);
|
||||
String className = launchIntent.getComponent().getClassName();
|
||||
try {
|
||||
return Class.forName(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,6 +155,9 @@ public class RNFirebaseMessaging extends ReactContextBaseJavaModule implements A
|
|||
FirebaseMessaging.getInstance().unsubscribeFromTopic(topic);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Start ActivityEventListener methods
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
|
||||
// FCM functionality does not need this function
|
||||
|
@ -168,6 +171,9 @@ public class RNFirebaseMessaging extends ReactContextBaseJavaModule implements A
|
|||
Utils.sendEvent(getReactApplicationContext(), "messaging_message_received", messageMap);
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// End ActivityEventListener methods
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
private WritableMap parseIntentForMessage(Intent intent) {
|
||||
// Check if FCM data exists
|
||||
|
|
|
@ -2,15 +2,12 @@ package io.invertase.firebase.notifications;
|
|||
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.Application;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
|
@ -19,6 +16,7 @@ import android.net.Uri;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
|
@ -29,7 +27,6 @@ import org.json.JSONException;
|
|||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
|
@ -39,9 +36,11 @@ import io.invertase.firebase.messaging.BundleJSONConverter;
|
|||
|
||||
public class RNFirebaseNotificationManager {
|
||||
private static final String PREFERENCES_KEY = "RNFNotifications";
|
||||
public static final String SCHEDULED_NOTIFICATION_EVENT = "notifications-scheduled-notification";
|
||||
private static final String TAG = "RNFNotificationManager";
|
||||
private AlarmManager alarmManager;
|
||||
private Context context;
|
||||
private boolean isForeground = false;
|
||||
private NotificationManager notificationManager;
|
||||
private SharedPreferences preferences;
|
||||
|
||||
|
@ -72,32 +71,100 @@ public class RNFirebaseNotificationManager {
|
|||
preferences.edit().remove(notificationId).apply();
|
||||
}
|
||||
|
||||
public void displayNotification(Bundle notification) {
|
||||
displayNotification(notification, null);
|
||||
}
|
||||
|
||||
public void displayNotification(ReadableMap notification, Promise promise) {
|
||||
Bundle notificationBundle = Arguments.toBundle(notification);
|
||||
displayNotification(notificationBundle, promise);
|
||||
}
|
||||
|
||||
public void displayScheduledNotification(Bundle notification) {
|
||||
// Broadcast the notification to the RN Application
|
||||
Intent scheduledNotificationEvent = new Intent(SCHEDULED_NOTIFICATION_EVENT);
|
||||
scheduledNotificationEvent.putExtra("notification", notification);
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(scheduledNotificationEvent);
|
||||
|
||||
// If this isn't a repeated notification, clear it from the scheduled notifications list
|
||||
if (!notification.getBundle("schedule").containsKey("repeated")
|
||||
|| !notification.getBundle("schedule").getBoolean("repeated")) {
|
||||
String notificationId = notification.getString("notificationId");
|
||||
preferences.edit().remove(notificationId).apply();;
|
||||
}
|
||||
|
||||
// If the app isn't in the foreground, then we display it
|
||||
// Otherwise, it is up to the JS to decide whether to send the notification
|
||||
if (!isForeground) {
|
||||
displayNotification(notification, null);
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<Bundle> getScheduledNotifications(){
|
||||
ArrayList<Bundle> array = new ArrayList<>();
|
||||
|
||||
Map<String, ?> notifications = preferences.getAll();
|
||||
|
||||
for(String notificationId : notifications.keySet()){
|
||||
try {
|
||||
JSONObject json = new JSONObject((String)notifications.get(notificationId));
|
||||
Bundle bundle = BundleJSONConverter.convertToBundle(json);
|
||||
array.add(bundle);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public void removeAllDeliveredNotifications() {
|
||||
notificationManager.cancelAll();
|
||||
}
|
||||
|
||||
public void removeDeliveredNotification(String notificationId) {
|
||||
notificationManager.cancel(notificationId.hashCode());
|
||||
}
|
||||
|
||||
|
||||
public void rescheduleNotifications() {
|
||||
ArrayList<Bundle> bundles = getScheduledNotifications();
|
||||
for(Bundle bundle: bundles){
|
||||
scheduleNotification(bundle, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void scheduleNotification(ReadableMap notification, Promise promise) {
|
||||
Bundle notificationBundle = Arguments.toBundle(notification);
|
||||
|
||||
scheduleNotification(notificationBundle, promise);
|
||||
}
|
||||
|
||||
public void setIsForeground(boolean isForeground) {
|
||||
this.isForeground = isForeground;
|
||||
}
|
||||
|
||||
private void cancelAlarm(String notificationId) {
|
||||
Intent notificationIntent = new Intent(context, RNFirebaseNotificationManager.class);
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, notificationId.hashCode(), notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
alarmManager.cancel(pendingIntent);
|
||||
}
|
||||
|
||||
private void displayNotification(Bundle notification, Promise promise) {
|
||||
try {
|
||||
Class intentClass = getMainActivityClass();
|
||||
if (intentClass == null) {
|
||||
if (promise != null) {
|
||||
promise.reject("notification/display_notification_error", "Could not find main activity class");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (bundle.getString("body") == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Resources res = mContext.getResources();
|
||||
String packageName = mContext.getPackageName();
|
||||
|
||||
String channelId = notification.getString("channelId");
|
||||
String notificationId = notification.getString("notificationId");
|
||||
|
||||
NotificationCompat.Builder nb = new NotificationCompat.Builder(context, channelId);
|
||||
NotificationCompat.Builder nb;
|
||||
// TODO: Change 27 to 'Build.VERSION_CODES.O_MR1' when using appsupport v27
|
||||
if (Build.VERSION.SDK_INT >= 27) {
|
||||
nb = new NotificationCompat.Builder(context, channelId);
|
||||
} else {
|
||||
nb = new NotificationCompat.Builder(context);
|
||||
}
|
||||
|
||||
if (notification.containsKey("body")) {
|
||||
nb = nb.setContentText(notification.getString("body"));
|
||||
|
@ -106,8 +173,16 @@ public class RNFirebaseNotificationManager {
|
|||
nb = nb.setExtras(notification.getBundle("data"));
|
||||
}
|
||||
if (notification.containsKey("sound")) {
|
||||
// TODO: Sound URI;
|
||||
nb = nb.setSound();
|
||||
String sound = notification.getString("sound");
|
||||
if (sound.equalsIgnoreCase("default")) {
|
||||
nb = nb.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
|
||||
} else {
|
||||
int soundResourceId = getResourceId("raw", sound);
|
||||
if (soundResourceId == 0) {
|
||||
soundResourceId = getResourceId("raw", sound.substring(0, sound.lastIndexOf('.')));
|
||||
}
|
||||
nb = nb.setSound(Uri.parse("android.resource://" + context.getPackageName() + "/" + soundResourceId));
|
||||
}
|
||||
}
|
||||
if (notification.containsKey("subtitle")) {
|
||||
nb = nb.setSubText(notification.getString("subtitle"));
|
||||
|
@ -126,7 +201,8 @@ public class RNFirebaseNotificationManager {
|
|||
nb = nb.setCategory(notification.getString("category"));
|
||||
}
|
||||
if (notification.containsKey("color")) {
|
||||
nb = nb.setColor(notification.getInt("color"));
|
||||
String color = notification.getString("color");
|
||||
nb = nb.setColor(Color.parseColor(color));
|
||||
}
|
||||
if (notification.containsKey("colorized")) {
|
||||
nb = nb.setColorized(notification.getBoolean("colorized"));
|
||||
|
@ -135,8 +211,12 @@ public class RNFirebaseNotificationManager {
|
|||
nb = nb.setContentInfo(notification.getString("contentInfo"));
|
||||
}
|
||||
if (notification.containsKey("defaults")) {
|
||||
// TODO: Bitwise ?
|
||||
nb = nb.setDefaults()
|
||||
int[] defaultsArray = notification.getIntArray("defaults");
|
||||
int defaults = 0;
|
||||
for (int d : defaultsArray) {
|
||||
defaults |= d;
|
||||
}
|
||||
nb = nb.setDefaults(defaults);
|
||||
}
|
||||
if (notification.containsKey("group")) {
|
||||
nb = nb.setGroup(notification.getString("group"));
|
||||
|
@ -183,12 +263,11 @@ public class RNFirebaseNotificationManager {
|
|||
Bundle progress = notification.getBundle("lights");
|
||||
nb = nb.setProgress(progress.getInt("max"), progress.getInt("progress"), progress.getBoolean("indeterminate"));
|
||||
}
|
||||
if (notification.containsKey("publicVersion")) {
|
||||
// TODO: Build notification
|
||||
// TODO: Public version of notification
|
||||
/* if (notification.containsKey("publicVersion")) {
|
||||
nb = nb.setPublicVersion();
|
||||
}
|
||||
} */
|
||||
if (notification.containsKey("remoteInputHistory")) {
|
||||
// TODO: Build notification
|
||||
nb = nb.setRemoteInputHistory(notification.getStringArray("remoteInputHistory"));
|
||||
}
|
||||
if (notification.containsKey("shortcutId")) {
|
||||
|
@ -198,7 +277,18 @@ public class RNFirebaseNotificationManager {
|
|||
nb = nb.setShowWhen(notification.getBoolean("showWhen"));
|
||||
}
|
||||
if (notification.containsKey("smallIcon")) {
|
||||
nb = nb.setSmallIcon(notification.getInt("smallIcon"));
|
||||
Bundle smallIcon = notification.getBundle("smallIcon");
|
||||
int smallIconResourceId = getResourceId("mipmap", smallIcon.getString("icon"));
|
||||
if (smallIconResourceId == 0) {
|
||||
smallIconResourceId = getResourceId("drawable", smallIcon.getString("icon"));
|
||||
}
|
||||
if (smallIconResourceId != 0) {
|
||||
if (smallIcon.containsKey("level")) {
|
||||
nb = nb.setSmallIcon(smallIconResourceId, smallIcon.getInt("level"));
|
||||
} else {
|
||||
nb = nb.setSmallIcon(smallIconResourceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (notification.containsKey("sortKey")) {
|
||||
nb = nb.setSortKey(notification.getString("sortKey"));
|
||||
|
@ -221,148 +311,109 @@ public class RNFirebaseNotificationManager {
|
|||
if (notification.containsKey("when")) {
|
||||
nb = nb.setWhen(notification.getLong("when"));
|
||||
}
|
||||
// TODO actions: Action[]; // icon, title, ??pendingIntent??, allowGeneratedReplies, extender, extras, remoteinput (ugh)
|
||||
// TODO: style: Style; // Need to figure out if this can work
|
||||
|
||||
//icon
|
||||
String smallIcon = bundle.getString("icon", "ic_launcher");
|
||||
int smallIconResId = res.getIdentifier(smallIcon, "mipmap", packageName);
|
||||
notification.setSmallIcon(smallIconResId);
|
||||
|
||||
//big text
|
||||
String bigText = bundle.getString("big_text");
|
||||
// TODO: Big text / Big picture
|
||||
/* String bigText = bundle.getString("big_text");
|
||||
if(bigText != null){
|
||||
notification.setStyle(new NotificationCompat.BigTextStyle().bigText(bigText));
|
||||
}
|
||||
String picture = bundle.getString("picture");
|
||||
if(picture!=null){
|
||||
NotificationCompat.BigPictureStyle bigPicture = new NotificationCompat.BigPictureStyle();
|
||||
|
||||
//sound
|
||||
String soundName = bundle.getString("sound", "default");
|
||||
if (!soundName.equalsIgnoreCase("default")) {
|
||||
int soundResourceId = res.getIdentifier(soundName, "raw", packageName);
|
||||
if(soundResourceId == 0){
|
||||
soundName = soundName.substring(0, soundName.lastIndexOf('.'));
|
||||
soundResourceId = res.getIdentifier(soundName, "raw", packageName);
|
||||
Bitmap pictureBitmap = getBitmap(picture);
|
||||
if (pictureBitmap != null) {
|
||||
bigPicture.bigPicture(pictureBitmap);
|
||||
}
|
||||
notification.setSound(Uri.parse("android.resource://" + packageName + "/" + soundResourceId));
|
||||
bigPicture.setBigContentTitle(title);
|
||||
bigPicture.setSummaryText(bundle.getString("body"));
|
||||
|
||||
notification.setStyle(bigPicture);
|
||||
} */
|
||||
|
||||
// Create the notification intent
|
||||
Intent intent = new Intent(context, intentClass);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
intent.putExtras(notification);
|
||||
if (notification.containsKey("clickAction")) {
|
||||
intent.setAction(notification.getString("clickAction"));
|
||||
}
|
||||
|
||||
//color
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
String color = bundle.getString("color");
|
||||
if (color != null) {
|
||||
notification.setColor(Color.parseColor(color));
|
||||
}
|
||||
}
|
||||
PendingIntent contentIntent = PendingIntent.getActivity(context, notificationId.hashCode(), intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
nb = nb.setContentIntent(contentIntent);
|
||||
|
||||
//lights
|
||||
if (bundle.getBoolean("lights")) {
|
||||
notification.setDefaults(NotificationCompat.DEFAULT_LIGHTS);
|
||||
}
|
||||
|
||||
Log.d(TAG, "broadcast intent before showing notification");
|
||||
Intent i = new Intent("io.invertase.firebase.messaging.ReceiveLocalNotification");
|
||||
i.putExtras(bundle);
|
||||
mContext.sendOrderedBroadcast(i, null);
|
||||
|
||||
if(!mIsForeground || bundle.getBoolean("show_in_foreground")){
|
||||
Intent intent = new Intent(mContext, intentClass);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
intent.putExtras(bundle);
|
||||
intent.setAction(bundle.getString("click_action"));
|
||||
|
||||
int notificationID = bundle.containsKey("id") ? bundle.getString("id", "").hashCode() : (int) System.currentTimeMillis();
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, notificationID, intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
notification.setContentIntent(pendingIntent);
|
||||
|
||||
Notification info = notification.build();
|
||||
|
||||
if (bundle.containsKey("tag")) {
|
||||
String tag = bundle.getString("tag");
|
||||
notificationManager.notify(tag, notificationID, info);
|
||||
} else {
|
||||
notificationManager.notify(notificationID, info);
|
||||
}
|
||||
}
|
||||
//clear out one time scheduled notification once fired
|
||||
if(!bundle.containsKey("repeat_interval") && bundle.containsKey("fire_date")) {
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.remove(bundle.getString("id"));
|
||||
editor.apply();
|
||||
}
|
||||
// Build the notification and send it
|
||||
Notification builtNotification = nb.build();
|
||||
notificationManager.notify(notificationId.hashCode(), builtNotification);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "failed to send local notification", e);
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<Bundle> getScheduledNotifications(){
|
||||
ArrayList<Bundle> array = new ArrayList<>();
|
||||
|
||||
Map<String, ?> notifications = preferences.getAll();
|
||||
|
||||
for(String notificationId : notifications.keySet()){
|
||||
try {
|
||||
JSONObject json = new JSONObject((String)notifications.get(notificationId));
|
||||
Bundle bundle = BundleJSONConverter.convertToBundle(json);
|
||||
array.add(bundle);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
if (promise == null) {
|
||||
Log.e(TAG, "Failed to send notification", e);
|
||||
} else {
|
||||
promise.reject("notification/display_notification_error", "Could not send notification", e);
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public void removeAllDeliveredNotifications() {
|
||||
notificationManager.cancelAll();
|
||||
}
|
||||
|
||||
public void removeDeliveredNotification(String notificationId) {
|
||||
notificationManager.cancel(notificationId.hashCode());
|
||||
}
|
||||
|
||||
|
||||
public void rescheduleNotifications() {
|
||||
ArrayList<Bundle> bundles = getScheduledNotifications();
|
||||
for(Bundle bundle: bundles){
|
||||
scheduleNotification(bundle, null);
|
||||
private Bitmap getBitmap(String image) {
|
||||
if (image.startsWith("http://") || image.startsWith("https://")) {
|
||||
return getBitmapFromUrl(image);
|
||||
} else {
|
||||
int largeIconResId = getResourceId("mipmap", image);
|
||||
return BitmapFactory.decodeResource(context.getResources(), largeIconResId);
|
||||
}
|
||||
}
|
||||
|
||||
public void scheduleNotification(ReadableMap notification, ReadableMap schedule, Promise promise) {
|
||||
Bundle notificationBundle = Arguments.toBundle(notification);
|
||||
private Bitmap getBitmapFromUrl(String imageUrl) {
|
||||
try {
|
||||
HttpURLConnection connection = (HttpURLConnection) new URL(imageUrl).openConnection();
|
||||
connection.setDoInput(true);
|
||||
connection.connect();
|
||||
return BitmapFactory.decodeStream(connection.getInputStream());
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to get bitmap for url: " + imageUrl, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
scheduleNotification(notificationBundle, promise);
|
||||
private Class getMainActivityClass() {
|
||||
String packageName = context.getPackageName();
|
||||
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName);
|
||||
try {
|
||||
return Class.forName(launchIntent.getComponent().getClassName());
|
||||
} catch (ClassNotFoundException e) {
|
||||
Log.e(TAG, "Failed to get main activity class", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private int getResourceId(String type, String image) {
|
||||
return context.getResources().getIdentifier(image, type, context.getPackageName());
|
||||
}
|
||||
|
||||
private void scheduleNotification(Bundle notification, Promise promise) {
|
||||
// TODO
|
||||
String notificationId = notification.getString("notificationId");
|
||||
if (!notification.containsKey("notificationId")) {
|
||||
if (promise != null) {
|
||||
promise.reject("notification/schedule_notification_error", "Missing notificationId");
|
||||
} else {
|
||||
if (promise == null) {
|
||||
Log.e(TAG, "Missing notificationId");
|
||||
} else {
|
||||
promise.reject("notification/schedule_notification_error", "Missing notificationId");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Schedule check
|
||||
if (!notification.hasKey("schedule")) {
|
||||
|
||||
if (!notification.containsKey("schedule")) {
|
||||
if (promise == null) {
|
||||
Log.e(TAG, "Missing schedule information");
|
||||
} else {
|
||||
promise.reject("notification/schedule_notification_error", "Missing schedule information");
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*
|
||||
Long fireDate = Math.round(bundle.getDouble("fire_date"));
|
||||
|
||||
if (fireDate == 0) {
|
||||
Log.e(TAG, "failed to schedule notification because fire date is missing");
|
||||
return;
|
||||
}*/
|
||||
String notificationId = notification.getString("notificationId");
|
||||
Bundle schedule = notification.getBundle("schedule");
|
||||
|
||||
long fireDate = schedule.getLong("fireDate");
|
||||
|
||||
// Scheduled alarms are cleared on restart
|
||||
// We store them so that they can be re-scheduled when the phone restarts in RNFirebaseNotificationsRebootReceiver
|
||||
|
@ -374,61 +425,47 @@ public class RNFirebaseNotificationManager {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
Intent notificationIntent = new Intent(context, RNFirebaseNotificationReceiver.class);
|
||||
notificationIntent.putExtras(notification);
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, notificationId.hashCode(), notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, notificationId.hashCode(),
|
||||
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
// TODO: Scheduling
|
||||
Long interval = null;
|
||||
switch (notification.getString("repeat_interval", "")) {
|
||||
case "minute":
|
||||
interval = (long) 60000;
|
||||
break;
|
||||
case "hour":
|
||||
interval = AlarmManager.INTERVAL_HOUR;
|
||||
break;
|
||||
case "day":
|
||||
interval = AlarmManager.INTERVAL_DAY;
|
||||
break;
|
||||
case "week":
|
||||
interval = AlarmManager.INTERVAL_DAY * 7;
|
||||
break;
|
||||
}
|
||||
if (schedule.containsKey("interval")) {
|
||||
Long interval = null;
|
||||
switch (schedule.getString("interval")) {
|
||||
case "minute":
|
||||
interval = 60000L;
|
||||
break;
|
||||
case "hour":
|
||||
interval = AlarmManager.INTERVAL_HOUR;
|
||||
break;
|
||||
case "day":
|
||||
interval = AlarmManager.INTERVAL_DAY;
|
||||
break;
|
||||
case "week":
|
||||
interval = AlarmManager.INTERVAL_DAY * 7;
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Invalid interval: " + schedule.getString("interval"));
|
||||
break;
|
||||
}
|
||||
|
||||
if (interval == null) {
|
||||
promise.reject("notification/schedule_notification_error", "Invalid interval");
|
||||
return;
|
||||
}
|
||||
|
||||
if(interval != null){
|
||||
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, fireDate, interval, pendingIntent);
|
||||
} else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
|
||||
alarmManager.setExact(AlarmManager.RTC_WAKEUP, fireDate, pendingIntent);
|
||||
}else {
|
||||
alarmManager.set(AlarmManager.RTC_WAKEUP, fireDate, pendingIntent);
|
||||
}
|
||||
}
|
||||
|
||||
private void cancelAlarm(String notificationId) {
|
||||
Intent notificationIntent = new Intent(context, RNFirebaseNotificationManager.class);
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, notificationId.hashCode(), notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
alarmManager.cancel(pendingIntent);
|
||||
}
|
||||
|
||||
private Bitmap getBitmap(String image) {
|
||||
if (image.startsWith("http://") || image.startsWith("https://")) {
|
||||
return getBitmapFromUrl(image);
|
||||
} else {
|
||||
int largeIconResId = res.getIdentifier(image, "mipmap", packageName);
|
||||
return BitmapFactory.decodeResource(res, largeIconResId);
|
||||
if (schedule.containsKey("exact")
|
||||
&& schedule.getBoolean("exact")
|
||||
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
alarmManager.setExact(AlarmManager.RTC_WAKEUP, fireDate, pendingIntent);
|
||||
} else {
|
||||
alarmManager.set(AlarmManager.RTC_WAKEUP, fireDate, pendingIntent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Bitmap getBitmapFromUrl(String imageUrl) {
|
||||
try {
|
||||
HttpURLConnection connection = (HttpURLConnection) new URL(imageUrl).openConnection();
|
||||
connection.setDoInput(true);
|
||||
connection.connect();
|
||||
return BitmapFactory.decodeStream(connection.getInputStream());
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
return null;
|
||||
}
|
||||
promise.resolve(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,6 @@ import android.content.Intent;
|
|||
public class RNFirebaseNotificationReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
new RNFirebaseNotificationManager(context).displayNotification(intent.getExtras());
|
||||
new RNFirebaseNotificationManager(context).displayScheduledNotification(intent.getExtras());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,41 @@
|
|||
package io.invertase.firebase.notifications;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.LifecycleEventListener;
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class RNFirebaseNotifications extends ReactContextBaseJavaModule {
|
||||
import io.invertase.firebase.Utils;
|
||||
|
||||
public class RNFirebaseNotifications extends ReactContextBaseJavaModule implements LifecycleEventListener {
|
||||
private static final String TAG = "RNFirebaseNotifications";
|
||||
|
||||
private RNFirebaseNotificationManager notificationManager;
|
||||
public RNFirebaseNotifications(ReactApplicationContext context) {
|
||||
super(context);
|
||||
notificationManager = new RNFirebaseNotificationManager(context.getApplicationContext());
|
||||
context.addLifecycleEventListener(this);
|
||||
|
||||
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);
|
||||
|
||||
// Subscribe to scheduled notification events
|
||||
localBroadcastManager.registerReceiver(new ScheduledNotificationReceiver(),
|
||||
new IntentFilter(RNFirebaseNotificationManager.SCHEDULED_NOTIFICATION_EVENT));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,7 +84,46 @@ public class RNFirebaseNotifications extends ReactContextBaseJavaModule {
|
|||
}
|
||||
|
||||
@ReactMethod
|
||||
public void scheduleNotification(ReadableMap notification, ReadableMap schedule, Promise promise) {
|
||||
notificationManager.scheduleNotification(notification, schedule, promise);
|
||||
public void scheduleNotification(ReadableMap notification, Promise promise) {
|
||||
notificationManager.scheduleNotification(notification, promise);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Start LifecycleEventListener methods
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@Override
|
||||
public void onHostResume() {
|
||||
notificationManager.setIsForeground(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHostPause() {
|
||||
notificationManager.setIsForeground(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHostDestroy() {
|
||||
// Do nothing
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// End LifecycleEventListener methods
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
private WritableMap parseNotificationBundle(Bundle notification) {
|
||||
return Arguments.makeNativeMap(notification);
|
||||
}
|
||||
|
||||
private class ScheduledNotificationReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (getReactApplicationContext().hasActiveCatalystInstance()) {
|
||||
Log.d(TAG, "Received new scheduled notification");
|
||||
|
||||
Bundle notification = intent.getBundleExtra("notification");
|
||||
WritableMap messageMap = parseNotificationBundle(notification);
|
||||
|
||||
Utils.sendEvent(getReactApplicationContext(), "notifications_notification_received", messageMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ RCT_EXPORT_METHOD(cancelNotification:(NSString*) notificationId) {
|
|||
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) {
|
||||
for (UILocalNotification *notification in RCTSharedApplication().scheduledLocalNotifications) {
|
||||
NSDictionary *notificationInfo = notification.userInfo;
|
||||
// TODO: NotificationId?
|
||||
if ([notificationId isEqualToString:[notificationInfo valueForKey:@"notificationId"]]) {
|
||||
[RCTSharedApplication() cancelLocalNotification:notification];
|
||||
}
|
||||
|
@ -46,12 +45,12 @@ RCT_EXPORT_METHOD(displayNotification:(NSDictionary*) notification
|
|||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject) {
|
||||
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) {
|
||||
UILocalNotification* notif = [self buildUILocalNotification:notification];
|
||||
UILocalNotification* notif = [self buildUILocalNotification:notification withSchedule:false];
|
||||
[RCTSharedApplication() presentLocalNotificationNow:notif];
|
||||
resolve(nil);
|
||||
} else {
|
||||
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
|
||||
UNNotificationRequest* request = [self buildUNNotificationRequest:notification];
|
||||
UNNotificationRequest* request = [self buildUNNotificationRequest:notification withSchedule:false];
|
||||
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
|
||||
if (!error) {
|
||||
resolve(nil);
|
||||
|
@ -123,18 +122,15 @@ RCT_EXPORT_METHOD(removeDeliveredNotification:(NSString*) notificationId) {
|
|||
}
|
||||
|
||||
RCT_EXPORT_METHOD(scheduleNotification:(NSDictionary*) notification
|
||||
schedule:(NSDictionary*) schedule
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject) {
|
||||
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_9_x_Max) {
|
||||
UILocalNotification* notif = [self buildUILocalNotification:notification];
|
||||
// TODO: Schedule
|
||||
UILocalNotification* notif = [self buildUILocalNotification:notification withSchedule:true];
|
||||
[RCTSharedApplication() scheduleLocalNotification:notif];
|
||||
resolve(nil);
|
||||
} else {
|
||||
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
|
||||
UNNotificationRequest* request = [self buildUNNotificationRequest:notification];
|
||||
// TODO: Schedule
|
||||
UNNotificationRequest* request = [self buildUNNotificationRequest:notification withSchedule:true];
|
||||
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
|
||||
if (!error) {
|
||||
resolve(nil);
|
||||
|
@ -146,7 +142,8 @@ RCT_EXPORT_METHOD(scheduleNotification:(NSDictionary*) notification
|
|||
}
|
||||
}
|
||||
|
||||
- (UILocalNotification*) buildUILocalNotification:(NSDictionary *) notification {
|
||||
- (UILocalNotification*) buildUILocalNotification:(NSDictionary *) notification
|
||||
withSchedule:(BOOL) withSchedule {
|
||||
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
|
||||
if (notification[@"body"]) {
|
||||
localNotification.alertBody = notification[@"body"];
|
||||
|
@ -179,11 +176,32 @@ RCT_EXPORT_METHOD(scheduleNotification:(NSDictionary*) notification
|
|||
localNotification.alertLaunchImage = ios[@"launchImage"];
|
||||
}
|
||||
}
|
||||
|
||||
if (withSchedule) {
|
||||
NSDictionary *schedule = notification[@"schedule"];
|
||||
NSNumber *fireDateNumber = schedule[@"fireDate"];
|
||||
NSDate *fireDate = [NSDate dateWithTimeIntervalSince1970:([fireDateNumber doubleValue] / 1000.0)];
|
||||
localNotification.fireDate = fireDate;
|
||||
|
||||
NSString *interval = schedule[@"repeatInterval"];
|
||||
if (interval) {
|
||||
if ([interval isEqualToString:@"minute"]) {
|
||||
localNotification.repeatInterval = NSCalendarUnitMinute;
|
||||
} else if ([interval isEqualToString:@"hour"]) {
|
||||
localNotification.repeatInterval = NSCalendarUnitHour;
|
||||
} else if ([interval isEqualToString:@"day"]) {
|
||||
localNotification.repeatInterval = NSCalendarUnitDay;
|
||||
} else if ([interval isEqualToString:@"week"]) {
|
||||
localNotification.repeatInterval = NSCalendarUnitWeekday;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return localNotification;
|
||||
}
|
||||
|
||||
- (UNNotificationRequest*) buildUNNotificationRequest:(NSDictionary *) notification {
|
||||
- (UNNotificationRequest*) buildUNNotificationRequest:(NSDictionary *) notification
|
||||
withSchedule:(BOOL) withSchedule {
|
||||
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
|
||||
if (notification[@"body"]) {
|
||||
content.body = notification[@"body"];
|
||||
|
@ -234,8 +252,34 @@ RCT_EXPORT_METHOD(scheduleNotification:(NSDictionary*) notification
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Scheduling
|
||||
return [UNNotificationRequest requestWithIdentifier:notification[@"ios"][@"identifier"] content:content trigger:nil];
|
||||
if (withSchedule) {
|
||||
NSDictionary *schedule = notification[@"schedule"];
|
||||
NSNumber *fireDateNumber = schedule[@"fireDate"];
|
||||
NSString *interval = schedule[@"repeatInterval"];
|
||||
NSDate *fireDate = [NSDate dateWithTimeIntervalSince1970:([fireDateNumber doubleValue] / 1000.0)];
|
||||
|
||||
NSCalendarUnit calendarUnit;
|
||||
if (interval) {
|
||||
if ([interval isEqualToString:@"minute"]) {
|
||||
calendarUnit = NSCalendarUnitSecond;
|
||||
} else if ([interval isEqualToString:@"hour"]) {
|
||||
calendarUnit = NSCalendarUnitMinute | NSCalendarUnitSecond;
|
||||
} else if ([interval isEqualToString:@"day"]) {
|
||||
calendarUnit = NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
|
||||
} else if ([interval isEqualToString:@"week"]) {
|
||||
calendarUnit = NSCalendarUnitWeekday | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
|
||||
}
|
||||
} else {
|
||||
// Needs to match exactly to the secpmd
|
||||
calendarUnit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
|
||||
}
|
||||
|
||||
NSDateComponents *components = [[NSCalendar currentCalendar] components:calendarUnit fromDate:fireDate];
|
||||
UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:interval];
|
||||
return [UNNotificationRequest requestWithIdentifier:notification[@"notificationId"] content:content trigger:trigger];
|
||||
} else {
|
||||
return [UNNotificationRequest requestWithIdentifier:notification[@"notificationId"] content:content trigger:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSDictionary*) parseUILocalNotification:(UILocalNotification *) localNotification {
|
||||
|
@ -278,7 +322,7 @@ RCT_EXPORT_METHOD(scheduleNotification:(NSDictionary*) notification
|
|||
- (NSDictionary*) parseUNNotificationRequest:(UNNotificationRequest *) localNotification {
|
||||
NSMutableDictionary *notification = [[NSMutableDictionary alloc] init];
|
||||
|
||||
notification[@"identifier"] = localNotification.identifier;
|
||||
notification[@"notificationId"] = localNotification.identifier;
|
||||
|
||||
if (localNotification.content.body) {
|
||||
notification[@"body"] = localNotification.content.body;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
import ModuleBase from '../../utils/ModuleBase';
|
||||
import { getNativeModule } from '../../utils/native';
|
||||
|
||||
import type App from '../core/firebase-app';
|
||||
import type App from '../core/app';
|
||||
|
||||
export const MODULE_NAME = 'RNFirebaseInstanceId';
|
||||
export const NAMESPACE = 'instanceid';
|
||||
|
|
|
@ -17,17 +17,18 @@ type Progress = {
|
|||
};
|
||||
|
||||
type SmallIcon = {
|
||||
icon: number,
|
||||
icon: string,
|
||||
level?: number,
|
||||
};
|
||||
|
||||
export type NativeAndroidNotification = {
|
||||
export type NativeAndroidNotification = {|
|
||||
// TODO actions: Action[],
|
||||
autoCancel: boolean,
|
||||
badgeIconType: BadgeIconTypeType,
|
||||
category: CategoryType,
|
||||
channelId: string,
|
||||
color: number,
|
||||
clickAction?: string,
|
||||
color: string,
|
||||
colorized: boolean,
|
||||
contentInfo: string,
|
||||
defaults: DefaultsType[],
|
||||
|
@ -43,7 +44,7 @@ export type NativeAndroidNotification = {
|
|||
people: string[],
|
||||
priority: PriorityType,
|
||||
progress: Progress,
|
||||
publicVersion: Notification,
|
||||
// publicVersion: Notification,
|
||||
remoteInputHistory: string[],
|
||||
shortcutId: string,
|
||||
showWhen: boolean,
|
||||
|
@ -56,7 +57,7 @@ export type NativeAndroidNotification = {
|
|||
vibrate: number[],
|
||||
visibility: VisibilityType,
|
||||
when: number,
|
||||
};
|
||||
|};
|
||||
|
||||
export const BadgeIconType = {
|
||||
Large: 2,
|
||||
|
@ -122,7 +123,8 @@ export default class AndroidNotification {
|
|||
_badgeIconType: BadgeIconTypeType;
|
||||
_category: CategoryType;
|
||||
_channelId: string;
|
||||
_color: number;
|
||||
_clickAction: string;
|
||||
_color: string;
|
||||
_colorized: boolean;
|
||||
_contentInfo: string;
|
||||
_defaults: DefaultsType[];
|
||||
|
@ -139,11 +141,13 @@ export default class AndroidNotification {
|
|||
_people: string[];
|
||||
_priority: PriorityType;
|
||||
_progress: Progress;
|
||||
_publicVersion: Notification;
|
||||
// _publicVersion: Notification;
|
||||
_remoteInputHistory: string[];
|
||||
_shortcutId: string;
|
||||
_showWhen: boolean;
|
||||
_smallIcon: SmallIcon;
|
||||
_smallIcon: SmallIcon = {
|
||||
icon: 'ic_launcher',
|
||||
};
|
||||
_sortKey: string;
|
||||
// TODO: style: Style; // Need to figure out if this can work
|
||||
_ticker: string;
|
||||
|
@ -170,9 +174,7 @@ export default class AndroidNotification {
|
|||
|
||||
/**
|
||||
*
|
||||
* @param identifier
|
||||
* @param identifier
|
||||
* @param identifier
|
||||
* @param person
|
||||
* @returns {Notification}
|
||||
*/
|
||||
addPerson(person: string): Notification {
|
||||
|
@ -228,7 +230,7 @@ export default class AndroidNotification {
|
|||
* @param color
|
||||
* @returns {Notification}
|
||||
*/
|
||||
setColor(color: number): Notification {
|
||||
setColor(color: string): Notification {
|
||||
this._color = color;
|
||||
return this._notification;
|
||||
}
|
||||
|
@ -394,10 +396,10 @@ export default class AndroidNotification {
|
|||
* @param publicVersion
|
||||
* @returns {Notification}
|
||||
*/
|
||||
setPublicVersion(publicVersion: Notification): Notification {
|
||||
/* setPublicVersion(publicVersion: Notification): Notification {
|
||||
this._publicVersion = publicVersion;
|
||||
return this._notification;
|
||||
}
|
||||
} */
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -435,7 +437,7 @@ export default class AndroidNotification {
|
|||
* @param level
|
||||
* @returns {Notification}
|
||||
*/
|
||||
setSmallIcon(icon: number, level?: number): Notification {
|
||||
setSmallIcon(icon: string, level?: number): Notification {
|
||||
this._smallIcon = {
|
||||
icon,
|
||||
level,
|
||||
|
@ -517,6 +519,7 @@ export default class AndroidNotification {
|
|||
badgeIconType: this._badgeIconType,
|
||||
category: this._category,
|
||||
channelId: this._channelId,
|
||||
clickAction: this._clickAction,
|
||||
color: this._color,
|
||||
colorized: this._colorized,
|
||||
contentInfo: this._contentInfo,
|
||||
|
@ -533,7 +536,7 @@ export default class AndroidNotification {
|
|||
people: this._people,
|
||||
priority: this._priority,
|
||||
progress: this._progress,
|
||||
publicVersion: this._publicVersion,
|
||||
// publicVersion: this._publicVersion,
|
||||
remoteInputHistory: this._remoteInputHistory,
|
||||
shortcutId: this._shortcutId,
|
||||
showWhen: this._showWhen,
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
* @flow
|
||||
* IOSNotification representation wrapper
|
||||
*/
|
||||
import { generatePushID } from '../../utils';
|
||||
import type Notification from './Notification';
|
||||
|
||||
type AttachmentOptions = {|
|
||||
|
@ -23,16 +22,15 @@ type Attachment = {|
|
|||
url: string,
|
||||
|};
|
||||
|
||||
export type NativeIOSNotification = {
|
||||
export type NativeIOSNotification = {|
|
||||
alertAction?: string,
|
||||
attachments: Attachment[],
|
||||
badge?: number,
|
||||
category?: string,
|
||||
hasAction?: boolean,
|
||||
identifier?: string,
|
||||
launchImage?: string,
|
||||
threadIdentifier?: string,
|
||||
};
|
||||
|};
|
||||
|
||||
export default class IOSNotification {
|
||||
_alertAction: string; // alertAction | N/A
|
||||
|
@ -40,23 +38,20 @@ export default class IOSNotification {
|
|||
_badge: number; // applicationIconBadgeNumber | badge
|
||||
_category: string;
|
||||
_hasAction: boolean; // hasAction | N/A
|
||||
_identifier: string; // N/A | identifier
|
||||
_launchImage: string; // alertLaunchImage | launchImageName
|
||||
_notification: Notification;
|
||||
_threadIdentifier: string; // N/A | threadIdentifier
|
||||
|
||||
constructor(notification: Notification) {
|
||||
this._attachments = [];
|
||||
// TODO: Is this the best way to generate an ID?
|
||||
this._identifier = generatePushID();
|
||||
this._notification = notification;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param identifier
|
||||
* @param identifier
|
||||
* @param identifier
|
||||
* @param url
|
||||
* @param options
|
||||
* @returns {Notification}
|
||||
*/
|
||||
addAttachment(
|
||||
|
@ -112,16 +107,6 @@ export default class IOSNotification {
|
|||
return this._notification;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param identifier
|
||||
* @returns {Notification}
|
||||
*/
|
||||
setIdentifier(identifier: string): Notification {
|
||||
this._identifier = identifier;
|
||||
return this._notification;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param launchImage
|
||||
|
@ -151,7 +136,6 @@ export default class IOSNotification {
|
|||
badge: this._badge,
|
||||
category: this._category,
|
||||
hasAction: this._hasAction,
|
||||
identifier: this._identifier,
|
||||
launchImage: this._launchImage,
|
||||
threadIdentifier: this._threadIdentifier,
|
||||
};
|
||||
|
|
|
@ -4,16 +4,19 @@
|
|||
*/
|
||||
import AndroidNotification from './AndroidNotification';
|
||||
import IOSNotification from './IOSNotification';
|
||||
import { isObject } from '../../utils';
|
||||
import { generatePushID, isObject } from '../../utils';
|
||||
|
||||
import type { NativeAndroidNotification } from './AndroidNotification';
|
||||
import type { NativeIOSNotification } from './IOSNotification';
|
||||
import type { Schedule } from './';
|
||||
|
||||
type NativeNotification = {|
|
||||
android: NativeAndroidNotification,
|
||||
body: string,
|
||||
data: { [string]: string },
|
||||
ios: NativeIOSNotification,
|
||||
notificationId: string,
|
||||
schedule?: Schedule,
|
||||
sound?: string,
|
||||
subtitle?: string,
|
||||
title: string,
|
||||
|
@ -25,6 +28,7 @@ export default class Notification {
|
|||
_body: string; // alertBody | body | contentText
|
||||
_data: { [string]: string }; // userInfo | userInfo | extras
|
||||
_ios: IOSNotification;
|
||||
_notificationId: string;
|
||||
_sound: string | void; // soundName | sound | sound
|
||||
_subtitle: string | void; // N/A | subtitle | subText
|
||||
_title: string; // alertTitle | title | contentTitle
|
||||
|
@ -33,6 +37,8 @@ export default class Notification {
|
|||
this._android = new AndroidNotification(this);
|
||||
this._data = {};
|
||||
this._ios = new IOSNotification(this);
|
||||
// TODO: Is this the best way to generate an ID?
|
||||
this._notificationId = generatePushID();
|
||||
}
|
||||
|
||||
get android(): AndroidNotification {
|
||||
|
@ -68,6 +74,16 @@ export default class Notification {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param notificationId
|
||||
* @returns {Notification}
|
||||
*/
|
||||
setNotificationId(notificationId: string): Notification {
|
||||
this._notificationId = notificationId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param sound
|
||||
|
@ -101,9 +117,13 @@ export default class Notification {
|
|||
build(): NativeNotification {
|
||||
// Android required fields: body, title, smallicon
|
||||
// iOS required fields: TODO
|
||||
if (!this.body) {
|
||||
if (!this._body) {
|
||||
throw new Error('Notification: Missing required `body` property');
|
||||
} else if (!this.title) {
|
||||
} else if (!this._notificationId) {
|
||||
throw new Error(
|
||||
'Notification: Missing required `notificationId` property'
|
||||
);
|
||||
} else if (!this._title) {
|
||||
throw new Error('Notification: Missing required `title` property');
|
||||
}
|
||||
|
||||
|
@ -112,6 +132,7 @@ export default class Notification {
|
|||
body: this._body,
|
||||
data: this._data,
|
||||
ios: this._ios.build(),
|
||||
notificationId: this._notificationId,
|
||||
sound: this._sound,
|
||||
subtitle: this._subtitle,
|
||||
title: this._title,
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
Visibility,
|
||||
} from './AndroidNotification';
|
||||
|
||||
import type App from '../core/firebase-app';
|
||||
import type App from '../core/app';
|
||||
|
||||
// TODO: Received notification type will be different from sent notification
|
||||
type OnNotification = Notification => any;
|
||||
|
@ -26,9 +26,10 @@ type OnNotificationObserver = {
|
|||
next: OnNotification,
|
||||
};
|
||||
|
||||
// TODO: Schedule type
|
||||
type Schedule = {
|
||||
build: () => Object,
|
||||
export type Schedule = {
|
||||
exact?: boolean,
|
||||
fireDate: number,
|
||||
repeatInterval?: 'minute' | 'hour' | 'day' | 'week',
|
||||
};
|
||||
|
||||
const NATIVE_EVENTS = ['notifications_notification_received'];
|
||||
|
@ -174,10 +175,9 @@ export default class Notifications extends ModuleBase {
|
|||
`Notifications:scheduleNotification expects a 'Notification' but got type ${typeof notification}`
|
||||
);
|
||||
}
|
||||
return getNativeModule(this).scheduleNotification(
|
||||
notification.build(),
|
||||
schedule.build()
|
||||
);
|
||||
const nativeNotification = notification.build();
|
||||
nativeNotification.schedule = schedule;
|
||||
return getNativeModule(this).scheduleNotification(nativeNotification);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ def enableProguardInReleaseBuilds = false
|
|||
|
||||
android {
|
||||
compileSdkVersion 26
|
||||
buildToolsVersion '25.0.3'
|
||||
buildToolsVersion '26.0.2'
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.reactnativefirebasedemo"
|
||||
|
@ -163,7 +163,7 @@ dependencies {
|
|||
compile('com.crashlytics.sdk.android:crashlytics:2.7.1@aar') {
|
||||
transitive = true
|
||||
}
|
||||
compile "com.android.support:appcompat-v7:26.0.1"
|
||||
compile "com.android.support:appcompat-v7:26.0.2"
|
||||
compile "com.facebook.react:react-native:+" // From node_modules
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,10 @@ allprojects {
|
|||
|
||||
subprojects {
|
||||
ext {
|
||||
compileSdk = 25
|
||||
buildTools = "25.0.2"
|
||||
compileSdk = 26
|
||||
buildTools = "26.0.2"
|
||||
minSdk = 16
|
||||
targetSdk = 25
|
||||
targetSdk = 26
|
||||
}
|
||||
|
||||
afterEvaluate { project ->
|
||||
|
|
|
@ -164,7 +164,7 @@ PODS:
|
|||
- React/Core
|
||||
- React/fishhook
|
||||
- React/RCTBlob
|
||||
- RNFirebase (3.2.4):
|
||||
- RNFirebase (3.2.5):
|
||||
- React
|
||||
- yoga (0.52.0.React)
|
||||
|
||||
|
@ -228,7 +228,7 @@ SPEC CHECKSUMS:
|
|||
nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3
|
||||
Protobuf: 8a9838fba8dae3389230e1b7f8c104aa32389c03
|
||||
React: 61a6bdf17a9ff16875c230e6ff278d9de274e16c
|
||||
RNFirebase: 011e47909cf54070f72d50b8d61eb7b347774d29
|
||||
RNFirebase: e3448c730955d51d06dee59a265011536abdd7c4
|
||||
yoga: 646606bf554d54a16711f35596178522fbc00480
|
||||
|
||||
PODFILE CHECKSUM: 67c98bcb203cb992da590bcab6f690f727653ca5
|
||||
|
|
Loading…
Reference in New Issue