Skip to content

Commit 4f2410f

Browse files
committed
Migrate to Flutter 2
* Add Null safety support
1 parent 2982cc1 commit 4f2410f

17 files changed

+237
-221
lines changed

android/src/main/java/com/onesignal/flutter/OneSignalSerializer.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ private static HashMap<String, Object> convertEmailSubscriptionStateToMap(OSEmai
5959
static HashMap<String, Object> convertDeviceStateToMap(OSDeviceState state) {
6060
HashMap<String, Object> hash = new HashMap<>();
6161

62+
if (state == null)
63+
return hash;
64+
6265
hash.put("hasNotificationPermission", state.areNotificationsEnabled());
6366
hash.put("pushDisabled", state.isPushDisabled());
6467
hash.put("subscribed", state.isSubscribed());

example/lib/main.dart

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ class MyApp extends StatefulWidget {
1313

1414
class _MyAppState extends State<MyApp> {
1515
String _debugLabelString = "";
16-
String _emailAddress;
17-
String _externalUserId;
16+
String? _emailAddress;
17+
String? _externalUserId;
1818
bool _enableConsentButton = false;
1919

2020
// CHANGE THIS parameter to true if you want to test GDPR privacy consent
@@ -79,7 +79,7 @@ class _MyAppState extends State<MyApp> {
7979

8080
// NOTE: Replace with your own app ID from https://www.onesignal.com
8181
await OneSignal.shared
82-
.setAppId("380dc082-5231-4cc2-ab51-a03da5a0e4c2");
82+
.setAppId("77e32082-ea27-42e3-a898-c72e141824ef");
8383

8484
bool requiresConsent = await OneSignal.shared.requiresUserPrivacyConsent();
8585

@@ -140,9 +140,9 @@ class _MyAppState extends State<MyApp> {
140140
void _handleGetDeviceState() async {
141141
print("Getting DeviceState");
142142
OneSignal.shared.getDeviceState().then((deviceState) {
143-
print("DeviceState: ${deviceState.jsonRepresentation()}");
143+
print("DeviceState: ${deviceState?.jsonRepresentation()}");
144144
this.setState(() {
145-
_debugLabelString = deviceState.jsonRepresentation();
145+
_debugLabelString = deviceState?.jsonRepresentation() ?? "Device state null";
146146
});
147147
});
148148
}
@@ -152,7 +152,7 @@ class _MyAppState extends State<MyApp> {
152152

153153
print("Setting email");
154154

155-
OneSignal.shared.setEmail(email: _emailAddress).whenComplete(() {
155+
OneSignal.shared.setEmail(email: _emailAddress!).whenComplete(() {
156156
print("Successfully set email");
157157
}).catchError((error) {
158158
print("Failed to set email with error: $error");
@@ -201,7 +201,9 @@ class _MyAppState extends State<MyApp> {
201201

202202
void _handleSetExternalUserId() {
203203
print("Setting external user ID");
204-
OneSignal.shared.setExternalUserId(_externalUserId).then((results) {
204+
if (_externalUserId == null) return;
205+
206+
OneSignal.shared.setExternalUserId(_externalUserId!).then((results) {
205207
if (results == null) return;
206208

207209
this.setState(() {
@@ -223,7 +225,10 @@ class _MyAppState extends State<MyApp> {
223225
void _handleSendNotification() async {
224226
var deviceState = await OneSignal.shared.getDeviceState();
225227

226-
var playerId = deviceState.userId;
228+
if (deviceState == null || deviceState.userId == null)
229+
return;
230+
231+
var playerId = deviceState.userId!;
227232

228233
var imgUrlString =
229234
"http://cdn1-www.dogtime.com/assets/uploads/gallery/30-impossibly-cute-puppies/impossibly-cute-puppy-2.jpg";
@@ -249,7 +254,10 @@ class _MyAppState extends State<MyApp> {
249254
void _handleSendSilentNotification() async {
250255
var deviceState = await OneSignal.shared.getDeviceState();
251256

252-
var playerId = deviceState.userId;
257+
if (deviceState == null || deviceState.userId == null)
258+
return;
259+
260+
var playerId = deviceState.userId!;
253261

254262
var notification = OSCreateNotification.silentNotification(
255263
playerIds: [playerId], additionalData: {'test': 'value'});
@@ -280,8 +288,8 @@ class _MyAppState extends State<MyApp> {
280288
OneSignal.shared.removeTriggerForKey("trigger_2");
281289

282290
// Get the value for a trigger by its key
283-
Object triggerValue = await OneSignal.shared.getTriggerValueForKey("trigger_3");
284-
print("'trigger_3' key trigger value: " + triggerValue.toString());
291+
Object? triggerValue = await OneSignal.shared.getTriggerValueForKey("trigger_3");
292+
print("'trigger_3' key trigger value: ${triggerValue?.toString() ?? null}");
285293

286294
// Create a list and bulk remove triggers based on keys supplied
287295
List<String> keys = ["trigger_1", "trigger_3"];

example/pubspec.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,6 @@ flutter:
5757
#
5858
# For details regarding fonts from package dependencies,
5959
# see https://flutter.io/custom-fonts/#from-packages
60+
environment:
61+
sdk: '>=2.12.0 <3.0.0'
62+
flutter: ">=1.10.0 <2.0.0"

lib/onesignal_flutter.dart

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ class OneSignal {
4040
MethodChannel _outcomesChannel = const MethodChannel('OneSignal#outcomes');
4141

4242
// event handlers
43-
OpenedNotificationHandler _onOpenedNotification;
44-
SubscriptionChangedHandler _onSubscriptionChangedHandler;
45-
EmailSubscriptionChangeHandler _onEmailSubscriptionChangedHandler;
46-
PermissionChangeHandler _onPermissionChangedHandler;
47-
InAppMessageClickedHandler _onInAppMessageClickedHandler;
48-
NotificationWillShowInForegroundHandler _onNotificationWillShowInForegroundHandler;
43+
OpenedNotificationHandler? _onOpenedNotification;
44+
SubscriptionChangedHandler? _onSubscriptionChangedHandler;
45+
EmailSubscriptionChangeHandler? _onEmailSubscriptionChangedHandler;
46+
PermissionChangeHandler? _onPermissionChangedHandler;
47+
InAppMessageClickedHandler? _onInAppMessageClickedHandler;
48+
NotificationWillShowInForegroundHandler? _onNotificationWillShowInForegroundHandler;
4949

5050
// constructor method
5151
OneSignal() {
@@ -179,7 +179,7 @@ class OneSignal {
179179
/// waiting for this request to complete.
180180
Future<Map<String, dynamic>> sendTags(Map<String, dynamic> tags) async {
181181
Map<dynamic, dynamic> response =
182-
await _tagsChannel.invokeMethod("OneSignal#sendTags", tags);
182+
await (_tagsChannel.invokeMethod("OneSignal#sendTags", tags));
183183
return response.cast<String, dynamic>();
184184
}
185185

@@ -190,7 +190,7 @@ class OneSignal {
190190
/// to finish.
191191
Future<Map<String, dynamic>> getTags() async {
192192
Map<dynamic, dynamic> tags =
193-
await _tagsChannel.invokeMethod("OneSignal#getTags");
193+
await (_tagsChannel.invokeMethod("OneSignal#getTags"));
194194
return tags.cast<String, dynamic>();
195195
}
196196

@@ -207,15 +207,18 @@ class OneSignal {
207207
/// array of keys.
208208
Future<Map<String, dynamic>> deleteTags(List<String> keys) async {
209209
Map<dynamic, dynamic> response =
210-
await _tagsChannel.invokeMethod("OneSignal#deleteTags", keys);
210+
await (_tagsChannel.invokeMethod("OneSignal#deleteTags", keys));
211211
return response.cast<String, dynamic>();
212212
}
213213

214214
/// Returns an `OSDeviceState` object, which contains the current device state
215-
Future<OSDeviceState> getDeviceState() async {
215+
Future<OSDeviceState?> getDeviceState() async {
216216
var json =
217217
await _channel.invokeMethod("OneSignal#getDeviceState");
218218

219+
if ((json.cast<String, dynamic>()).isEmpty)
220+
return null;
221+
219222
return OSDeviceState(json.cast<String, dynamic>());
220223
}
221224

@@ -232,14 +235,14 @@ class OneSignal {
232235
Future<Map<String, dynamic>> postNotificationWithJson(
233236
Map<String, dynamic> json) async {
234237
Map<dynamic, dynamic> response =
235-
await _channel.invokeMethod("OneSignal#postNotification", json);
238+
await (_channel.invokeMethod("OneSignal#postNotification", json));
236239
return response.cast<String, dynamic>();
237240
}
238241

239242
Future<Map<String, dynamic>> postNotification(
240243
OSCreateNotification notification) async {
241-
Map<dynamic, dynamic> response = await _channel.invokeMethod(
242-
"OneSignal#postNotification", notification.mapRepresentation());
244+
Map<dynamic, dynamic> response = await (_channel.invokeMethod(
245+
"OneSignal#postNotification", notification.mapRepresentation()));
243246
return response.cast<String, dynamic>();
244247
}
245248

@@ -270,7 +273,7 @@ class OneSignal {
270273
/// Identity Verification. The email auth hash is a hash of your app's API key and the
271274
/// user ID. We recommend you generate this token from your backend server, do NOT
272275
/// store your API key in your app as this is highly insecure.
273-
Future<void> setEmail({String email, String emailAuthHashToken}) async {
276+
Future<void> setEmail({required String email, String? emailAuthHashToken}) async {
274277
return await _channel.invokeMethod("OneSignal#setEmail",
275278
{'email': email, 'emailAuthHashToken': emailAuthHashToken});
276279
}
@@ -284,16 +287,16 @@ class OneSignal {
284287
/// OneSignal allows you to set a custom ID for your users. This makes it so that
285288
/// if your app has its own user ID's, you can use your own custom user ID's with
286289
/// our API instead of having to save their OneSignal user ID's.
287-
Future<Map<String, dynamic>> setExternalUserId(String externalId, [String authHashToken]) async {
290+
Future<Map<String, dynamic>> setExternalUserId(String externalId, [String? authHashToken]) async {
288291
Map<dynamic, dynamic> results =
289-
await _channel.invokeMethod("OneSignal#setExternalUserId", {'externalUserId' : externalId, 'authHashToken' : authHashToken});
292+
await (_channel.invokeMethod("OneSignal#setExternalUserId", {'externalUserId' : externalId, 'authHashToken' : authHashToken}));
290293
return results.cast<String, dynamic>();
291294
}
292295

293296
/// Removes the external user ID that was set for the current user.
294297
Future<Map<String, dynamic>> removeExternalUserId() async {
295298
Map<dynamic, dynamic> results =
296-
await _channel.invokeMethod("OneSignal#removeExternalUserId");
299+
await (_channel.invokeMethod("OneSignal#removeExternalUserId"));
297300
return results.cast<String, dynamic>();
298301
}
299302

@@ -322,7 +325,7 @@ class OneSignal {
322325
}
323326

324327
/// Get the trigger value associated with the key provided
325-
Future<Object> getTriggerValueForKey(String key) async {
328+
Future<Object?> getTriggerValueForKey(String key) async {
326329
return await _inAppMessagesChannel.invokeMethod("OneSignal#getTriggerValueForKey", key);
327330
}
328331

@@ -368,27 +371,27 @@ class OneSignal {
368371
Future<Null> _handleMethod(MethodCall call) async {
369372
if (call.method == 'OneSignal#handleOpenedNotification' &&
370373
this._onOpenedNotification != null) {
371-
this._onOpenedNotification(
374+
this._onOpenedNotification!(
372375
OSNotificationOpenedResult(call.arguments.cast<String, dynamic>()));
373376
} else if (call.method == 'OneSignal#subscriptionChanged' &&
374377
this._onSubscriptionChangedHandler != null) {
375-
this._onSubscriptionChangedHandler(
378+
this._onSubscriptionChangedHandler!(
376379
OSSubscriptionStateChanges(call.arguments.cast<String, dynamic>()));
377380
} else if (call.method == 'OneSignal#permissionChanged' &&
378381
this._onPermissionChangedHandler != null) {
379-
this._onPermissionChangedHandler(
382+
this._onPermissionChangedHandler!(
380383
OSPermissionStateChanges(call.arguments.cast<String, dynamic>()));
381384
} else if (call.method == 'OneSignal#emailSubscriptionChanged' &&
382385
this._onEmailSubscriptionChangedHandler != null) {
383-
this._onEmailSubscriptionChangedHandler(
386+
this._onEmailSubscriptionChangedHandler!(
384387
OSEmailSubscriptionStateChanges(call.arguments.cast<String, dynamic>()));
385388
} else if (call.method == 'OneSignal#handleClickedInAppMessage' &&
386389
this._onInAppMessageClickedHandler != null) {
387-
this._onInAppMessageClickedHandler(
390+
this._onInAppMessageClickedHandler!(
388391
OSInAppMessageAction(call.arguments.cast<String, dynamic>()));
389392
} else if (call.method == 'OneSignal#handleNotificationWillShowInForeground' &&
390393
this._onNotificationWillShowInForegroundHandler != null) {
391-
this._onNotificationWillShowInForegroundHandler(
394+
this._onNotificationWillShowInForegroundHandler!(
392395
OSNotificationReceivedEvent(call.arguments.cast<String, dynamic>()));
393396
}
394397
return null;

lib/src/create_notification.dart

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,90 +11,90 @@ class OSCreateNotification extends JSONStringRepresentable {
1111
List<String> playerIds;
1212

1313
/// The notification's content (excluding title)
14-
String content;
14+
String? content;
1515

1616
/// The language code (ie. "en" for English) for this notification
1717
/// defaults to "en" (English)
18-
String languageCode;
18+
String? languageCode;
1919

2020
/// The title/heading for the notification
21-
String heading;
21+
String? heading;
2222

2323
/// The subtitle for the notification (iOS 10+ only)
24-
String subtitle;
24+
String? subtitle;
2525

2626
/// Tells the app to launch in the background (iOS only)
27-
bool contentAvailable;
27+
bool? contentAvailable;
2828

2929
/// Tells the app to launch the Notification Service extension,
3030
/// which can mutate your notification (ie. download attachments)
31-
bool mutableContent;
31+
bool? mutableContent;
3232

3333
/// Additional data you wish to send with the notification
34-
Map<String, dynamic> additionalData;
34+
Map<String, dynamic>? additionalData;
3535

3636
/// The URL to open when the user taps the notification
37-
String url;
37+
String? url;
3838

3939
/// Media (images, videos, etc.) for iOS
4040
/// Maps a custom ID to a resource URL
4141
/// in the format {'id' : 'https://.....'}
42-
Map<String, String> iosAttachments;
42+
Map<String, String>? iosAttachments;
4343

4444
/// An image to use as the big picture (android only)
45-
String bigPicture;
45+
String? bigPicture;
4646

4747
/// A list of buttons to attach to the notification
48-
List<OSActionButton> buttons;
48+
List<OSActionButton>? buttons;
4949

5050
/// The category identifier for iOS (controls various aspects
5151
/// of the notification, for example, whether to launch a
5252
/// Notification Content Extension) (iOS only)
53-
String iosCategory;
53+
String? iosCategory;
5454

5555
/// The sound to play (iOS only)
56-
String iosSound;
56+
String? iosSound;
5757

5858
/// The sound to play (Android only)
59-
String androidSound;
59+
String? androidSound;
6060

6161
/// A small icon (Android only)
6262
/// Can be a drawable resource name or a URL
63-
String androidSmallIcon;
63+
String? androidSmallIcon;
6464

6565
/// A large icon (android only)
6666
/// Can be a drawable resource name or a URL
67-
String androidLargeIcon;
67+
String? androidLargeIcon;
6868

6969
/// The Android Oreo Notification Category to send the notification under
70-
String androidChannelId;
70+
String? androidChannelId;
7171

7272
/// can be 'Increase' or 'SetTo'
73-
OSCreateNotificationBadgeType iosBadgeType;
73+
OSCreateNotificationBadgeType? iosBadgeType;
7474

7575
/// The actual badge count to either set to directly, or increment by
7676
/// To decrement the user's badge count, send a negative value
77-
int iosBadgeCount;
77+
int? iosBadgeCount;
7878

7979
/// If multiple notifications have the same collapse ID, only the most
8080
/// recent notification will be shown
81-
String collapseId;
81+
String? collapseId;
8282

8383
/// Allows you to send a notification at a specific date
84-
DateTime sendAfter;
84+
DateTime? sendAfter;
8585

8686
/// You can use several options to send notifications at specific times
8787
/// ie. you can send notifications to different user's at the same time
8888
/// in each timezone with the 'timezone' delayedOption
89-
OSCreateNotificationDelayOption delayedOption;
89+
OSCreateNotificationDelayOption? delayedOption;
9090

9191
/// Used with delayedOption == timezone, lets you specify what time of day
9292
/// each user should receive the notification, ie. "9:00 AM"
93-
String deliveryTimeOfDay;
93+
String? deliveryTimeOfDay;
9494

9595
OSCreateNotification(
96-
{@required this.playerIds,
97-
@required this.content,
96+
{required this.playerIds,
97+
required this.content,
9898
this.languageCode,
9999
this.heading,
100100
this.subtitle,
@@ -119,7 +119,7 @@ class OSCreateNotification extends JSONStringRepresentable {
119119
this.deliveryTimeOfDay});
120120

121121
OSCreateNotification.silentNotification(
122-
{@required this.playerIds,
122+
{required this.playerIds,
123123
this.additionalData,
124124
this.sendAfter,
125125
this.delayedOption,
@@ -164,16 +164,16 @@ class OSCreateNotification extends JSONStringRepresentable {
164164

165165
// adds optional parameters that require transformations
166166
if (this.sendAfter != null)
167-
json['send_after'] = dateToStringWithOffset(this.sendAfter);
167+
json['send_after'] = dateToStringWithOffset(this.sendAfter!);
168168
if (this.iosBadgeType != null)
169169
json['ios_badgeType'] = convertEnumCaseToValue(this.iosBadgeType);
170170
if (this.delayedOption != null)
171171
json['delayed_option'] = convertEnumCaseToValue(this.delayedOption);
172172

173173
// adds buttons
174174
if (this.buttons != null) {
175-
var btns = List<Map<String, dynamic>>();
176-
this.buttons.forEach((btn) => btns.add(btn.mapRepresentation()));
175+
var btns = [];
176+
this.buttons!.forEach((btn) => btns.add(btn.mapRepresentation()));
177177
json['buttons'] = btns;
178178
}
179179

0 commit comments

Comments
 (0)