[android, ios] first draft of full fcm implementation - ios still todo
This commit is contained in:
parent
b9fd032b6d
commit
856da83a80
|
@ -43,7 +43,9 @@ allprojects {
|
||||||
// END
|
// END
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'com.facebook.react:react-native:0.20.+'
|
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
|
compile 'com.facebook.react:react-native:+'
|
||||||
|
compile 'me.leolin:ShortcutBadger:1.1.10@aar'
|
||||||
compile 'com.google.android.gms:play-services-base:10.2.0'
|
compile 'com.google.android.gms:play-services-base:10.2.0'
|
||||||
compile 'com.google.firebase:firebase-core:10.2.0'
|
compile 'com.google.firebase:firebase-core:10.2.0'
|
||||||
compile 'com.google.firebase:firebase-config:10.2.0'
|
compile 'com.google.firebase:firebase-config:10.2.0'
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
package io.invertase.firebase;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.content.Intent;
|
|
||||||
|
|
||||||
import com.google.firebase.iid.FirebaseInstanceId;
|
|
||||||
import com.google.firebase.iid.FirebaseInstanceIdService;
|
|
||||||
|
|
||||||
import io.invertase.firebase.messaging.RNFirebaseMessaging;
|
|
||||||
|
|
||||||
public class RNFirebaseInstanceIdService extends FirebaseInstanceIdService {
|
|
||||||
|
|
||||||
private static final String TAG = "FSInstanceIdService";
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onTokenRefresh() {
|
|
||||||
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
|
|
||||||
Log.d(TAG, "Refreshed token: " + refreshedToken);
|
|
||||||
Intent i = new Intent(RNFirebaseMessaging.INTENT_NAME_TOKEN);
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putString("token", refreshedToken);
|
|
||||||
i.putExtras(bundle);
|
|
||||||
sendBroadcast(i);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
package io.invertase.firebase;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.google.firebase.messaging.FirebaseMessagingService;
|
|
||||||
import com.google.firebase.messaging.RemoteMessage;
|
|
||||||
import com.google.firebase.messaging.SendException;
|
|
||||||
|
|
||||||
import io.invertase.firebase.messaging.RNFirebaseMessaging;
|
|
||||||
|
|
||||||
public class RNFirebaseMessagingService extends FirebaseMessagingService {
|
|
||||||
|
|
||||||
private static final String TAG = "FSMessagingService";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMessageReceived(RemoteMessage remoteMessage) {
|
|
||||||
Log.d(TAG, "Remote message received");
|
|
||||||
// debug
|
|
||||||
Log.d(TAG, "From: " + remoteMessage.getFrom());
|
|
||||||
|
|
||||||
if (remoteMessage.getData().size() > 0) {
|
|
||||||
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remoteMessage.getNotification() != null) {
|
|
||||||
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
Intent i = new Intent(RNFirebaseMessaging.INTENT_NAME_NOTIFICATION);
|
|
||||||
i.putExtra("data", remoteMessage);
|
|
||||||
sendOrderedBroadcast(i, null);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMessageSent(String msgId) {
|
|
||||||
// Called when an upstream message has been successfully sent to the GCM connection server.
|
|
||||||
Log.d(TAG, "upstream message has been successfully sent");
|
|
||||||
Intent i = new Intent(RNFirebaseMessaging.INTENT_NAME_SEND);
|
|
||||||
i.putExtra("msgId", msgId);
|
|
||||||
sendOrderedBroadcast(i, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSendError(String msgId, Exception exception) {
|
|
||||||
// Called when there was an error sending an upstream message.
|
|
||||||
Log.d(TAG, "error sending an upstream message");
|
|
||||||
Intent i = new Intent(RNFirebaseMessaging.INTENT_NAME_SEND);
|
|
||||||
i.putExtra("msgId", msgId);
|
|
||||||
i.putExtra("hasError", true);
|
|
||||||
SendException sendException = (SendException) exception;
|
|
||||||
i.putExtra("errorCode", sendException.getErrorCode());
|
|
||||||
switch (sendException.getErrorCode()) {
|
|
||||||
case SendException.ERROR_INVALID_PARAMETERS:
|
|
||||||
i.putExtra("errorMessage", "Message was sent with invalid parameters.");
|
|
||||||
break;
|
|
||||||
case SendException.ERROR_SIZE:
|
|
||||||
i.putExtra("errorMessage", "Message exceeded the maximum payload size.");
|
|
||||||
break;
|
|
||||||
case SendException.ERROR_TOO_MANY_MESSAGES:
|
|
||||||
i.putExtra("errorMessage", "App has too many pending messages so this one was dropped.");
|
|
||||||
break;
|
|
||||||
case SendException.ERROR_TTL_EXCEEDED:
|
|
||||||
i.putExtra("errorMessage", "Message time to live (TTL) was exceeded before the message could be sent.");
|
|
||||||
break;
|
|
||||||
case SendException.ERROR_UNKNOWN:
|
|
||||||
default:
|
|
||||||
i.putExtra("errorMessage", "Unknown error.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sendOrderedBroadcast(i, null);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
package io.invertase.firebase.messaging;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import me.leolin.shortcutbadger.ShortcutBadger;
|
||||||
|
|
||||||
|
public class BadgeHelper {
|
||||||
|
|
||||||
|
private static final String TAG = "BadgeHelper";
|
||||||
|
private static final String PREFERENCES_FILE = "BadgeCountFile";
|
||||||
|
private static final String BADGE_COUNT_KEY = "BadgeCount";
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
private SharedPreferences sharedPreferences = null;
|
||||||
|
|
||||||
|
public BadgeHelper(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
sharedPreferences = (SharedPreferences) mContext.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBadgeCount() {
|
||||||
|
return sharedPreferences.getInt(BADGE_COUNT_KEY, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBadgeCount(int badgeCount) {
|
||||||
|
storeBadgeCount(badgeCount);
|
||||||
|
if (badgeCount == 0) {
|
||||||
|
ShortcutBadger.removeCount(mContext);
|
||||||
|
Log.d(TAG, "Remove count");
|
||||||
|
} else {
|
||||||
|
ShortcutBadger.applyCount(mContext, badgeCount);
|
||||||
|
Log.d(TAG, "Apply count: " + badgeCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void storeBadgeCount(int badgeCount) {
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||||
|
editor.putInt(BADGE_COUNT_KEY, badgeCount);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,206 @@
|
||||||
|
package io.invertase.firebase.messaging;
|
||||||
|
|
||||||
|
// taken from https://github.com/facebook/facebook-android-sdk/blob/master/facebook/src/main/java/com/facebook/internal/BundleJSONConverter.java
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||||
|
* <p>
|
||||||
|
* You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||||
|
* copy, modify, and distribute this software in source code or binary form for use
|
||||||
|
* in connection with the web services and APIs provided by Facebook.
|
||||||
|
* <p>
|
||||||
|
* As with any software that integrates with the Facebook platform, your use of
|
||||||
|
* this software is subject to the Facebook Developer Principles and Policies
|
||||||
|
* [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||||
|
* included in all copies or substantial portions of the software.
|
||||||
|
* <p>
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* com.facebook.internal is solely for the use of other packages within the Facebook SDK for
|
||||||
|
* Android. Use of any of the classes in this package is unsupported, and they may be modified or
|
||||||
|
* removed without warning at any time.
|
||||||
|
*
|
||||||
|
* A helper class that can round trip between JSON and Bundle objects that contains the types:
|
||||||
|
* Boolean, Integer, Long, Double, String
|
||||||
|
* If other types are found, an IllegalArgumentException is thrown.
|
||||||
|
*/
|
||||||
|
public class BundleJSONConverter {
|
||||||
|
private static final Map<Class<?>, Setter> SETTERS = new HashMap<Class<?>, Setter>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
SETTERS.put(Boolean.class, new Setter() {
|
||||||
|
public void setOnBundle(Bundle bundle, String key, Object value) throws JSONException {
|
||||||
|
bundle.putBoolean(key, (Boolean) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnJSON(JSONObject json, String key, Object value) throws JSONException {
|
||||||
|
json.put(key, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
SETTERS.put(Integer.class, new Setter() {
|
||||||
|
public void setOnBundle(Bundle bundle, String key, Object value) throws JSONException {
|
||||||
|
bundle.putInt(key, (Integer) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnJSON(JSONObject json, String key, Object value) throws JSONException {
|
||||||
|
json.put(key, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
SETTERS.put(Long.class, new Setter() {
|
||||||
|
public void setOnBundle(Bundle bundle, String key, Object value) throws JSONException {
|
||||||
|
bundle.putLong(key, (Long) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnJSON(JSONObject json, String key, Object value) throws JSONException {
|
||||||
|
json.put(key, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
SETTERS.put(Double.class, new Setter() {
|
||||||
|
public void setOnBundle(Bundle bundle, String key, Object value) throws JSONException {
|
||||||
|
bundle.putDouble(key, (Double) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnJSON(JSONObject json, String key, Object value) throws JSONException {
|
||||||
|
json.put(key, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
SETTERS.put(String.class, new Setter() {
|
||||||
|
public void setOnBundle(Bundle bundle, String key, Object value) throws JSONException {
|
||||||
|
bundle.putString(key, (String) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnJSON(JSONObject json, String key, Object value) throws JSONException {
|
||||||
|
json.put(key, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
SETTERS.put(String[].class, new Setter() {
|
||||||
|
public void setOnBundle(Bundle bundle, String key, Object value) throws JSONException {
|
||||||
|
throw new IllegalArgumentException("Unexpected type from JSON");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnJSON(JSONObject json, String key, Object value) throws JSONException {
|
||||||
|
JSONArray jsonArray = new JSONArray();
|
||||||
|
for (String stringValue : (String[]) value) {
|
||||||
|
jsonArray.put(stringValue);
|
||||||
|
}
|
||||||
|
json.put(key, jsonArray);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
SETTERS.put(JSONArray.class, new Setter() {
|
||||||
|
public void setOnBundle(Bundle bundle, String key, Object value) throws JSONException {
|
||||||
|
JSONArray jsonArray = (JSONArray) value;
|
||||||
|
ArrayList<String> stringArrayList = new ArrayList<String>();
|
||||||
|
// Empty list, can't even figure out the type, assume an ArrayList<String>
|
||||||
|
if (jsonArray.length() == 0) {
|
||||||
|
bundle.putStringArrayList(key, stringArrayList);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only strings are supported for now
|
||||||
|
for (int i = 0; i < jsonArray.length(); i++) {
|
||||||
|
Object current = jsonArray.get(i);
|
||||||
|
if (current instanceof String) {
|
||||||
|
stringArrayList.add((String) current);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unexpected type in an array: " + current.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bundle.putStringArrayList(key, stringArrayList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOnJSON(JSONObject json, String key, Object value) throws JSONException {
|
||||||
|
throw new IllegalArgumentException("JSONArray's are not supported in bundles.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Setter {
|
||||||
|
public void setOnBundle(Bundle bundle, String key, Object value) throws JSONException;
|
||||||
|
|
||||||
|
public void setOnJSON(JSONObject json, String key, Object value) throws JSONException;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JSONObject convertToJSON(Bundle bundle) throws JSONException {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
|
||||||
|
for (String key : bundle.keySet()) {
|
||||||
|
Object value = bundle.get(key);
|
||||||
|
if (value == null) {
|
||||||
|
// Null is not supported.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case List<String> as getClass would not work, since List is an interface
|
||||||
|
if (value instanceof List<?>) {
|
||||||
|
JSONArray jsonArray = new JSONArray();
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<String> listValue = (List<String>) value;
|
||||||
|
for (String stringValue : listValue) {
|
||||||
|
jsonArray.put(stringValue);
|
||||||
|
}
|
||||||
|
json.put(key, jsonArray);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case Bundle as it's one way, on the return it will be JSONObject
|
||||||
|
if (value instanceof Bundle) {
|
||||||
|
json.put(key, convertToJSON((Bundle) value));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Setter setter = SETTERS.get(value.getClass());
|
||||||
|
if (setter == null) {
|
||||||
|
throw new IllegalArgumentException("Unsupported type: " + value.getClass());
|
||||||
|
}
|
||||||
|
setter.setOnJSON(json, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bundle convertToBundle(JSONObject jsonObject) throws JSONException {
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Iterator<String> jsonIterator = jsonObject.keys();
|
||||||
|
while (jsonIterator.hasNext()) {
|
||||||
|
String key = jsonIterator.next();
|
||||||
|
Object value = jsonObject.get(key);
|
||||||
|
if (value == null || value == JSONObject.NULL) {
|
||||||
|
// Null is not supported.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case JSONObject as it's one way, on the return it would be Bundle.
|
||||||
|
if (value instanceof JSONObject) {
|
||||||
|
bundle.putBundle(key, convertToBundle((JSONObject) value));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Setter setter = SETTERS.get(value.getClass());
|
||||||
|
if (setter == null) {
|
||||||
|
throw new IllegalArgumentException("Unsupported type: " + value.getClass());
|
||||||
|
}
|
||||||
|
setter.setOnBundle(bundle, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bundle;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package io.invertase.firebase.messaging;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.google.firebase.iid.FirebaseInstanceId;
|
||||||
|
import com.google.firebase.iid.FirebaseInstanceIdService;
|
||||||
|
|
||||||
|
public class InstanceIdService extends FirebaseInstanceIdService {
|
||||||
|
|
||||||
|
private static final String TAG = "InstanceIdService";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called if InstanceID token is updated. This may occur if the security of
|
||||||
|
* the previous token had been compromised. This call is initiated by the
|
||||||
|
* InstanceID provider.
|
||||||
|
*/
|
||||||
|
// [START refresh_token]
|
||||||
|
@Override
|
||||||
|
public void onTokenRefresh() {
|
||||||
|
// Get updated InstanceID token.
|
||||||
|
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
|
||||||
|
Log.d(TAG, "Refreshed token: " + refreshedToken);
|
||||||
|
|
||||||
|
// Broadcast refreshed token
|
||||||
|
|
||||||
|
Intent i = new Intent("io.invertase.firebase.messaging.FCMRefreshToken");
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString("token", refreshedToken);
|
||||||
|
i.putExtras(bundle);
|
||||||
|
sendBroadcast(i);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package io.invertase.firebase.messaging;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.google.firebase.messaging.FirebaseMessagingService;
|
||||||
|
import com.google.firebase.messaging.RemoteMessage;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
public class MessagingService extends FirebaseMessagingService {
|
||||||
|
|
||||||
|
private static final String TAG = "MessagingService";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessageReceived(RemoteMessage remoteMessage) {
|
||||||
|
Log.d(TAG, "Remote message received");
|
||||||
|
Intent i = new Intent("io.invertase.firebase.messaging.ReceiveNotification");
|
||||||
|
i.putExtra("data", remoteMessage);
|
||||||
|
handleBadge(remoteMessage);
|
||||||
|
buildLocalNotification(remoteMessage);
|
||||||
|
sendOrderedBroadcast(i, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleBadge(RemoteMessage remoteMessage) {
|
||||||
|
BadgeHelper badgeHelper = new BadgeHelper(this);
|
||||||
|
if (remoteMessage.getData() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map data = remoteMessage.getData();
|
||||||
|
if (data.get("badge") == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
int badgeCount = Integer.parseInt((String)data.get("badge"));
|
||||||
|
badgeHelper.setBadgeCount(badgeCount);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Badge count needs to be an integer", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildLocalNotification(RemoteMessage remoteMessage) {
|
||||||
|
if(remoteMessage.getData() == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Map<String, String> data = remoteMessage.getData();
|
||||||
|
String customNotification = data.get("custom_notification");
|
||||||
|
if(customNotification != null){
|
||||||
|
try {
|
||||||
|
Bundle bundle = BundleJSONConverter.convertToBundle(new JSONObject(customNotification));
|
||||||
|
RNFirebaseLocalMessagingHelper helper = new RNFirebaseLocalMessagingHelper(this.getApplication());
|
||||||
|
helper.sendNotification(bundle);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,332 @@
|
||||||
|
package io.invertase.firebase.messaging;
|
||||||
|
|
||||||
|
import android.app.*;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.media.RingtoneManager;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.NotificationCompat;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.Patterns;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
|
||||||
|
public class RNFirebaseLocalMessagingHelper {
|
||||||
|
private static final long DEFAULT_VIBRATION = 300L;
|
||||||
|
private static final String TAG = RNFirebaseLocalMessagingHelper.class.getSimpleName();
|
||||||
|
private final static String PREFERENCES_KEY = "ReactNativeSystemNotification";
|
||||||
|
private static boolean mIsForeground = false; //this is a hack
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
private SharedPreferences sharedPreferences = null;
|
||||||
|
|
||||||
|
public RNFirebaseLocalMessagingHelper(Application context) {
|
||||||
|
mContext = context;
|
||||||
|
sharedPreferences = (SharedPreferences) mContext.getSharedPreferences(PREFERENCES_KEY, Context.MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AlarmManager getAlarmManager() {
|
||||||
|
return (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendNotification(Bundle bundle) {
|
||||||
|
try {
|
||||||
|
Class intentClass = getMainActivityClass();
|
||||||
|
if (intentClass == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bundle.getString("body") == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Resources res = mContext.getResources();
|
||||||
|
String packageName = mContext.getPackageName();
|
||||||
|
|
||||||
|
String title = bundle.getString("title");
|
||||||
|
if (title == null) {
|
||||||
|
ApplicationInfo appInfo = mContext.getApplicationInfo();
|
||||||
|
title = mContext.getPackageManager().getApplicationLabel(appInfo).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationCompat.Builder notification = new NotificationCompat.Builder(mContext)
|
||||||
|
.setContentTitle(title)
|
||||||
|
.setContentText(bundle.getString("body"))
|
||||||
|
.setTicker(bundle.getString("ticker"))
|
||||||
|
.setVisibility(NotificationCompat.VISIBILITY_PRIVATE)
|
||||||
|
.setAutoCancel(bundle.getBoolean("auto_cancel", true))
|
||||||
|
.setNumber(bundle.getInt("number"))
|
||||||
|
.setSubText(bundle.getString("sub_text"))
|
||||||
|
.setGroup(bundle.getString("group"))
|
||||||
|
.setVibrate(new long[]{0, DEFAULT_VIBRATION})
|
||||||
|
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
|
||||||
|
.setExtras(bundle.getBundle("data"));
|
||||||
|
|
||||||
|
//priority
|
||||||
|
String priority = bundle.getString("priority", "");
|
||||||
|
switch(priority) {
|
||||||
|
case "min":
|
||||||
|
notification.setPriority(NotificationCompat.PRIORITY_MIN);
|
||||||
|
break;
|
||||||
|
case "high":
|
||||||
|
notification.setPriority(NotificationCompat.PRIORITY_HIGH);
|
||||||
|
break;
|
||||||
|
case "max":
|
||||||
|
notification.setPriority(NotificationCompat.PRIORITY_MAX);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
notification.setPriority(NotificationCompat.PRIORITY_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
//icon
|
||||||
|
String smallIcon = bundle.getString("icon", "ic_launcher");
|
||||||
|
int smallIconResId = res.getIdentifier(smallIcon, "mipmap", packageName);
|
||||||
|
notification.setSmallIcon(smallIconResId);
|
||||||
|
|
||||||
|
//large icon
|
||||||
|
String largeIcon = bundle.getString("large_icon");
|
||||||
|
if(largeIcon != null && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){
|
||||||
|
if (largeIcon.startsWith("http://") || largeIcon.startsWith("https://")) {
|
||||||
|
Bitmap bitmap = getBitmapFromURL(largeIcon);
|
||||||
|
notification.setLargeIcon(bitmap);
|
||||||
|
} else {
|
||||||
|
int largeIconResId = res.getIdentifier(largeIcon, "mipmap", packageName);
|
||||||
|
Bitmap largeIconBitmap = BitmapFactory.decodeResource(res, largeIconResId);
|
||||||
|
|
||||||
|
if (largeIconResId != 0) {
|
||||||
|
notification.setLargeIcon(largeIconBitmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//big text
|
||||||
|
String bigText = bundle.getString("big_text");
|
||||||
|
if(bigText != null){
|
||||||
|
notification.setStyle(new NotificationCompat.BigTextStyle().bigText(bigText));
|
||||||
|
}
|
||||||
|
|
||||||
|
//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);
|
||||||
|
}
|
||||||
|
notification.setSound(Uri.parse("android.resource://" + packageName + "/" + soundResourceId));
|
||||||
|
}
|
||||||
|
|
||||||
|
//color
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
notification.setCategory(NotificationCompat.CATEGORY_CALL);
|
||||||
|
|
||||||
|
String color = bundle.getString("color");
|
||||||
|
if (color != null) {
|
||||||
|
notification.setColor(Color.parseColor(color));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//vibrate
|
||||||
|
if(bundle.containsKey("vibrate")){
|
||||||
|
long vibrate = bundle.getLong("vibrate", Math.round(bundle.getDouble("vibrate", bundle.getInt("vibrate"))));
|
||||||
|
if(vibrate > 0){
|
||||||
|
notification.setVibrate(new long[]{0, vibrate});
|
||||||
|
}else{
|
||||||
|
notification.setVibrate(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//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();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "failed to send local notification", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendNotificationScheduled(Bundle bundle) {
|
||||||
|
Class intentClass = getMainActivityClass();
|
||||||
|
if (intentClass == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String notificationId = bundle.getString("id");
|
||||||
|
if(notificationId == null){
|
||||||
|
Log.e(TAG, "failed to schedule notification because id is missing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Long fireDate = bundle.getLong("fire_date", Math.round(bundle.getDouble("fire_date")));
|
||||||
|
if (fireDate == 0) {
|
||||||
|
Log.e(TAG, "failed to schedule notification because fire date is missing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Intent notificationIntent = new Intent(mContext, RNFirebaseLocalMessagingPublisher.class);
|
||||||
|
notificationIntent.putExtras(bundle);
|
||||||
|
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, notificationId.hashCode(), notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
|
||||||
|
Long interval = null;
|
||||||
|
switch (bundle.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(interval != null){
|
||||||
|
getAlarmManager().setRepeating(AlarmManager.RTC_WAKEUP, fireDate, interval, pendingIntent);
|
||||||
|
} else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
|
||||||
|
getAlarmManager().setExact(AlarmManager.RTC_WAKEUP, fireDate, pendingIntent);
|
||||||
|
}else {
|
||||||
|
getAlarmManager().set(AlarmManager.RTC_WAKEUP, fireDate, pendingIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
//store intent
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||||
|
try {
|
||||||
|
JSONObject json = BundleJSONConverter.convertToJSON(bundle);
|
||||||
|
editor.putString(notificationId, json.toString());
|
||||||
|
editor.apply();
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelLocalNotification(String notificationId) {
|
||||||
|
cancelAlarm(notificationId);
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||||
|
editor.remove(notificationId);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelAllLocalNotifications() {
|
||||||
|
java.util.Map<String, ?> keyMap = sharedPreferences.getAll();
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||||
|
for(java.util.Map.Entry<String, ?> entry:keyMap.entrySet()){
|
||||||
|
cancelAlarm(entry.getKey());
|
||||||
|
}
|
||||||
|
editor.clear();
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeDeliveredNotification(String notificationId){
|
||||||
|
NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
notificationManager.cancel(notificationId.hashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAllDeliveredNotifications(){
|
||||||
|
NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
notificationManager.cancelAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelAlarm(String notificationId) {
|
||||||
|
Intent notificationIntent = new Intent(mContext, RNFirebaseLocalMessagingPublisher.class);
|
||||||
|
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, notificationId.hashCode(), notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
getAlarmManager().cancel(pendingIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Bundle> getScheduledLocalNotifications(){
|
||||||
|
ArrayList<Bundle> array = new ArrayList<Bundle>();
|
||||||
|
java.util.Map<String, ?> keyMap = sharedPreferences.getAll();
|
||||||
|
for(java.util.Map.Entry<String, ?> entry:keyMap.entrySet()){
|
||||||
|
try {
|
||||||
|
JSONObject json = new JSONObject((String)entry.getValue());
|
||||||
|
Bundle bundle = BundleJSONConverter.convertToBundle(json);
|
||||||
|
array.add(bundle);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApplicationForeground(boolean foreground){
|
||||||
|
mIsForeground = foreground;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bitmap getBitmapFromURL(String strURL) {
|
||||||
|
try {
|
||||||
|
URL url = new URL(strURL);
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
|
connection.setDoInput(true);
|
||||||
|
connection.connect();
|
||||||
|
InputStream input = connection.getInputStream();
|
||||||
|
return BitmapFactory.decodeStream(input);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package io.invertase.firebase.messaging;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
public class RNFirebaseLocalMessagingPublisher extends BroadcastReceiver {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
new RNFirebaseLocalMessagingHelper((Application) context.getApplicationContext()).sendNotification(intent.getExtras());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,222 +1,285 @@
|
||||||
package io.invertase.firebase.messaging;
|
package io.invertase.firebase.messaging;
|
||||||
|
|
||||||
import java.util.Map;
|
import android.app.Activity;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.util.Log;
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
|
||||||
|
import com.facebook.react.bridge.ActivityEventListener;
|
||||||
import com.facebook.react.bridge.Arguments;
|
import com.facebook.react.bridge.Arguments;
|
||||||
import com.facebook.react.bridge.Callback;
|
import com.facebook.react.bridge.LifecycleEventListener;
|
||||||
import com.facebook.react.bridge.Promise;
|
import com.facebook.react.bridge.Promise;
|
||||||
import com.facebook.react.bridge.ReactApplicationContext;
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
import com.facebook.react.bridge.ReactContext;
|
|
||||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||||
import com.facebook.react.bridge.ReactMethod;
|
import com.facebook.react.bridge.ReactMethod;
|
||||||
import com.facebook.react.bridge.ReadableMap;
|
import com.facebook.react.bridge.ReadableMap;
|
||||||
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
||||||
import com.facebook.react.bridge.ReadableType;
|
import com.facebook.react.bridge.WritableArray;
|
||||||
import com.facebook.react.bridge.WritableMap;
|
import com.facebook.react.bridge.WritableMap;
|
||||||
|
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
||||||
import com.google.firebase.iid.FirebaseInstanceId;
|
import com.google.firebase.iid.FirebaseInstanceId;
|
||||||
import com.google.firebase.messaging.FirebaseMessaging;
|
import com.google.firebase.messaging.FirebaseMessaging;
|
||||||
import com.google.firebase.messaging.RemoteMessage;
|
import com.google.firebase.messaging.RemoteMessage;
|
||||||
|
import com.google.firebase.messaging.RemoteMessage.Notification;
|
||||||
|
|
||||||
import io.invertase.firebase.Utils;
|
import android.app.Application;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
public class RNFirebaseMessaging extends ReactContextBaseJavaModule {
|
import android.content.Context;
|
||||||
|
|
||||||
private static final String TAG = "RNFirebaseMessaging";
|
import java.util.ArrayList;
|
||||||
private static final String EVENT_NAME_TOKEN = "RNFirebaseRefreshToken";
|
import java.util.Map;
|
||||||
private static final String EVENT_NAME_NOTIFICATION = "RNFirebaseReceiveNotification";
|
import java.util.Set;
|
||||||
private static final String EVENT_NAME_SEND = "RNFirebaseUpstreamSend";
|
import java.util.UUID;
|
||||||
|
|
||||||
public static final String INTENT_NAME_TOKEN = "io.invertase.firebase.refreshToken";
|
public class RNFirebaseMessaging extends ReactContextBaseJavaModule implements LifecycleEventListener, ActivityEventListener {
|
||||||
public static final String INTENT_NAME_NOTIFICATION = "io.invertase.firebase.ReceiveNotification";
|
private final static String TAG = RNFirebaseMessaging.class.getCanonicalName();
|
||||||
public static final String INTENT_NAME_SEND = "io.invertase.firebase.Upstream";
|
private RNFirebaseLocalMessagingHelper mRNFirebaseLocalMessagingHelper;
|
||||||
|
private BadgeHelper mBadgeHelper;
|
||||||
private IntentFilter mRefreshTokenIntentFilter;
|
|
||||||
private IntentFilter mReceiveNotificationIntentFilter;
|
|
||||||
private IntentFilter mReceiveSendIntentFilter;
|
|
||||||
private BroadcastReceiver mBroadcastReceiver;
|
|
||||||
|
|
||||||
public RNFirebaseMessaging(ReactApplicationContext reactContext) {
|
public RNFirebaseMessaging(ReactApplicationContext reactContext) {
|
||||||
super(reactContext);
|
super(reactContext);
|
||||||
mRefreshTokenIntentFilter = new IntentFilter(INTENT_NAME_TOKEN);
|
mRNFirebaseLocalMessagingHelper = new RNFirebaseLocalMessagingHelper((Application) reactContext.getApplicationContext());
|
||||||
mReceiveNotificationIntentFilter = new IntentFilter(INTENT_NAME_NOTIFICATION);
|
mBadgeHelper = new BadgeHelper(reactContext.getApplicationContext());
|
||||||
mReceiveSendIntentFilter = new IntentFilter(INTENT_NAME_SEND);
|
getReactApplicationContext().addLifecycleEventListener(this);
|
||||||
initRefreshTokenHandler();
|
getReactApplicationContext().addActivityEventListener(this);
|
||||||
initMessageHandler();
|
registerTokenRefreshHandler();
|
||||||
initSendHandler();
|
registerMessageHandler();
|
||||||
Log.d(TAG, "New instance");
|
registerLocalMessageHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return TAG;
|
return "RNFirebaseMessaging";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initMessageHandler() {
|
@ReactMethod
|
||||||
Log.d(TAG, "RNFirebase initMessageHandler called");
|
public void getInitialNotification(Promise promise) {
|
||||||
|
Activity activity = getCurrentActivity();
|
||||||
if (mBroadcastReceiver == null) {
|
if (activity == null) {
|
||||||
mBroadcastReceiver = new BroadcastReceiver() {
|
promise.resolve(null);
|
||||||
@Override
|
return;
|
||||||
public void onReceive(Context context, Intent intent) {
|
}
|
||||||
RemoteMessage remoteMessage = intent.getParcelableExtra("data");
|
promise.resolve(parseIntent(getCurrentActivity().getIntent()));
|
||||||
Log.d(TAG, "Firebase onReceive: " + remoteMessage);
|
|
||||||
WritableMap params = Arguments.createMap();
|
|
||||||
|
|
||||||
params.putNull("data");
|
|
||||||
params.putNull("notification");
|
|
||||||
params.putString("id", remoteMessage.getMessageId());
|
|
||||||
params.putString("messageId", remoteMessage.getMessageId());
|
|
||||||
|
|
||||||
|
|
||||||
if (remoteMessage.getData().size() != 0) {
|
|
||||||
WritableMap dataMap = Arguments.createMap();
|
|
||||||
Map<String, String> data = remoteMessage.getData();
|
|
||||||
|
|
||||||
for (String key : data.keySet()) {
|
|
||||||
dataMap.putString(key, data.get(key));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
params.putMap("data", dataMap);
|
@ReactMethod
|
||||||
|
public void requestPermissions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
if (remoteMessage.getNotification() != null) {
|
public void getToken(Promise promise) {
|
||||||
WritableMap notificationMap = Arguments.createMap();
|
Log.d(TAG, "Firebase token: " + FirebaseInstanceId.getInstance().getToken());
|
||||||
RemoteMessage.Notification notification = remoteMessage.getNotification();
|
promise.resolve(FirebaseInstanceId.getInstance().getToken());
|
||||||
notificationMap.putString("title", notification.getTitle());
|
|
||||||
notificationMap.putString("body", notification.getBody());
|
|
||||||
notificationMap.putString("icon", notification.getIcon());
|
|
||||||
notificationMap.putString("sound", notification.getSound());
|
|
||||||
notificationMap.putString("tag", notification.getTag());
|
|
||||||
params.putMap("notification", notificationMap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReactContext ctx = getReactApplicationContext();
|
@ReactMethod
|
||||||
Utils.sendEvent(ctx, EVENT_NAME_NOTIFICATION, params);
|
public void createLocalNotification(ReadableMap details) {
|
||||||
}
|
Bundle bundle = Arguments.toBundle(details);
|
||||||
};
|
mRNFirebaseLocalMessagingHelper.sendNotification(bundle);
|
||||||
|
|
||||||
}
|
|
||||||
getReactApplicationContext().registerReceiver(mBroadcastReceiver, mReceiveNotificationIntentFilter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@ReactMethod
|
||||||
*
|
public void scheduleLocalNotification(ReadableMap details) {
|
||||||
*/
|
Bundle bundle = Arguments.toBundle(details);
|
||||||
private void initRefreshTokenHandler() {
|
mRNFirebaseLocalMessagingHelper.sendNotificationScheduled(bundle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void cancelLocalNotification(String notificationID) {
|
||||||
|
mRNFirebaseLocalMessagingHelper.cancelLocalNotification(notificationID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void cancelAllLocalNotifications() {
|
||||||
|
mRNFirebaseLocalMessagingHelper.cancelAllLocalNotifications();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void removeDeliveredNotification(String notificationID) {
|
||||||
|
mRNFirebaseLocalMessagingHelper.removeDeliveredNotification(notificationID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void removeAllDeliveredNotifications() {
|
||||||
|
mRNFirebaseLocalMessagingHelper.removeAllDeliveredNotifications();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void subscribeToTopic(String topic) {
|
||||||
|
FirebaseMessaging.getInstance().subscribeToTopic(topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void unsubscribeFromTopic(String topic) {
|
||||||
|
FirebaseMessaging.getInstance().unsubscribeFromTopic(topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void getScheduledLocalNotifications(Promise promise) {
|
||||||
|
ArrayList<Bundle> bundles = mRNFirebaseLocalMessagingHelper.getScheduledLocalNotifications();
|
||||||
|
WritableArray array = Arguments.createArray();
|
||||||
|
for (Bundle bundle : bundles) {
|
||||||
|
array.pushMap(Arguments.fromBundle(bundle));
|
||||||
|
}
|
||||||
|
promise.resolve(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void setBadgeNumber(int badgeNumber) {
|
||||||
|
mBadgeHelper.setBadgeCount(badgeNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void getBadgeNumber(Promise promise) {
|
||||||
|
promise.resolve(mBadgeHelper.getBadgeCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendEvent(String eventName, Object params) {
|
||||||
|
getReactApplicationContext()
|
||||||
|
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
||||||
|
.emit(eventName, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerTokenRefreshHandler() {
|
||||||
|
IntentFilter intentFilter = new IntentFilter("io.invertase.firebase.messaging.FCMRefreshToken");
|
||||||
getReactApplicationContext().registerReceiver(new BroadcastReceiver() {
|
getReactApplicationContext().registerReceiver(new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
WritableMap params = Arguments.createMap();
|
if (getReactApplicationContext().hasActiveCatalystInstance()) {
|
||||||
params.putString("token", intent.getStringExtra("token"));
|
String token = intent.getStringExtra("token");
|
||||||
ReactContext ctx = getReactApplicationContext();
|
sendEvent("FCMTokenRefreshed", token);
|
||||||
Log.d(TAG, "initRefreshTokenHandler received event " + EVENT_NAME_TOKEN);
|
|
||||||
Utils.sendEvent(ctx, EVENT_NAME_TOKEN, params);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
;
|
}, intentFilter);
|
||||||
}, mRefreshTokenIntentFilter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void subscribeToTopic(String topic, final Callback callback) {
|
public void send(String senderId, ReadableMap payload) throws Exception {
|
||||||
try {
|
|
||||||
FirebaseMessaging.getInstance().subscribeToTopic(topic);
|
|
||||||
callback.invoke(null, topic);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
Log.d(TAG, "Firebase token: " + e);
|
|
||||||
WritableMap error = Arguments.createMap();
|
|
||||||
error.putString("message", e.getMessage());
|
|
||||||
callback.invoke(error);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ReactMethod
|
|
||||||
public void getToken(final Promise promise) {
|
|
||||||
try {
|
|
||||||
String token = FirebaseInstanceId.getInstance().getToken();
|
|
||||||
Log.d(TAG, "Firebase token: " + token);
|
|
||||||
promise.resolve(token);
|
|
||||||
} catch (Exception e) {
|
|
||||||
promise.reject("messaging/unknown", e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ReactMethod
|
|
||||||
public void unsubscribeFromTopic(String topic, final Callback callback) {
|
|
||||||
try {
|
|
||||||
FirebaseMessaging.getInstance().unsubscribeFromTopic(topic);
|
|
||||||
callback.invoke(null, topic);
|
|
||||||
} catch (Exception e) {
|
|
||||||
WritableMap error = Arguments.createMap();
|
|
||||||
error.putString("message", e.getMessage());
|
|
||||||
callback.invoke(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// String senderId, String messageId, String messageType,
|
|
||||||
@ReactMethod
|
|
||||||
public void send(ReadableMap params, final Promise promise) {
|
|
||||||
ReadableMap data = params.getMap("data");
|
|
||||||
FirebaseMessaging fm = FirebaseMessaging.getInstance();
|
FirebaseMessaging fm = FirebaseMessaging.getInstance();
|
||||||
RemoteMessage.Builder remoteMessage = new RemoteMessage.Builder(params.getString("sender"));
|
RemoteMessage.Builder message = new RemoteMessage.Builder(senderId + "@gcm.googleapis.com")
|
||||||
|
.setMessageId(UUID.randomUUID().toString());
|
||||||
remoteMessage.setMessageId(params.getString("id"));
|
|
||||||
remoteMessage.setMessageType(params.getString("type"));
|
|
||||||
|
|
||||||
if (params.hasKey("ttl")) {
|
|
||||||
remoteMessage.setTtl(params.getInt("ttl"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.hasKey("collapseKey")) {
|
|
||||||
remoteMessage.setCollapseKey(params.getString("collapseKey"));
|
|
||||||
}
|
|
||||||
|
|
||||||
ReadableMapKeySetIterator iterator = data.keySetIterator();
|
|
||||||
|
|
||||||
|
ReadableMapKeySetIterator iterator = payload.keySetIterator();
|
||||||
while (iterator.hasNextKey()) {
|
while (iterator.hasNextKey()) {
|
||||||
String key = iterator.nextKey();
|
String key = iterator.nextKey();
|
||||||
ReadableType type = data.getType(key);
|
String value = getStringFromReadableMap(payload, key);
|
||||||
if (type == ReadableType.String) {
|
message.addData(key, value);
|
||||||
remoteMessage.addData(key, data.getString(key));
|
|
||||||
}
|
}
|
||||||
|
fm.send(message.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getStringFromReadableMap(ReadableMap map, String key) throws Exception {
|
||||||
|
switch (map.getType(key)) {
|
||||||
|
case String:
|
||||||
|
return map.getString(key);
|
||||||
|
case Number:
|
||||||
try {
|
try {
|
||||||
fm.send(remoteMessage.build());
|
return String.valueOf(map.getInt(key));
|
||||||
WritableMap res = Arguments.createMap();
|
|
||||||
promise.resolve(null);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "send: error sending message", e);
|
return String.valueOf(map.getDouble(key));
|
||||||
promise.reject("messaging/unknown", e.getMessage(), e);
|
}
|
||||||
|
case Boolean:
|
||||||
|
return String.valueOf(map.getBoolean(key));
|
||||||
|
default:
|
||||||
|
throw new Exception("Unknown data type: " + map.getType(key).name() + " for message key " + key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initSendHandler() {
|
private void registerMessageHandler() {
|
||||||
|
IntentFilter intentFilter = new IntentFilter("io.invertase.firebase.messaging.ReceiveNotification");
|
||||||
|
|
||||||
getReactApplicationContext().registerReceiver(new BroadcastReceiver() {
|
getReactApplicationContext().registerReceiver(new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (getReactApplicationContext().hasActiveCatalystInstance()) {
|
||||||
|
RemoteMessage message = intent.getParcelableExtra("data");
|
||||||
WritableMap params = Arguments.createMap();
|
WritableMap params = Arguments.createMap();
|
||||||
if (intent.getBooleanExtra("hasError", false)) {
|
WritableMap fcmData = Arguments.createMap();
|
||||||
WritableMap error = Arguments.createMap();
|
|
||||||
error.putInt("code", intent.getIntExtra("errCode", 0));
|
if (message.getNotification() != null) {
|
||||||
error.putString("message", intent.getStringExtra("errorMessage"));
|
Notification notification = message.getNotification();
|
||||||
params.putMap("err", error);
|
fcmData.putString("title", notification.getTitle());
|
||||||
|
fcmData.putString("body", notification.getBody());
|
||||||
|
fcmData.putString("color", notification.getColor());
|
||||||
|
fcmData.putString("icon", notification.getIcon());
|
||||||
|
fcmData.putString("tag", notification.getTag());
|
||||||
|
fcmData.putString("action", notification.getClickAction());
|
||||||
|
}
|
||||||
|
params.putMap("fcm", fcmData);
|
||||||
|
|
||||||
|
if (message.getData() != null) {
|
||||||
|
Map<String, String> data = message.getData();
|
||||||
|
Set<String> keysIterator = data.keySet();
|
||||||
|
for (String key : keysIterator) {
|
||||||
|
params.putString(key, data.get(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sendEvent("FCMNotificationReceived", params);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, intentFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerLocalMessageHandler() {
|
||||||
|
IntentFilter intentFilter = new IntentFilter("io.invertase.firebase.messaging.ReceiveLocalNotification");
|
||||||
|
|
||||||
|
getReactApplicationContext().registerReceiver(new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (getReactApplicationContext().hasActiveCatalystInstance()) {
|
||||||
|
sendEvent("FCMNotificationReceived", Arguments.fromBundle(intent.getExtras()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, intentFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private WritableMap parseIntent(Intent intent) {
|
||||||
|
WritableMap params;
|
||||||
|
Bundle extras = intent.getExtras();
|
||||||
|
if (extras != null) {
|
||||||
|
try {
|
||||||
|
params = Arguments.fromBundle(extras);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, e.getMessage());
|
||||||
|
params = Arguments.createMap();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
params.putNull("err");
|
params = Arguments.createMap();
|
||||||
}
|
}
|
||||||
ReactContext ctx = getReactApplicationContext();
|
WritableMap fcm = Arguments.createMap();
|
||||||
Utils.sendEvent(ctx, EVENT_NAME_SEND, params);
|
fcm.putString("action", intent.getAction());
|
||||||
|
params.putMap("fcm", fcm);
|
||||||
|
|
||||||
|
params.putBoolean("opened_from_tray", true);
|
||||||
|
return params;
|
||||||
}
|
}
|
||||||
}, mReceiveSendIntentFilter);
|
|
||||||
|
@Override
|
||||||
|
public void onHostResume() {
|
||||||
|
mRNFirebaseLocalMessagingHelper.setApplicationForeground(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHostPause() {
|
||||||
|
mRNFirebaseLocalMessagingHelper.setApplicationForeground(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHostDestroy() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
|
||||||
|
// todo hmm?
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNewIntent(Intent intent) {
|
||||||
|
// todo hmm?
|
||||||
|
sendEvent("FCMNotificationReceived", parseIntent(intent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,30 @@
|
||||||
import { NativeModules, NativeEventEmitter } from 'react-native';
|
import { NativeModules, DeviceEventEmitter, Platform } from 'react-native';
|
||||||
import { Base } from './../base';
|
import { Base } from './../base';
|
||||||
import { promisify } from './../../utils';
|
|
||||||
|
|
||||||
const FirebaseMessaging = NativeModules.RNFirebaseMessaging;
|
const FirebaseMessaging = NativeModules.RNFirebaseMessaging;
|
||||||
const FirebaseMessagingEvt = new NativeEventEmitter(FirebaseMessaging);
|
|
||||||
|
export const EVENT_TYPE = {
|
||||||
|
RefreshToken: 'FCMTokenRefreshed',
|
||||||
|
Notification: 'FCMNotificationReceived',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const NOTIFICATION_TYPE = {
|
||||||
|
Remote: 'remote_notification',
|
||||||
|
NotificationResponse: 'notification_response',
|
||||||
|
WillPresent: 'will_present_notification',
|
||||||
|
Local: 'local_notification',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const REMOTE_NOTIFICATION_RESULT = {
|
||||||
|
NewData: 'UIBackgroundFetchResultNewData',
|
||||||
|
NoData: 'UIBackgroundFetchResultNoData',
|
||||||
|
ResultFailed: 'UIBackgroundFetchResultFailed',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const WILL_PRESENT_RESULT = {
|
||||||
|
All: 'UNNotificationPresentationOptionAll',
|
||||||
|
None: 'UNNotificationPresentationOptionNone',
|
||||||
|
};
|
||||||
|
|
||||||
type RemoteMessage = {
|
type RemoteMessage = {
|
||||||
id: string,
|
id: string,
|
||||||
|
@ -14,6 +35,48 @@ type RemoteMessage = {
|
||||||
data: Object,
|
data: Object,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IOS only finish function
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
function finish(data) {
|
||||||
|
if (Platform.OS !== 'ios') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!this._finishCalled && this._completionHandlerId) {
|
||||||
|
let result = Object.assign({}, data);
|
||||||
|
|
||||||
|
this._finishCalled = true;
|
||||||
|
|
||||||
|
switch (this._notificationType) {
|
||||||
|
case NOTIFICATION_TYPE.Remote:
|
||||||
|
result = result || REMOTE_NOTIFICATION_RESULT.NoData;
|
||||||
|
if (!Object.values(REMOTE_NOTIFICATION_RESULT).includes(result)) {
|
||||||
|
throw new Error('Invalid REMOTE_NOTIFICATION_RESULT value, use messaging().REMOTE_NOTIFICATION_RESULT');
|
||||||
|
}
|
||||||
|
|
||||||
|
FirebaseMessaging.finishRemoteNotification(this._completionHandlerId, result);
|
||||||
|
return;
|
||||||
|
case NOTIFICATION_TYPE.NotificationResponse:
|
||||||
|
FirebaseMessaging.finishNotificationResponse(this._completionHandlerId);
|
||||||
|
return;
|
||||||
|
case NOTIFICATION_TYPE.WillPresent:
|
||||||
|
result = result || (this.show_in_foreground ? WILL_PRESENT_RESULT.All : WILL_PRESENT_RESULT.None);
|
||||||
|
if (!Object.values(WILL_PRESENT_RESULT).includes(result)) {
|
||||||
|
throw new Error('Invalid WILL_PRESENT_RESULT value, use messaging().WILL_PRESENT_RESULT');
|
||||||
|
}
|
||||||
|
|
||||||
|
FirebaseMessaging.finishWillPresentNotification(this._completionHandlerId, result);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class Messaging
|
* @class Messaging
|
||||||
*/
|
*/
|
||||||
|
@ -23,80 +86,150 @@ export default class Messaging extends Base {
|
||||||
this.namespace = 'firebase:messaging';
|
this.namespace = 'firebase:messaging';
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
get EVENT_TYPE() {
|
||||||
* WEB API
|
return EVENT_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
get NOTIFICATION_TYPE() {
|
||||||
|
return NOTIFICATION_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
get REMOTE_NOTIFICATION_RESULT() {
|
||||||
|
return REMOTE_NOTIFICATION_RESULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
get WILL_PRESENT_RESULT() {
|
||||||
|
return WILL_PRESENT_RESULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the notification that triggered application open
|
||||||
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
// TODO move to new event emitter logic
|
getInitialNotification() {
|
||||||
onMessage(callback) {
|
return FirebaseMessaging.getInitialNotification();
|
||||||
this.log.info('Setting up onMessage callback');
|
|
||||||
const sub = this._on('RNFirebaseReceiveNotification', callback, FirebaseMessagingEvt);
|
|
||||||
return promisify(() => sub, FirebaseMessaging)(sub);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO this is wrong - also there is no 'off' onMessage should return the unsubscribe function?
|
|
||||||
offMessage() {
|
|
||||||
this.log.info('Unlistening from onMessage (offMessage)');
|
|
||||||
this._off('FirebaseReceiveNotification');
|
|
||||||
}
|
|
||||||
|
|
||||||
offMessageReceived(...args) {
|
|
||||||
return this.offMessage(...args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the fcm token for the current device
|
||||||
|
* @returns {*|Promise.<String>}
|
||||||
|
*/
|
||||||
getToken() {
|
getToken() {
|
||||||
return FirebaseMessaging.getToken();
|
return FirebaseMessaging.getToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
send(remoteMessage: RemoteMessage) {
|
/**
|
||||||
if (!remoteMessage || !remoteMessage.data) return Promise.reject(new Error('Invalid remote message format provided.'));
|
* Create and display a local notification
|
||||||
return FirebaseMessaging.send(remoteMessage);
|
* @param notification
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
createLocalNotification(notification: Object) {
|
||||||
|
const _notification = Object.assign({}, notification);
|
||||||
|
_notification.id = _notification.id || new Date().getTime().toString();
|
||||||
|
_notification.local_notification = true;
|
||||||
|
return FirebaseMessaging.createLocalNotification(_notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
/**
|
||||||
listenForTokenRefresh(callback) {
|
*
|
||||||
this.log.info('Setting up listenForTokenRefresh callback');
|
* @param notification
|
||||||
const sub = this._on('RNFirebaseRefreshToken', callback, FirebaseMessagingEvt);
|
* @returns {*}
|
||||||
return promisify(() => sub, FirebaseMessaging)(sub);
|
*/
|
||||||
|
scheduleLocalNotification(notification: Object) {
|
||||||
|
const _notification = Object.assign({}, notification);
|
||||||
|
if (!notification.id) return Promise.reject(new Error('An id is required to schedule a local notification.'));
|
||||||
|
_notification.local_notification = true;
|
||||||
|
return FirebaseMessaging.scheduleLocalNotification(_notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
unlistenForTokenRefresh() {
|
/**
|
||||||
this.log.info('Unlistening for TokenRefresh');
|
* Returns an array of all scheduled notifications
|
||||||
this._off('RNFirebaseRefreshToken');
|
* @returns {Promise.<Array>}
|
||||||
|
*/
|
||||||
|
getScheduledLocalNotifications() {
|
||||||
|
return FirebaseMessaging.getScheduledLocalNotifications();
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribeToTopic(topic) {
|
/**
|
||||||
this.log.info(`subscribeToTopic ${topic}`);
|
* Cancel a local notification by id - using '*' will cancel
|
||||||
const finalTopic = `/topics/${topic}`;
|
* all local notifications.
|
||||||
return promisify('subscribeToTopic', FirebaseMessaging)(finalTopic);
|
* @param id
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
cancelLocalNotification(id: string) {
|
||||||
|
if (!id) return null;
|
||||||
|
if (id === '*') return FirebaseMessaging.cancelAllLocalNotifications();
|
||||||
|
return FirebaseMessaging.cancelLocalNotification(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsubscribeFromTopic(topic) {
|
/**
|
||||||
this.log.info(`unsubscribeFromTopic ${topic}`);
|
* Remove a delivered notification - using '*' will remove
|
||||||
const finalTopic = `/topics/${topic}`;
|
* all delivered notifications.
|
||||||
return promisify('unsubscribeFromTopic', FirebaseMessaging)(finalTopic);
|
* @param id
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
removeDeliveredNotification(id: string) {
|
||||||
|
if (!id) return null;
|
||||||
|
if (id === '*') return FirebaseMessaging.removeAllDeliveredNotifications();
|
||||||
|
return FirebaseMessaging.removeDeliveredNotification(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// New api
|
/**
|
||||||
onRemoteMessage(callback) {
|
* Set notification count badge number
|
||||||
this.log.info('On remote message callback');
|
*/
|
||||||
const sub = this._on('messaging_remote_event_received', callback, FirebaseMessagingEvt);
|
setBadgeNumber() {
|
||||||
return promisify(() => sub, FirebaseMessaging)(sub);
|
FirebaseMessaging.setBadgeNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
onLocalMessage(callback) {
|
/**
|
||||||
this.log.info('on local callback');
|
* set notification count badge number
|
||||||
const sub = this._on('messaging_local_event_received', callback, FirebaseMessagingEvt);
|
* @returns {Promise.<Number>}
|
||||||
return promisify(() => sub, FirebaseMessaging)(sub);
|
*/
|
||||||
|
getBadgeNumber() {
|
||||||
|
return FirebaseMessaging.getBadgeNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
listenForReceiveUpstreamSend(callback) {
|
/**
|
||||||
this.log.info('Setting up send callback');
|
* Subscribe to messages / notifications
|
||||||
const sub = this._on('FirebaseUpstreamSend', callback, FirebaseMessagingEvt);
|
* @param listener
|
||||||
return promisify(() => sub, FirebaseMessaging)(sub);
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
onMessageReceived(listener: Function) {
|
||||||
|
return DeviceEventEmitter.addListener(EVENT_TYPE.Notification, async(event) => {
|
||||||
|
const data = Object.assign({}, event);
|
||||||
|
|
||||||
|
data.finish = finish;
|
||||||
|
|
||||||
|
await listener(data);
|
||||||
|
|
||||||
|
if (!data._finishCalled) {
|
||||||
|
data.finish();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
unlistenForReceiveUpstreamSend() {
|
/**
|
||||||
this.log.info('Unlistening for send');
|
* Subscribe to token refresh events
|
||||||
this._off('FirebaseUpstreamSend');
|
* @param listener
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
onTokenRefresh(listener: Function) {
|
||||||
|
return DeviceEventEmitter.addListener(EVENT_TYPE.RefreshToken, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to a topic
|
||||||
|
* @param topic
|
||||||
|
*/
|
||||||
|
subscribeToTopic(topic: String) {
|
||||||
|
FirebaseMessaging.subscribeToTopic(topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsubscribe from a topic
|
||||||
|
* @param topic
|
||||||
|
*/
|
||||||
|
unsubscribeFromTopic(topic: String) {
|
||||||
|
FirebaseMessaging.unsubscribeFromTopic(topic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue