From 0d32471a5aeef52e9eef5ade80071b1a98e16ff0 Mon Sep 17 00:00:00 2001 From: Filippo Dossena Date: Tue, 12 Sep 2017 15:10:53 +0200 Subject: [PATCH 1/3] add "inboxStyle" property to notification --- README.md | 9 + .../helpers/Arguments.java | 424 ++++++++++++++++++ .../helpers/RNUtil.java | 316 +++++++++++++ .../modules/RNPushNotification.java | 2 +- .../modules/RNPushNotificationAttributes.java | 10 + .../modules/RNPushNotificationHelper.java | 25 ++ .../modules/RNPushNotificationJsDelivery.java | 2 +- 7 files changed, 786 insertions(+), 2 deletions(-) create mode 100644 android/src/main/java/com/dieam/reactnativepushnotification/helpers/Arguments.java create mode 100644 android/src/main/java/com/dieam/reactnativepushnotification/helpers/RNUtil.java diff --git a/README.md b/README.md index 36f795974..fc20fe2da 100644 --- a/README.md +++ b/README.md @@ -211,6 +211,15 @@ PushNotification.localNotification({ number: '10', // (optional) Valid 32 bit integer specified as string. default: none (Cannot be zero) repeatType: 'day', // (Android only) Repeating interval. Could be one of `week`, `day`, `hour`, `minute, `time`. If specified as time, it should be accompanied by one more parameter 'repeatTime` which should the number of milliseconds between each interval actions: '["Yes", "No"]', // (Android only) See the doc for notification actions to know more + inboxStyle: { // (Android only) See the android doc (https://developer.android.com/reference/android/app/Notification.InboxStyle.html) + bigContentTitle: 'title', // (optional) + summaryText: 'summary', // (optional) + lines: [ // (optional) Array of strings + 'line 1', + 'line 2', + 'line 3' + ] + } }); ``` diff --git a/android/src/main/java/com/dieam/reactnativepushnotification/helpers/Arguments.java b/android/src/main/java/com/dieam/reactnativepushnotification/helpers/Arguments.java new file mode 100644 index 000000000..e1fc89097 --- /dev/null +++ b/android/src/main/java/com/dieam/reactnativepushnotification/helpers/Arguments.java @@ -0,0 +1,424 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + *

+ * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * Copied from: https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/bridge/Arguments.java + * because support to lists was introduced only in RN v0.48.0 + */ +package com.dieam.reactnativepushnotification.helpers; + +import java.lang.reflect.Array; + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.annotation.Nullable; + +import android.os.Bundle; + +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +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.WritableNativeArray; +import com.facebook.react.bridge.WritableNativeMap; + +public class Arguments { + private static Object makeNativeObject(Object object) { + if (object == null) { + return null; + } else if (object instanceof Float || + object instanceof Long || + object instanceof Byte || + object instanceof Short) { + return new Double(((Number) object).doubleValue()); + } else if (object.getClass().isArray()) { + return makeNativeArray(object); + } else if (object instanceof List) { + return makeNativeArray((List) object); + } else if (object instanceof Map) { + return makeNativeMap((Map) object); + } else if (object instanceof Bundle) { + return makeNativeMap((Bundle) object); + } else { + // Boolean, Integer, Double, String, WritableNativeArray, WritableNativeMap + return object; + } + } + + /** + * This method converts a List into a NativeArray. The data types supported + * are boolean, int, float, double, and String. List, Map, and Bundle + * objects, as well as arrays, containing values of the above types and/or + * null, or any recursive arrangement of these, are also supported. The best + * way to think of this is a way to generate a Java representation of a json + * list, from Java types which have a natural representation in json. + */ + public static WritableNativeArray makeNativeArray(List objects) { + WritableNativeArray nativeArray = new WritableNativeArray(); + if (objects == null) { + return nativeArray; + } + for (Object elem : objects) { + elem = makeNativeObject(elem); + if (elem == null) { + nativeArray.pushNull(); + } else if (elem instanceof Boolean) { + nativeArray.pushBoolean((Boolean) elem); + } else if (elem instanceof Integer) { + nativeArray.pushInt((Integer) elem); + } else if (elem instanceof Double) { + nativeArray.pushDouble((Double) elem); + } else if (elem instanceof String) { + nativeArray.pushString((String) elem); + } else if (elem instanceof WritableNativeArray) { + nativeArray.pushArray((WritableNativeArray) elem); + } else if (elem instanceof WritableNativeMap) { + nativeArray.pushMap((WritableNativeMap) elem); + } else { + throw new IllegalArgumentException("Could not convert " + elem.getClass()); + } + } + return nativeArray; + } + + /** + * This overload is like the above, but uses reflection to operate on any + * primitive or object type. + */ + public static WritableNativeArray makeNativeArray(final Object objects) { + if (objects == null) { + return new WritableNativeArray(); + } + // No explicit check for objects's type here. If it's not an array, the + // Array methods will throw IllegalArgumentException. + return makeNativeArray(new AbstractList() { + public int size() { + return Array.getLength(objects); + } + + public Object get(int index) { + return Array.get(objects, index); + } + }); + } + + private static void addEntry(WritableNativeMap nativeMap, String key, Object value) { + value = makeNativeObject(value); + if (value == null) { + nativeMap.putNull(key); + } else if (value instanceof Boolean) { + nativeMap.putBoolean(key, (Boolean) value); + } else if (value instanceof Integer) { + nativeMap.putInt(key, (Integer) value); + } else if (value instanceof Number) { + nativeMap.putDouble(key, ((Number) value).doubleValue()); + } else if (value instanceof String) { + nativeMap.putString(key, (String) value); + } else if (value instanceof WritableNativeArray) { + nativeMap.putArray(key, (WritableNativeArray) value); + } else if (value instanceof WritableNativeMap) { + nativeMap.putMap(key, (WritableNativeMap) value); + } else { + throw new IllegalArgumentException("Could not convert " + value.getClass()); + } + } + + /** + * This method converts a Map into a NativeMap. Value types are supported as + * with makeNativeArray. The best way to think of this is a way to generate + * a Java representation of a json object, from Java types which have a + * natural representation in json. + */ + public static WritableNativeMap makeNativeMap(Map objects) { + WritableNativeMap nativeMap = new WritableNativeMap(); + if (objects == null) { + return nativeMap; + } + for (Map.Entry entry : objects.entrySet()) { + addEntry(nativeMap, entry.getKey(), entry.getValue()); + } + return nativeMap; + } + + /** + * Like the above, but takes a Bundle instead of a Map. + */ + public static WritableNativeMap makeNativeMap(Bundle bundle) { + WritableNativeMap nativeMap = new WritableNativeMap(); + if (bundle == null) { + return nativeMap; + } + for (String key : bundle.keySet()) { + addEntry(nativeMap, key, bundle.get(key)); + } + return nativeMap; + } + + /** + * This method should be used when you need to stub out creating NativeArrays in unit tests. + */ + public static WritableArray createArray() { + return new WritableNativeArray(); + } + + /** + * This method should be used when you need to stub out creating NativeMaps in unit tests. + */ + public static WritableMap createMap() { + return new WritableNativeMap(); + } + + public static WritableNativeArray fromJavaArgs(Object[] args) { + WritableNativeArray arguments = new WritableNativeArray(); + for (int i = 0; i < args.length; i++) { + Object argument = args[i]; + if (argument == null) { + arguments.pushNull(); + continue; + } + + Class argumentClass = argument.getClass(); + if (argumentClass == Boolean.class) { + arguments.pushBoolean(((Boolean) argument).booleanValue()); + } else if (argumentClass == Integer.class) { + arguments.pushDouble(((Integer) argument).doubleValue()); + } else if (argumentClass == Double.class) { + arguments.pushDouble(((Double) argument).doubleValue()); + } else if (argumentClass == Float.class) { + arguments.pushDouble(((Float) argument).doubleValue()); + } else if (argumentClass == String.class) { + arguments.pushString(argument.toString()); + } else if (argumentClass == WritableNativeMap.class) { + arguments.pushMap((WritableNativeMap) argument); + } else if (argumentClass == WritableNativeArray.class) { + arguments.pushArray((WritableNativeArray) argument); + } else { + throw new RuntimeException("Cannot convert argument of type " + argumentClass); + } + } + return arguments; + } + + /** + * Convert an array to a {@link WritableArray}. + * + * @param array the array to convert. Supported types are: {@code String[]}, {@code Bundle[]}, + * {@code int[]}, {@code float[]}, {@code double[]}, {@code boolean[]}. + * @return the converted {@link WritableArray} + * @throws IllegalArgumentException if the passed object is none of the above types + */ + public static WritableArray fromArray(Object array) { + WritableArray catalystArray = createArray(); + if (array instanceof String[]) { + for (String v : (String[]) array) { + catalystArray.pushString(v); + } + } else if (array instanceof Bundle[]) { + for (Bundle v : (Bundle[]) array) { + catalystArray.pushMap(fromBundle(v)); + } + } else if (array instanceof int[]) { + for (int v : (int[]) array) { + catalystArray.pushInt(v); + } + } else if (array instanceof float[]) { + for (float v : (float[]) array) { + catalystArray.pushDouble(v); + } + } else if (array instanceof double[]) { + for (double v : (double[]) array) { + catalystArray.pushDouble(v); + } + } else if (array instanceof boolean[]) { + for (boolean v : (boolean[]) array) { + catalystArray.pushBoolean(v); + } + } else { + throw new IllegalArgumentException("Unknown array type " + array.getClass()); + } + return catalystArray; + } + + /** + * Convert a {@link List} to a {@link WritableArray}. + * + * @param list the list to convert. Supported value types are: {@code null}, {@code String}, {@code Bundle}, + * {@code List}, {@code Number}, {@code Boolean}, and all array types supported in {@link #fromArray(Object)}. + * @return the converted {@link WritableArray} + * @throws IllegalArgumentException if one of the values from the passed list is none of the above types + */ + public static WritableArray fromList(List list) { + WritableArray catalystArray = createArray(); + for (Object obj : list) { + if (obj == null) { + catalystArray.pushNull(); + } else if (obj.getClass().isArray()) { + catalystArray.pushArray(fromArray(obj)); + } else if (obj instanceof Bundle) { + catalystArray.pushMap(fromBundle((Bundle) obj)); + } else if (obj instanceof List) { + catalystArray.pushArray(fromList((List) obj)); + } else if (obj instanceof String) { + catalystArray.pushString((String) obj); + } else if (obj instanceof Integer) { + catalystArray.pushInt((Integer) obj); + } else if (obj instanceof Number) { + catalystArray.pushDouble(((Number) obj).doubleValue()); + } else if (obj instanceof Boolean) { + catalystArray.pushBoolean((Boolean) obj); + } else { + throw new IllegalArgumentException("Unknown value type " + obj.getClass()); + } + } + return catalystArray; + } + + /** + * Convert a {@link Bundle} to a {@link WritableMap}. Supported key types in the bundle + * are: + *

+ *

+ * + * @param bundle the {@link Bundle} to convert + * @return the converted {@link WritableMap} + * @throws IllegalArgumentException if there are keys of unsupported types + */ + public static WritableMap fromBundle(Bundle bundle) { + WritableMap map = createMap(); + for (String key : bundle.keySet()) { + Object value = bundle.get(key); + if (value == null) { + map.putNull(key); + } else if (value.getClass().isArray()) { + map.putArray(key, fromArray(value)); + } else if (value instanceof String) { + map.putString(key, (String) value); + } else if (value instanceof Number) { + if (value instanceof Integer) { + map.putInt(key, (Integer) value); + } else { + map.putDouble(key, ((Number) value).doubleValue()); + } + } else if (value instanceof Boolean) { + map.putBoolean(key, (Boolean) value); + } else if (value instanceof Bundle) { + map.putMap(key, fromBundle((Bundle) value)); + } else if (value instanceof List) { + map.putArray(key, fromList((List) value)); + } else { + throw new IllegalArgumentException("Could not convert " + value.getClass()); + } + } + return map; + } + + /** + * Convert a {@link WritableArray} to a {@link ArrayList}. + * + * @param readableArray the {@link WritableArray} to convert. + * @return the converted {@link ArrayList}. + */ + @Nullable + public static ArrayList toList(@Nullable ReadableArray readableArray) { + if (readableArray == null) { + return null; + } + + ArrayList list = new ArrayList(); + + for (int i = 0; i < readableArray.size(); i++) { + switch (readableArray.getType(i)) { + case Null: + list.add(null); + break; + case Boolean: + list.add(readableArray.getBoolean(i)); + break; + case Number: + double number = readableArray.getDouble(i); + if (number == Math.rint(number)) { + // Add as an integer + list.add((int) number); + } else { + // Add as a double + list.add(number); + } + break; + case String: + list.add(readableArray.getString(i)); + break; + case Map: + list.add(toBundle(readableArray.getMap(i))); + break; + case Array: + list.add(toList(readableArray.getArray(i))); + break; + default: + throw new IllegalArgumentException("Could not convert object in array."); + } + } + + return list; + } + + /** + * Convert a {@link WritableMap} to a {@link Bundle}. + * Note: Each array is converted to an {@link ArrayList}. + * + * @param readableMap the {@link WritableMap} to convert. + * @return the converted {@link Bundle}. + */ + @Nullable + public static Bundle toBundle(@Nullable ReadableMap readableMap) { + if (readableMap == null) { + return null; + } + + ReadableMapKeySetIterator iterator = readableMap.keySetIterator(); + + Bundle bundle = new Bundle(); + while (iterator.hasNextKey()) { + String key = iterator.nextKey(); + ReadableType readableType = readableMap.getType(key); + switch (readableType) { + case Null: + bundle.putString(key, null); + break; + case Boolean: + bundle.putBoolean(key, readableMap.getBoolean(key)); + break; + case Number: + // Can be int or double. + bundle.putDouble(key, readableMap.getDouble(key)); + break; + case String: + bundle.putString(key, readableMap.getString(key)); + break; + case Map: + bundle.putBundle(key, toBundle(readableMap.getMap(key))); + break; + case Array: + bundle.putSerializable(key, toList(readableMap.getArray(key))); + break; + default: + throw new IllegalArgumentException("Could not convert object with key: " + key + "."); + } + } + + return bundle; + } +} \ No newline at end of file diff --git a/android/src/main/java/com/dieam/reactnativepushnotification/helpers/RNUtil.java b/android/src/main/java/com/dieam/reactnativepushnotification/helpers/RNUtil.java new file mode 100644 index 000000000..6c686f626 --- /dev/null +++ b/android/src/main/java/com/dieam/reactnativepushnotification/helpers/RNUtil.java @@ -0,0 +1,316 @@ +package com.dieam.reactnativepushnotification.helpers; + +import com.facebook.react.bridge.ReadableMapKeySetIterator; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.ReadableType; + + +import com.facebook.react.bridge.WritableArray; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.WritableNativeArray; +import com.facebook.react.bridge.WritableNativeMap; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Iterator; + + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.Nullable; + +/** + * Maintained By: Miguel Caballero + * Source: https://github.com/artemyarulin/react-native-eval/blob/master/android/src/main/java/com/evaluator/react/ConversionUtil.java + */ +public class RNUtil { + private RNUtil() { + } + + /** + * Converts Facebook's ReadableMap to a Java Map<> + * + * @param readableMap The Readable Map to parse + * @return a Java Map<> to be used in memory + */ + public static Map toMap(@Nullable ReadableMap readableMap) { + if (readableMap == null) { + return null; + } + + ReadableMapKeySetIterator iterator = readableMap.keySetIterator(); + if (!iterator.hasNextKey()) { + return null; + } + + Map result = new HashMap<>(); + while (iterator.hasNextKey()) { + String key = iterator.nextKey(); + result.put(key, toObject(readableMap, key)); + } + + return result; + } + + /** + * Attempts to pull the ReadableMap's attribute out as the proper type + * + * @param readableMap The Facebook ReadableMap to parse + * @param key The map key to attempt to read from the readableMap + * @return the converted attribute from the map if available + */ + public static Object toObject(@Nullable ReadableMap readableMap, String key) { + if (readableMap == null) { + return null; + } + + Object result; + ReadableType readableType = readableMap.getType(key); + switch (readableType) { + case Null: + result = null; + break; + case Boolean: + result = readableMap.getBoolean(key); + break; + case Number: + // Can be int or double. + double tmp = readableMap.getDouble(key); + if (tmp == (int) tmp) { + result = (int) tmp; + } else { + result = tmp; + } + break; + case String: + result = readableMap.getString(key); + break; + case Map: + result = toMap(readableMap.getMap(key)); + break; + case Array: + result = toList(readableMap.getArray(key)); + break; + default: + throw new IllegalArgumentException("Could not convert object with key: " + key + "."); + } + + return result; + } + + /** + * Converts a ReadableArray into a Java List<> + * + * @param readableArray the ReadableArray to parse + * @return a Java List<> if applicable + */ + public static List toList(@Nullable ReadableArray readableArray) { + if (readableArray == null) { + return null; + } + + List result = new ArrayList<>(readableArray.size()); + for (int index = 0; index < readableArray.size(); index++) { + ReadableType readableType = readableArray.getType(index); + switch (readableType) { + case Null: + result.add(null); + break; + case Boolean: + result.add(readableArray.getBoolean(index)); + break; + case Number: + // Can be int or double. + double tmp = readableArray.getDouble(index); + if (tmp == (int) tmp) { + result.add((int) tmp); + } else { + result.add(tmp); + } + break; + case String: + result.add(readableArray.getString(index)); + break; + case Map: + result.add(toMap(readableArray.getMap(index))); + break; + case Array: + result = toList(readableArray.getArray(index)); + break; + default: + throw new IllegalArgumentException("Could not convert object with index: " + index + "."); + } + } + + return result; + } + + + /** + * Converts a react native readable map into a JSON object. + * + * @param readableMap map to convert to JSON Object + * @return JSON Object that contains the readable map properties + */ + @Nullable + public static JSONObject readableMapToJson(ReadableMap readableMap) { + JSONObject jsonObject = new JSONObject(); + + if (readableMap == null) { + return null; + } + + ReadableMapKeySetIterator iterator = readableMap.keySetIterator(); + if (!iterator.hasNextKey()) { + return null; + } + + while (iterator.hasNextKey()) { + String key = iterator.nextKey(); + ReadableType readableType = readableMap.getType(key); + + try { + switch (readableType) { + case Null: + jsonObject.put(key, null); + break; + case Boolean: + jsonObject.put(key, readableMap.getBoolean(key)); + break; + case Number: + // Can be int or double. + jsonObject.put(key, readableMap.getInt(key)); + break; + case String: + jsonObject.put(key, readableMap.getString(key)); + break; + case Map: + jsonObject.put(key, readableMapToJson(readableMap.getMap(key))); + break; + case Array: + jsonObject.put(key, convertArrayToJson(readableMap.getArray(key))); + default: + // Do nothing and fail silently + } + } catch (JSONException ex) { + // Do nothing and fail silently + } + } + + return jsonObject; + } + + private static JSONArray convertArrayToJson(ReadableArray readableArray) throws JSONException { + JSONArray array = new JSONArray(); + for (int i = 0; i < readableArray.size(); i++) { + switch (readableArray.getType(i)) { + case Null: + break; + case Boolean: + array.put(readableArray.getBoolean(i)); + break; + case Number: + array.put(readableArray.getDouble(i)); + break; + case String: + array.put(readableArray.getString(i)); + break; + case Map: + array.put(readableMapToJson(readableArray.getMap(i))); + break; + case Array: + array.put(convertArrayToJson(readableArray.getArray(i))); + break; + } + } + return array; + } + + @Nullable + public static WritableMap jsonToWritableMap(JSONObject jsonObject) { + WritableMap writableMap = new WritableNativeMap(); + + if (jsonObject == null) { + return null; + } + + + Iterator iterator = jsonObject.keys(); + if (!iterator.hasNext()) { + return null; + } + + while (iterator.hasNext()) { + String key = iterator.next(); + + try { + Object value = jsonObject.get(key); + + if (value == null) { + writableMap.putNull(key); + } else if (value instanceof Boolean) { + writableMap.putBoolean(key, (Boolean) value); + } else if (value instanceof Integer) { + writableMap.putInt(key, (Integer) value); + } else if (value instanceof Double) { + writableMap.putDouble(key, (Double) value); + } else if (value instanceof String) { + writableMap.putString(key, (String) value); + } else if (value instanceof JSONObject) { + writableMap.putMap(key, jsonToWritableMap((JSONObject) value)); + } else if (value instanceof JSONArray) { + writableMap.putArray(key, jsonArrayToWritableArray((JSONArray) value)); + } + } catch (JSONException ex) { + // Do nothing and fail silently + } + } + + return writableMap; + } + + @Nullable + public static WritableArray jsonArrayToWritableArray(JSONArray jsonArray) { + WritableArray writableArray = new WritableNativeArray(); + + if (jsonArray == null) { + return null; + } + + if (jsonArray.length() <= 0) { + return null; + } + + for (int i = 0; i < jsonArray.length(); i++) { + try { + Object value = jsonArray.get(i); + if (value == null) { + writableArray.pushNull(); + } else if (value instanceof Boolean) { + writableArray.pushBoolean((Boolean) value); + } else if (value instanceof Integer) { + writableArray.pushInt((Integer) value); + } else if (value instanceof Double) { + writableArray.pushDouble((Double) value); + } else if (value instanceof String) { + writableArray.pushString((String) value); + } else if (value instanceof JSONObject) { + writableArray.pushMap(jsonToWritableMap((JSONObject) value)); + } else if (value instanceof JSONArray) { + writableArray.pushArray(jsonArrayToWritableArray((JSONArray) value)); + } + } catch (JSONException e) { + // Do nothing and fail silently + } + } + + return writableArray; + } + +} \ No newline at end of file diff --git a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotification.java b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotification.java index 3ff203a9b..9c7b5b36f 100644 --- a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotification.java +++ b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotification.java @@ -10,8 +10,8 @@ import android.os.Bundle; import com.dieam.reactnativepushnotification.helpers.ApplicationBadgeHelper; +import com.dieam.reactnativepushnotification.helpers.Arguments; import com.facebook.react.bridge.ActivityEventListener; -import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContext; diff --git a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationAttributes.java b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationAttributes.java index 25357af3b..46201d5da 100644 --- a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationAttributes.java +++ b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationAttributes.java @@ -4,8 +4,11 @@ import android.support.annotation.NonNull; import android.util.Log; +import com.dieam.reactnativepushnotification.helpers.Arguments; +import com.dieam.reactnativepushnotification.helpers.RNUtil; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMapKeySetIterator; +import com.facebook.react.bridge.WritableMap; import org.json.JSONException; import org.json.JSONObject; @@ -36,6 +39,7 @@ public class RNPushNotificationAttributes { private static final String REPEAT_TYPE = "repeatType"; private static final String REPEAT_TIME = "repeatTime"; private static final String ONGOING = "ongoing"; + private static final String INBOXSTYLE = "inboxStyle"; private final String id; private final String message; @@ -60,6 +64,7 @@ public class RNPushNotificationAttributes { private final String repeatType; private final double repeatTime; private final boolean ongoing; + private final WritableMap inboxStyle; public RNPushNotificationAttributes(Bundle bundle) { id = bundle.getString(ID); @@ -85,6 +90,7 @@ public RNPushNotificationAttributes(Bundle bundle) { repeatType = bundle.getString(REPEAT_TYPE); repeatTime = bundle.getDouble(REPEAT_TIME); ongoing = bundle.getBoolean(ONGOING); + inboxStyle = bundle.containsKey(INBOXSTYLE) ? Arguments.fromBundle(bundle.getBundle(INBOXSTYLE)) : null; } private RNPushNotificationAttributes(JSONObject jsonObject) { @@ -112,6 +118,7 @@ private RNPushNotificationAttributes(JSONObject jsonObject) { repeatType = jsonObject.has(REPEAT_TYPE) ? jsonObject.getString(REPEAT_TYPE) : null; repeatTime = jsonObject.has(REPEAT_TIME) ? jsonObject.getDouble(REPEAT_TIME) : 0.0; ongoing = jsonObject.has(ONGOING) ? jsonObject.getBoolean(ONGOING) : false; + inboxStyle = jsonObject.has(INBOXSTYLE) ? RNUtil.jsonToWritableMap(jsonObject.getJSONObject(INBOXSTYLE)) : null; } catch (JSONException e) { throw new IllegalStateException("Exception while initializing RNPushNotificationAttributes from JSON", e); } @@ -197,6 +204,7 @@ public Bundle toBundle() { bundle.putString(REPEAT_TYPE, repeatType); bundle.putDouble(REPEAT_TIME, repeatTime); bundle.putBoolean(ONGOING, ongoing); + bundle.putBundle(INBOXSTYLE, inboxStyle != null ? Arguments.toBundle(inboxStyle) : null); return bundle; } @@ -226,6 +234,7 @@ public JSONObject toJson() { jsonObject.put(REPEAT_TYPE, repeatType); jsonObject.put(REPEAT_TIME, repeatTime); jsonObject.put(ONGOING, ongoing); + jsonObject.put(INBOXSTYLE, inboxStyle != null ? RNUtil.readableMapToJson(inboxStyle) : null); } catch (JSONException e) { Log.e(LOG_TAG, "Exception while converting RNPushNotificationAttributes to " + "JSON. Returning an empty object", e); @@ -261,6 +270,7 @@ public String toString() { ", repeatType='" + repeatType + '\'' + ", repeatTime=" + repeatTime + ", ongoing=" + ongoing + + ", inboxStyle=" + inboxStyle.toString() + '}'; } diff --git a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationHelper.java b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationHelper.java index 988cccf49..4477f4915 100644 --- a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationHelper.java +++ b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationHelper.java @@ -22,10 +22,12 @@ import android.util.Log; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableMap; import org.json.JSONArray; import org.json.JSONException; +import java.util.ArrayList; import java.util.Arrays; import static com.dieam.reactnativepushnotification.modules.RNPushNotification.LOG_TAG; @@ -224,6 +226,29 @@ public void sendToNotificationCentre(Bundle bundle) { notification.setStyle(new NotificationCompat.BigTextStyle().bigText(bigText)); + if (bundle.containsKey("inboxStyle")) { + Bundle inboxStyleBundle = bundle.getBundle("inboxStyle"); + String bigContentTitle = inboxStyleBundle.getString("bigContentTitle"); + String summaryText = inboxStyleBundle.getString("summaryText"); + ArrayList lines = inboxStyleBundle.getStringArrayList("lines"); + + NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); + + if (bigContentTitle != null) { + inboxStyle.setBigContentTitle(bigContentTitle); + } + if (summaryText != null) { + inboxStyle.setSummaryText(summaryText); + } + if (lines != null) { + for (int i=0; i Date: Wed, 13 Sep 2017 13:36:37 +0200 Subject: [PATCH 2/3] updated README --- README.md | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index fc20fe2da..c90fab4b1 100644 --- a/README.md +++ b/README.md @@ -211,14 +211,30 @@ PushNotification.localNotification({ number: '10', // (optional) Valid 32 bit integer specified as string. default: none (Cannot be zero) repeatType: 'day', // (Android only) Repeating interval. Could be one of `week`, `day`, `hour`, `minute, `time`. If specified as time, it should be accompanied by one more parameter 'repeatTime` which should the number of milliseconds between each interval actions: '["Yes", "No"]', // (Android only) See the doc for notification actions to know more - inboxStyle: { // (Android only) See the android doc (https://developer.android.com/reference/android/app/Notification.InboxStyle.html) - bigContentTitle: 'title', // (optional) - summaryText: 'summary', // (optional) - lines: [ // (optional) Array of strings - 'line 1', - 'line 2', - 'line 3' - ] + inboxStyle: { // (Android only) See the android doc (https://developer.android.com/reference/android/app/Notification.InboxStyle.html) + bigContentTitle: 'title', // (optional) + summaryText: 'summary', // (optional) + lines: [ // (optional) Array of strings + 'line 1', + 'line 2', + 'line 3' + ] + }, + messagingStyle: { // (Android only) See the android doc (https://developer.android.com/reference/android/app/Notification.MessagingStyle.html) + userDisplayName: 'myName', // (optional) Name to be displayed for any replies sent by the user + conversationTitle: 'My Conversation', // (optional) This should only be used for group messaging and left unset for one-on-one conversations + messages: [ // (optional) List of messages + { + text: 'ehy dude!', // (optional) Text to be displayed as the message content + timestamp: Date.now(), // (optional) Time at which the message arrived + sender: 'George' // (optional) Name of the sender. Should be null for messages by the current user, in which case the platform will insert 'userDisplayName'. + }, + { + text: 'my reply', + timestamp: Date.now(), + sender: null + } + ] } }); ``` From 1df89d09e8bc76725257d65425f96e9713aa280f Mon Sep 17 00:00:00 2001 From: Filippo Dossena Date: Wed, 13 Sep 2017 13:38:54 +0200 Subject: [PATCH 3/3] Revert "updated README" This reverts commit b872072499a0143c525a2a30939c6e9d1d3ecab0. --- README.md | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index c90fab4b1..fc20fe2da 100644 --- a/README.md +++ b/README.md @@ -211,30 +211,14 @@ PushNotification.localNotification({ number: '10', // (optional) Valid 32 bit integer specified as string. default: none (Cannot be zero) repeatType: 'day', // (Android only) Repeating interval. Could be one of `week`, `day`, `hour`, `minute, `time`. If specified as time, it should be accompanied by one more parameter 'repeatTime` which should the number of milliseconds between each interval actions: '["Yes", "No"]', // (Android only) See the doc for notification actions to know more - inboxStyle: { // (Android only) See the android doc (https://developer.android.com/reference/android/app/Notification.InboxStyle.html) - bigContentTitle: 'title', // (optional) - summaryText: 'summary', // (optional) - lines: [ // (optional) Array of strings - 'line 1', - 'line 2', - 'line 3' - ] - }, - messagingStyle: { // (Android only) See the android doc (https://developer.android.com/reference/android/app/Notification.MessagingStyle.html) - userDisplayName: 'myName', // (optional) Name to be displayed for any replies sent by the user - conversationTitle: 'My Conversation', // (optional) This should only be used for group messaging and left unset for one-on-one conversations - messages: [ // (optional) List of messages - { - text: 'ehy dude!', // (optional) Text to be displayed as the message content - timestamp: Date.now(), // (optional) Time at which the message arrived - sender: 'George' // (optional) Name of the sender. Should be null for messages by the current user, in which case the platform will insert 'userDisplayName'. - }, - { - text: 'my reply', - timestamp: Date.now(), - sender: null - } - ] + inboxStyle: { // (Android only) See the android doc (https://developer.android.com/reference/android/app/Notification.InboxStyle.html) + bigContentTitle: 'title', // (optional) + summaryText: 'summary', // (optional) + lines: [ // (optional) Array of strings + 'line 1', + 'line 2', + 'line 3' + ] } }); ```