Skip to content

Commit 6518a1f

Browse files
authored
Merge pull request #130 from CatalystCode/phongcao/mixer-improvements
Integrate new features and improvements from Mixer
2 parents 2c44b56 + 75593a5 commit 6518a1f

27 files changed

+1818
-417
lines changed

android/src/main/java/com/azure/reactnative/notificationhub/ReactNativeConstants.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ public final class ReactNativeConstants {
2222
public static final String KEY_REGISTRATION_CHANNELSHOWBADGE = "channelShowBadge";
2323
public static final String KEY_REGISTRATION_CHANNELENABLELIGHTS = "channelEnableLights";
2424
public static final String KEY_REGISTRATION_CHANNELENABLEVIBRATION = "channelEnableVibration";
25+
public static final String KEY_REGISTRATION_TEMPLATENAME = "templateName";
26+
public static final String KEY_REGISTRATION_TEMPLATE = "template";
27+
public static final String KEY_REGISTRATION_ISTEMPLATE = "isTemplate";
2528

2629
// Shared prefs used in NotificationHubUtil
2730
public static final String SHARED_PREFS_NAME = "com.azure.reactnative.notificationhub.NotificationHubUtil";
@@ -36,6 +39,10 @@ public final class ReactNativeConstants {
3639
public static final String KEY_FOR_PREFS_CHANNELSHOWBADGE = "AzureNotificationHub_channelShowBadge";
3740
public static final String KEY_FOR_PREFS_CHANNELENABLELIGHTS = "AzureNotificationHub_channelEnableLights";
3841
public static final String KEY_FOR_PREFS_CHANNELENABLEVIBRATION = "AzureNotificationHub_channelEnableVibration";
42+
public static final String KEY_FOR_PREFS_TEMPLATENAME = "AzureNotificationHub_templateName";
43+
public static final String KEY_FOR_PREFS_TEMPLATE = "AzureNotificationHub_template";
44+
public static final String KEY_FOR_PREFS_ISTEMPLATE = "AzureNotificationHub_isTemplate";
45+
public static final String KEY_FOR_PREFS_UUID = "AzureNotificationHub_UUID";
3946

4047
// Remote notification payload
4148
public static final String KEY_REMOTE_NOTIFICATION_MESSAGE = "message";
@@ -85,6 +92,10 @@ public final class ReactNativeConstants {
8592
public static final String RESOURCE_NAME_NOTIFICATION = "ic_notification";
8693
public static final String RESOURCE_NAME_LAUNCHER = "ic_launcher";
8794

95+
// Promise
96+
public static final String KEY_PROMISE_RESOLVE_UUID = "uuid";
97+
public static final String AZURE_NOTIFICATION_HUB_UNREGISTERED = "Unregistered successfully";
98+
8899
// Errors
89100
public static final String ERROR_NO_ACTIVITY_CLASS = "No activity class found for the notification";
90101
public static final String ERROR_NO_MESSAGE = "No message specified for the notification";
@@ -96,13 +107,21 @@ public final class ReactNativeConstants {
96107
public static final String ERROR_INVALID_CONNECTION_STRING = "Connection string cannot be null.";
97108
public static final String ERROR_INVALID_HUBNAME = "Hub name cannot be null.";
98109
public static final String ERROR_INVALID_SENDER_ID = "Sender ID cannot be null.";
110+
public static final String ERROR_INVALID_TEMPLATE_NAME = "Template Name cannot be null.";
111+
public static final String ERROR_INVALID_TEMPLATE = "Template cannot be null.";
99112
public static final String ERROR_PLAY_SERVICES = "E_PLAY_SERVICES";
100113
public static final String ERROR_PLAY_SERVICES_DISABLED = "User must enable Google Play Services.";
101114
public static final String ERROR_PLAY_SERVICES_UNSUPPORTED = "This device is not supported by Google Play Services.";
102115
public static final String ERROR_NOTIFICATION_HUB = "E_NOTIFICATION_HUB";
103116
public static final String ERROR_NOT_REGISTERED = "E_NOT_REGISTERED";
104117
public static final String ERROR_NOT_REGISTERED_DESC = "No registration to Azure Notification Hub.";
105118
public static final String ERROR_FETCH_IMAGE = "Error while fetching image.";
119+
public static final String ERROR_GET_INIT_NOTIFICATION = "E_GET_INIT_NOTIF";
120+
public static final String ERROR_ACTIVITY_IS_NULL = "Current activity is null";
121+
public static final String ERROR_INTENT_EXTRAS_IS_NULL = "Intent get extras is null";
122+
public static final String ERROR_ACTIVITY_INTENT_IS_NULL = "Activity intent is null";
123+
public static final String ERROR_GET_UUID = "E_GET_UUID";
124+
public static final String ERROR_NO_UUID_SET = "No uuid set";
106125

107126
private ReactNativeConstants() {
108127
}

android/src/main/java/com/azure/reactnative/notificationhub/ReactNativeNotificationHubModule.java

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
77
import android.content.IntentFilter;
88
import android.os.Bundle;
99

10+
import androidx.core.app.NotificationManagerCompat;
1011
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
1112

1213
import com.facebook.react.bridge.ActivityEventListener;
14+
import com.facebook.react.bridge.Arguments;
1315
import com.facebook.react.bridge.LifecycleEventListener;
16+
import com.facebook.react.bridge.WritableMap;
1417
import com.google.android.gms.common.ConnectionResult;
1518
import com.google.android.gms.common.GoogleApiAvailability;
1619

@@ -61,6 +64,29 @@ public boolean getIsForeground() {
6164
return notificationHubUtil.getAppIsForeground();
6265
}
6366

67+
@ReactMethod
68+
public void getInitialNotification(Promise promise) {
69+
Activity activity = getCurrentActivity();
70+
if (activity == null) {
71+
promise.reject(ERROR_GET_INIT_NOTIFICATION, ERROR_ACTIVITY_IS_NULL);
72+
return;
73+
}
74+
75+
Intent intent = activity.getIntent();
76+
if (intent != null && intent.getAction() != null) {
77+
if (intent.getExtras() == null) {
78+
// In certain cases while app cold launches, i.getExtras() returns null.
79+
// Adding the check to make sure app won't crash,
80+
// and still successfully launches from notification
81+
promise.reject(ERROR_GET_INIT_NOTIFICATION, ERROR_INTENT_EXTRAS_IS_NULL);
82+
} else {
83+
promise.resolve(ReactNativeUtil.convertBundleToMap(intent.getExtras()));
84+
}
85+
} else {
86+
promise.reject(ERROR_GET_INIT_NOTIFICATION, ERROR_ACTIVITY_INTENT_IS_NULL);
87+
}
88+
}
89+
6490
@ReactMethod
6591
public void register(ReadableMap config, Promise promise) {
6692
ReactNativeNotificationHubUtil notificationHubUtil = ReactNativeNotificationHubUtil.getInstance();
@@ -95,6 +121,114 @@ public void register(ReadableMap config, Promise promise) {
95121
notificationHubUtil.setConnectionString(reactContext, connectionString);
96122
notificationHubUtil.setHubName(reactContext, hubName);
97123
notificationHubUtil.setSenderID(reactContext, senderID);
124+
notificationHubUtil.setTemplated(reactContext, false);
125+
notificationHubUtil.setTags(reactContext, tags);
126+
127+
if (config.hasKey(KEY_REGISTRATION_CHANNELNAME)) {
128+
String channelName = config.getString(KEY_REGISTRATION_CHANNELNAME);
129+
notificationHubUtil.setChannelName(reactContext, channelName);
130+
}
131+
132+
if (config.hasKey(KEY_REGISTRATION_CHANNELIMPORTANCE)) {
133+
int channelImportance = config.getInt(KEY_REGISTRATION_CHANNELIMPORTANCE);
134+
notificationHubUtil.setChannelImportance(reactContext, channelImportance);
135+
}
136+
137+
if (config.hasKey(KEY_REGISTRATION_CHANNELSHOWBADGE)) {
138+
boolean channelShowBadge = config.getBoolean(KEY_REGISTRATION_CHANNELSHOWBADGE);
139+
notificationHubUtil.setChannelShowBadge(reactContext, channelShowBadge);
140+
}
141+
142+
if (config.hasKey(KEY_REGISTRATION_CHANNELENABLELIGHTS)) {
143+
boolean channelEnableLights = config.getBoolean(KEY_REGISTRATION_CHANNELENABLELIGHTS);
144+
notificationHubUtil.setChannelEnableLights(reactContext, channelEnableLights);
145+
}
146+
147+
if (config.hasKey(KEY_REGISTRATION_CHANNELENABLEVIBRATION)) {
148+
boolean channelEnableVibration = config.getBoolean(KEY_REGISTRATION_CHANNELENABLEVIBRATION);
149+
notificationHubUtil.setChannelEnableVibration(reactContext, channelEnableVibration);
150+
}
151+
152+
String uuid = notificationHubUtil.getUUID(reactContext);
153+
if (uuid == null) {
154+
uuid = ReactNativeUtil.genUUID();
155+
notificationHubUtil.setUUID(reactContext, uuid);
156+
}
157+
158+
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
159+
int resultCode = apiAvailability.isGooglePlayServicesAvailable(reactContext);
160+
if (resultCode != ConnectionResult.SUCCESS) {
161+
if (apiAvailability.isUserResolvableError(resultCode)) {
162+
UiThreadUtil.runOnUiThread(
163+
new GoogleApiAvailabilityRunnable(
164+
getCurrentActivity(),
165+
apiAvailability,
166+
resultCode));
167+
promise.reject(ERROR_PLAY_SERVICES, ERROR_PLAY_SERVICES_DISABLED);
168+
} else {
169+
promise.reject(ERROR_PLAY_SERVICES, ERROR_PLAY_SERVICES_UNSUPPORTED);
170+
}
171+
return;
172+
}
173+
174+
Intent intent = ReactNativeNotificationHubUtil.IntentFactory.createIntent(
175+
reactContext, ReactNativeRegistrationIntentService.class);
176+
ReactNativeRegistrationIntentService.enqueueWork(reactContext, intent);
177+
178+
WritableMap res = Arguments.createMap();
179+
res.putString(KEY_PROMISE_RESOLVE_UUID, uuid);
180+
promise.resolve(res);
181+
}
182+
183+
@ReactMethod
184+
public void registerTemplate(ReadableMap config, Promise promise) {
185+
ReactNativeNotificationHubUtil notificationHubUtil = ReactNativeNotificationHubUtil.getInstance();
186+
String connectionString = config.getString(KEY_REGISTRATION_CONNECTIONSTRING);
187+
if (connectionString == null) {
188+
promise.reject(ERROR_INVALID_ARGUMENTS, ERROR_INVALID_CONNECTION_STRING);
189+
return;
190+
}
191+
192+
String hubName = config.getString(KEY_REGISTRATION_HUBNAME);
193+
if (hubName == null) {
194+
promise.reject(ERROR_INVALID_ARGUMENTS, ERROR_INVALID_HUBNAME);
195+
return;
196+
}
197+
198+
String senderID = config.getString(KEY_REGISTRATION_SENDERID);
199+
if (senderID == null) {
200+
promise.reject(ERROR_INVALID_ARGUMENTS, ERROR_INVALID_SENDER_ID);
201+
return;
202+
}
203+
204+
String templateName = config.getString(KEY_REGISTRATION_TEMPLATENAME);
205+
if (templateName == null) {
206+
promise.reject(ERROR_INVALID_ARGUMENTS, ERROR_INVALID_TEMPLATE_NAME);
207+
return;
208+
}
209+
210+
String template = config.getString(KEY_REGISTRATION_TEMPLATE);
211+
if (template == null) {
212+
promise.reject(ERROR_INVALID_ARGUMENTS, ERROR_INVALID_TEMPLATE);
213+
return;
214+
}
215+
216+
String[] tags = null;
217+
if (config.hasKey(KEY_REGISTRATION_TAGS) && !config.isNull(KEY_REGISTRATION_TAGS)) {
218+
ReadableArray tagsJson = config.getArray(KEY_REGISTRATION_TAGS);
219+
tags = new String[tagsJson.size()];
220+
for (int i = 0; i < tagsJson.size(); ++i) {
221+
tags[i] = tagsJson.getString(i);
222+
}
223+
}
224+
225+
ReactContext reactContext = getReactApplicationContext();
226+
notificationHubUtil.setConnectionString(reactContext, connectionString);
227+
notificationHubUtil.setHubName(reactContext, hubName);
228+
notificationHubUtil.setSenderID(reactContext, senderID);
229+
notificationHubUtil.setTemplateName(reactContext, templateName);
230+
notificationHubUtil.setTemplate(reactContext, template);
231+
notificationHubUtil.setTemplated(reactContext, true);
98232
notificationHubUtil.setTags(reactContext, tags);
99233

100234
if (config.hasKey(KEY_REGISTRATION_CHANNELNAME)) {
@@ -122,6 +256,12 @@ public void register(ReadableMap config, Promise promise) {
122256
notificationHubUtil.setChannelEnableVibration(reactContext, channelEnableVibration);
123257
}
124258

259+
String uuid = notificationHubUtil.getUUID(reactContext);
260+
if (uuid == null) {
261+
uuid = ReactNativeUtil.genUUID();
262+
notificationHubUtil.setUUID(reactContext, uuid);
263+
}
264+
125265
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
126266
int resultCode = apiAvailability.isGooglePlayServicesAvailable(reactContext);
127267
if (resultCode != ConnectionResult.SUCCESS) {
@@ -141,6 +281,10 @@ public void register(ReadableMap config, Promise promise) {
141281
Intent intent = ReactNativeNotificationHubUtil.IntentFactory.createIntent(
142282
reactContext, ReactNativeRegistrationIntentService.class);
143283
ReactNativeRegistrationIntentService.enqueueWork(reactContext, intent);
284+
285+
WritableMap res = Arguments.createMap();
286+
res.putString(KEY_PROMISE_RESOLVE_UUID, uuid);
287+
promise.resolve(res);
144288
}
145289

146290
@ReactMethod
@@ -161,11 +305,63 @@ public void unregister(Promise promise) {
161305
try {
162306
hub.unregister();
163307
notificationHubUtil.setRegistrationID(reactContext, null);
308+
notificationHubUtil.setUUID(reactContext, null);
309+
promise.resolve(AZURE_NOTIFICATION_HUB_UNREGISTERED);
164310
} catch (Exception e) {
165311
promise.reject(ERROR_NOTIFICATION_HUB, e);
166312
}
167313
}
168314

315+
@ReactMethod
316+
public void unregisterTemplate(String templateName, Promise promise) {
317+
ReactNativeNotificationHubUtil notificationHubUtil = ReactNativeNotificationHubUtil.getInstance();
318+
319+
ReactContext reactContext = getReactApplicationContext();
320+
String connectionString = notificationHubUtil.getConnectionString(reactContext);
321+
String hubName = notificationHubUtil.getHubName(reactContext);
322+
String registrationId = notificationHubUtil.getRegistrationID(reactContext);
323+
324+
if (connectionString == null || hubName == null || registrationId == null) {
325+
promise.reject(ERROR_NOT_REGISTERED, ERROR_NOT_REGISTERED_DESC);
326+
return;
327+
}
328+
329+
NotificationHub hub = ReactNativeUtil.createNotificationHub(hubName, connectionString, reactContext);
330+
try {
331+
hub.unregisterTemplate(templateName);
332+
notificationHubUtil.setRegistrationID(reactContext, null);
333+
notificationHubUtil.setUUID(reactContext, null);
334+
promise.resolve(AZURE_NOTIFICATION_HUB_UNREGISTERED);
335+
} catch (Exception e) {
336+
promise.reject(ERROR_NOTIFICATION_HUB, e);
337+
}
338+
}
339+
340+
@ReactMethod
341+
public void getUUID(Boolean autoGen, Promise promise) {
342+
ReactNativeNotificationHubUtil notificationHubUtil = ReactNativeNotificationHubUtil.getInstance();
343+
ReactContext reactContext = getReactApplicationContext();
344+
String uuid = notificationHubUtil.getUUID(reactContext);
345+
346+
if (uuid != null) {
347+
promise.resolve(uuid);
348+
} else if (autoGen) {
349+
uuid = ReactNativeUtil.genUUID();
350+
notificationHubUtil.setUUID(reactContext, uuid);
351+
promise.resolve(uuid);
352+
} else {
353+
promise.reject(ERROR_GET_UUID, ERROR_NO_UUID_SET);
354+
}
355+
}
356+
357+
@ReactMethod
358+
public void isNotificationEnabledOnOSLevel(Promise promise) {
359+
ReactContext reactContext = getReactApplicationContext();
360+
NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(reactContext);
361+
boolean areNotificationsEnabled = notificationManagerCompat.areNotificationsEnabled();
362+
promise.resolve(areNotificationsEnabled);
363+
}
364+
169365
@Override
170366
public void onHostResume() {
171367
setIsForeground(true);

android/src/main/java/com/azure/reactnative/notificationhub/ReactNativeNotificationHubUtil.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,38 @@ public boolean hasChannelEnableVibration(Context context) {
165165
return hasKey(context, KEY_FOR_PREFS_CHANNELENABLEVIBRATION);
166166
}
167167

168+
public String getTemplateName(Context context) {
169+
return getPref(context, KEY_FOR_PREFS_TEMPLATENAME);
170+
}
171+
172+
public void setTemplateName(Context context, String templateName) {
173+
setPref(context, KEY_FOR_PREFS_TEMPLATENAME, templateName);
174+
}
175+
176+
public String getTemplate(Context context) {
177+
return getPref(context, KEY_FOR_PREFS_TEMPLATE);
178+
}
179+
180+
public void setTemplate(Context context, String template) {
181+
setPref(context, KEY_FOR_PREFS_TEMPLATE, template);
182+
}
183+
184+
public boolean isTemplated(Context context) {
185+
return getPrefBoolean(context, KEY_FOR_PREFS_ISTEMPLATE);
186+
}
187+
188+
public void setTemplated(Context context, boolean templated) {
189+
setPrefBoolean(context, KEY_FOR_PREFS_ISTEMPLATE, templated);
190+
}
191+
192+
public String getUUID(Context context) {
193+
return getPref(context, KEY_FOR_PREFS_UUID);
194+
}
195+
196+
public void setUUID(Context context, String uuid) {
197+
setPref(context, KEY_FOR_PREFS_UUID, uuid);
198+
}
199+
168200
public void setAppIsForeground(boolean isForeground) {
169201
mIsForeground = isForeground;
170202
}

android/src/main/java/com/azure/reactnative/notificationhub/ReactNativeRegistrationIntentService.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ protected void onHandleWork(Intent intent) {
3838
final String hubName = notificationHubUtil.getHubName(this);
3939
final String storedToken = notificationHubUtil.getFCMToken(this);
4040
final String[] tags = notificationHubUtil.getTags(this);
41+
final boolean isTemplated = notificationHubUtil.isTemplated(this);
42+
final String templateName = notificationHubUtil.getTemplateName(this);
43+
final String template = notificationHubUtil.getTemplate(this);
4144

4245
if (connectionString == null || hubName == null) {
4346
// The intent was triggered when no connection string has been set.
@@ -63,7 +66,13 @@ public void onSuccess(InstanceIdResult instanceIdResult) {
6366
ReactNativeRegistrationIntentService.this);
6467
Log.d(TAG, "NH Registration refreshing with token : " + token);
6568

66-
regID = hub.register(token, tags).getRegistrationId();
69+
if (isTemplated) {
70+
regID = hub.registerTemplate(
71+
token, templateName, template, tags).getRegistrationId();
72+
} else {
73+
regID = hub.register(token, tags).getRegistrationId();
74+
}
75+
6776
Log.d(TAG, "New NH Registration Successfully - RegId : " + regID);
6877

6978
notificationHubUtil.setRegistrationID(ReactNativeRegistrationIntentService.this, regID);

android/src/main/java/com/azure/reactnative/notificationhub/ReactNativeUtil.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626

2727
import java.io.InputStream;
2828
import java.net.HttpURLConnection;
29-
import java.net.MalformedURLException;
3029
import java.net.URL;
3130
import java.util.Set;
31+
import java.util.UUID;
3232
import java.util.concurrent.ExecutorService;
3333
import java.util.concurrent.Executors;
3434

@@ -335,6 +335,10 @@ public static Bitmap fetchImage(String urlString) {
335335
}
336336
}
337337

338+
public static String genUUID() {
339+
return UUID.randomUUID().toString();
340+
}
341+
338342
private ReactNativeUtil() {
339343
}
340344
}

0 commit comments

Comments
 (0)