1import React from 'react'; 2import { Alert, Platform, ScrollView } from 'react-native'; 3import { Notifications } from 'expo'; 4import * as Permissions from 'expo-permissions'; 5import HeadingText from '../components/HeadingText'; 6import ListButton from '../components/ListButton'; 7 8import registerForPushNotificationsAsync from '../api/registerForPushNotificationsAsync'; 9 10export default class NotificationScreen extends React.Component { 11 static navigationOptions = { 12 title: 'Notifications', 13 }; 14 15 render() { 16 return ( 17 <ScrollView style={{ padding: 10 }}> 18 <HeadingText>Local Notifications</HeadingText> 19 <ListButton 20 onPress={this._presentLocalNotificationAsync} 21 title="Present a notification immediately" 22 /> 23 <ListButton 24 onPress={this._scheduleLocalNotificationAsync} 25 title="Schedule notification for 10 seconds from now" 26 /> 27 <ListButton 28 onPress={this._scheduleLocalNotificationAndCancelAsync} 29 title="Schedule notification for 10 seconds from now and then cancel it immediately" 30 /> 31 <ListButton 32 onPress={Notifications.cancelAllScheduledNotificationsAsync} 33 title="Cancel all scheduled notifications" 34 /> 35 <ListButton 36 onPress={this._scheduleLegacyNotificationAsync} 37 title="Schedule a notification with both `time` and `repeat` (deprecated on iOS)" 38 /> 39 <ListButton 40 onPress={this._scheduleAndCancelLegacyNotificationAsync} 41 title="Schedule and immediately cancel notification with both `time` and `repeat` (deprecated on iOS)" 42 /> 43 44 <HeadingText>Push Notifications</HeadingText> 45 <ListButton 46 onPress={() => this._sendNotificationAsync('simple')} 47 title="Send me a push notification" 48 /> 49 <ListButton 50 onPress={() => this._sendNotificationAsync('image')} 51 title="Send me a push notification with an image" 52 /> 53 <ListButton 54 onPress={() => this._sendNotificationAsync('audio')} 55 title="Send me a push notification with an audio" 56 /> 57 <ListButton 58 onPress={() => this._sendNotificationAsync('gif')} 59 title="Send me a push notification with an animated image" 60 /> 61 <ListButton 62 onPress={() => this._sendNotificationAsync('video')} 63 title="Send me a push notification with a video" 64 /> 65 <ListButton 66 onPress={() => this._sendNotificationAsync('imageWithCustomIcon')} 67 title="Send me a push notification with a image and a custom icon" 68 /> 69 70 <HeadingText>Custom notification categories</HeadingText> 71 <ListButton 72 onPress={this._createCategoryAsync} 73 title="Create a custom 'message' category" 74 /> 75 <ListButton 76 onPress={this._scheduleLocalNotificationWithCategoryAsync} 77 title="Schedule notification for 10 seconds from now with a 'message' category" 78 /> 79 <ListButton 80 onPress={this._deleteCategoryAsync} 81 title="Delete the custom 'message' category" 82 /> 83 84 <HeadingText>Badge Number</HeadingText> 85 <ListButton 86 onPress={this._incrementIconBadgeNumberAsync} 87 title="Increment the app icon's badge number" 88 /> 89 <ListButton 90 onPress={this._clearIconBadgeAsync} 91 title="Clear the app icon's badge number" 92 /> 93 </ScrollView> 94 ); 95 } 96 97 _obtainUserFacingNotifPermissionsAsync = async () => { 98 let permission = await Permissions.getAsync( 99 Permissions.USER_FACING_NOTIFICATIONS 100 ); 101 if (permission.status !== 'granted') { 102 permission = await Permissions.askAsync( 103 Permissions.USER_FACING_NOTIFICATIONS 104 ); 105 if (permission.status !== 'granted') { 106 Alert.alert(`We don't have permission to present notifications.`); 107 } 108 } 109 return permission; 110 } 111 112 _obtainRemoteNotifPermissionsAsync = async () => { 113 let permission = await Permissions.getAsync(Permissions.NOTIFICATIONS); 114 if (permission.status !== 'granted') { 115 permission = await Permissions.askAsync(Permissions.NOTIFICATIONS); 116 if (permission.status !== 'granted') { 117 Alert.alert( 118 `We don't have permission to receive remote notifications.` 119 ); 120 } 121 } 122 return permission; 123 } 124 125 _presentLocalNotificationAsync = async () => { 126 await this._obtainUserFacingNotifPermissionsAsync(); 127 Notifications.presentLocalNotificationAsync({ 128 title: 'Here is a local notification!', 129 body: 'This is the body', 130 data: { 131 hello: 'there', 132 }, 133 ios: { 134 sound: true, 135 }, 136 }); 137 } 138 139 _scheduleLocalNotificationAsync = async () => { 140 await this._obtainUserFacingNotifPermissionsAsync(); 141 Notifications.scheduleLocalNotificationAsync( 142 { 143 title: 'Here is a scheduled notifiation!', 144 body: 'This is the body', 145 data: { 146 hello: 'there', 147 future: 'self', 148 }, 149 ios: { 150 sound: true, 151 }, 152 }, 153 { 154 time: new Date().getTime() + 10000, 155 } 156 ); 157 } 158 159 _createCategoryAsync = () => 160 Notifications.createCategoryAsync('message', [ 161 { 162 actionId: 'dismiss', 163 buttonTitle: 'Dismiss notification', 164 isDestructive: true, 165 isAuthenticationRequired: false, 166 }, 167 { 168 actionId: 'respond', 169 buttonTitle: 'Respond', 170 isDestructive: false, 171 isAuthenticationRequired: true, 172 textInput: { 173 submitButtonTitle: 'Send', 174 placeholder: 'Response', 175 }, 176 }, 177 ]) 178 179 _deleteCategoryAsync = () => Notifications.deleteCategoryAsync('message'); 180 181 _scheduleLocalNotificationWithCategoryAsync = async () => { 182 await this._obtainUserFacingNotifPermissionsAsync(); 183 184 await Notifications.scheduleLocalNotificationAsync( 185 { 186 title: 'Expo sent you a message!', 187 body: 'Howdy, fella!', 188 ios: { 189 sound: true, 190 }, 191 categoryId: 'message', 192 }, 193 { 194 time: new Date().getTime() + 10000, 195 } 196 ); 197 } 198 199 _scheduleLocalNotificationAndCancelAsync = async () => { 200 await this._obtainUserFacingNotifPermissionsAsync(); 201 const notificationId = await Notifications.scheduleLocalNotificationAsync( 202 { 203 title: 'This notification should not appear', 204 body: 'It should have been cancelled. :(', 205 ios: { 206 sound: true, 207 }, 208 }, 209 { 210 time: new Date().getTime() + 10000, 211 } 212 ); 213 await Notifications.cancelScheduledNotificationAsync(notificationId); 214 } 215 216 _scheduleLegacyNotificationAsync = async () => { 217 await this._obtainUserFacingNotifPermissionsAsync(); 218 return Notifications.scheduleLocalNotificationAsync( 219 { 220 title: 'Repeating notification', 221 body: `I repeat every minute starting from ${new Date().toLocaleTimeString()}`, 222 data: { 223 repeatingEvery: 'minute', 224 scheduledAt: new Date().toLocaleTimeString(), 225 }, 226 ios: { 227 sound: true, 228 }, 229 }, 230 { 231 time: new Date().getTime() + 2000, 232 repeat: 'minute', 233 } 234 ); 235 } 236 237 _scheduleAndCancelLegacyNotificationAsync = async () => { 238 const notificationId = await this._scheduleLegacyNotificationAsync(); 239 await Notifications.cancelScheduledNotificationAsync(notificationId); 240 } 241 242 _incrementIconBadgeNumberAsync = async () => { 243 const currentNumber = await Notifications.getBadgeNumberAsync(); 244 await Notifications.setBadgeNumberAsync(currentNumber + 1); 245 const actualNumber = await Notifications.getBadgeNumberAsync(); 246 Alert.alert(`Set the badge number to ${actualNumber}`); 247 } 248 249 _clearIconBadgeAsync = async () => { 250 await Notifications.setBadgeNumberAsync(0); 251 Alert.alert(`Cleared the badge`); 252 } 253 254 _sendNotificationAsync = async (type: string) => { 255 if (type !== 'simple' && type !== 'image' && Platform.OS !== 'ios') { 256 alert( 257 'While you will still receive the notification, you will not see any rich content since rich content other than images are only supported on iOS.' 258 ); 259 } 260 if (type === 'imageWithCustomIcon' && Platform.OS === 'ios') { 261 alert( 262 'While you will still receive the notification, you will not see any custom icon since custom icons are not supported on iOS.' 263 ); 264 } 265 const permission = await this._obtainRemoteNotifPermissionsAsync(); 266 if (permission.status === 'granted') { 267 registerForPushNotificationsAsync(type); 268 } 269 } 270} 271