1 00:00:02,250 --> 00:00:04,370 So in order to also get 2 00:00:04,370 --> 00:00:06,490 local notifications on iOS, 3 00:00:06,490 --> 00:00:09,820 we need to ask the user for permission. 4 00:00:09,820 --> 00:00:12,100 And for this, we an use another package 5 00:00:12,100 --> 00:00:14,860 which we also install with expo install, 6 00:00:14,860 --> 00:00:17,920 and that's the expo-permissions package. 7 00:00:17,920 --> 00:00:21,200 The expo-permissions package, as the name implies, 8 00:00:21,200 --> 00:00:23,500 helps us manage permissions. 9 00:00:23,500 --> 00:00:27,640 It helps us request permissions, and work with permissions. 10 00:00:27,640 --> 00:00:29,430 So once this is installed, 11 00:00:29,430 --> 00:00:32,870 in App.js or in any other file 12 00:00:32,870 --> 00:00:35,550 where you want to get those permissions, 13 00:00:35,550 --> 00:00:38,360 but here we only have this one component, 14 00:00:38,360 --> 00:00:41,440 we simply import everything as permissions 15 00:00:41,440 --> 00:00:45,290 from expo-permissions, just like that. 16 00:00:45,290 --> 00:00:49,630 And with imported, we need to ask the user for permission 17 00:00:49,630 --> 00:00:53,370 to show notifications before we try doing that. 18 00:00:53,370 --> 00:00:55,980 Now, it depends on your application 19 00:00:55,980 --> 00:00:58,130 when you want to ask the user. 20 00:00:58,130 --> 00:01:00,700 Maybe you wanna ask when the app starts up, 21 00:01:00,700 --> 00:01:03,410 maybe a better point of time is better. 22 00:01:03,410 --> 00:01:05,620 After all, you wanna ask for permissions 23 00:01:05,620 --> 00:01:07,470 when it's very likely that the user 24 00:01:07,470 --> 00:01:09,820 gives you the permission, right? 25 00:01:09,820 --> 00:01:12,110 Now here we'll do it right when the app starts up, 26 00:01:12,110 --> 00:01:17,110 so I will actually import the useEffect hook from react 27 00:01:19,600 --> 00:01:24,600 so that we can run logic when this component mounts, 28 00:01:25,160 --> 00:01:28,460 simply by passing an empty dependencies array here. 29 00:01:28,460 --> 00:01:32,270 And in there I now wanna use this permissions object 30 00:01:32,270 --> 00:01:35,880 which we imported here, to first of all check 31 00:01:35,880 --> 00:01:37,650 the permission status. 32 00:01:37,650 --> 00:01:41,930 And thereafter, if we don't have permission, to ask for it. 33 00:01:41,930 --> 00:01:45,028 So therefore here, we can call getAsync 34 00:01:45,028 --> 00:01:48,340 to first of all check the current permission status. 35 00:01:48,340 --> 00:01:50,810 We now need to specify for which permission 36 00:01:50,810 --> 00:01:52,800 we wanna get that information, 37 00:01:52,800 --> 00:01:56,410 and we can therefore access Permissions.NOTIFICATIONS... 38 00:01:56,410 --> 00:01:58,560 Whoops, all caps, though. 39 00:01:58,560 --> 00:02:01,950 To check how the current permissions status is 40 00:02:01,950 --> 00:02:04,290 for notification permissions. 41 00:02:04,290 --> 00:02:05,930 On Android this will do nothing, 42 00:02:05,930 --> 00:02:09,250 on iOS it will find out whether we already are allowed 43 00:02:09,250 --> 00:02:11,250 to send permissions. 44 00:02:11,250 --> 00:02:12,770 Now, this is a async task, 45 00:02:12,770 --> 00:02:14,670 and therefore it gives us a promise. 46 00:02:14,670 --> 00:02:18,780 Hence, we can use then here to proceed. 47 00:02:18,780 --> 00:02:23,160 Now in here, we'll get the status of that permission. 48 00:02:23,160 --> 00:02:26,070 So we'll get the information whether we do have permission 49 00:02:26,070 --> 00:02:28,563 to send notifications or not. 50 00:02:30,360 --> 00:02:33,460 Now we can check which status we got. 51 00:02:33,460 --> 00:02:36,040 There are a couple of possible values here, 52 00:02:36,040 --> 00:02:40,120 but in the end we're interested in the granted status. 53 00:02:40,120 --> 00:02:45,083 If we got that granted status, we don't need to continue. 54 00:02:45,930 --> 00:02:49,430 But if we don't have the granted status yet, 55 00:02:49,430 --> 00:02:51,890 we wanna ask for permission, 56 00:02:51,890 --> 00:02:55,060 because we haven't been granted those permissions before. 57 00:02:55,060 --> 00:02:58,380 So now we can use the permissions object again, 58 00:02:58,380 --> 00:03:00,273 but this time we call askAsync. 59 00:03:02,110 --> 00:03:04,160 Before, we checked the status, 60 00:03:04,160 --> 00:03:06,810 now we're asking for a new permission 61 00:03:06,810 --> 00:03:09,700 because now we know that we don't yet have the permission 62 00:03:09,700 --> 00:03:11,070 which we need. 63 00:03:11,070 --> 00:03:15,110 So now here we again access Permissions.NOTIFICATIONS, 64 00:03:15,110 --> 00:03:18,560 and now this will ask for getting that permission. 65 00:03:18,560 --> 00:03:21,670 This will return a promise, so we can overall return it here 66 00:03:21,670 --> 00:03:24,873 to stay in this promise chain which we've started here. 67 00:03:26,060 --> 00:03:28,650 And therefore, now here, we can again use then. 68 00:03:28,650 --> 00:03:30,620 You could also use async await, 69 00:03:30,620 --> 00:03:34,220 but in useEffect you shouldn't make this function async, 70 00:03:34,220 --> 00:03:36,670 instead you would have to wrap this into a new function 71 00:03:36,670 --> 00:03:39,820 which you immediately execute, just as a side note. 72 00:03:39,820 --> 00:03:42,140 But here, I will use good old then catch, 73 00:03:42,140 --> 00:03:45,130 and we'll reach the function in this then block 74 00:03:45,130 --> 00:03:48,470 after askAsync finished. 75 00:03:48,470 --> 00:03:50,760 Now again, here we'll get the status. 76 00:03:50,760 --> 00:03:53,500 Because of course, just because we're asking 77 00:03:53,500 --> 00:03:56,130 does not mean that we're getting the permission. 78 00:03:56,130 --> 00:03:58,480 So the user might still deny the permission, 79 00:03:58,480 --> 00:04:00,870 and in this case there is nothing we can do. 80 00:04:00,870 --> 00:04:03,060 So now we wanna check this status 81 00:04:03,060 --> 00:04:05,900 and find out if it's still not granted. 82 00:04:05,900 --> 00:04:08,960 And if that is the case, then well, as I said, 83 00:04:08,960 --> 00:04:10,370 there's nothing we can do. 84 00:04:10,370 --> 00:04:12,020 So here we can just return. 85 00:04:12,020 --> 00:04:13,740 We might show a message to the user, 86 00:04:13,740 --> 00:04:18,740 we might an alert that we now can't send any notifications. 87 00:04:19,710 --> 00:04:22,350 But in the end, there is nothing we can do here. 88 00:04:22,350 --> 00:04:26,470 If the status is granted though, then we're good. 89 00:04:26,470 --> 00:04:30,440 Now either way, we can definitely schedule a notification, 90 00:04:30,440 --> 00:04:32,620 because the worst case scenario 91 00:04:32,620 --> 00:04:34,170 is that we don't have permissions 92 00:04:34,170 --> 00:04:36,030 and therefore nothing happens. 93 00:04:36,030 --> 00:04:38,960 But now that we're asking, the best case scenario 94 00:04:38,960 --> 00:04:40,800 is that we did get the permission 95 00:04:40,800 --> 00:04:43,513 and therefore this here will succeed. 96 00:04:45,080 --> 00:04:46,810 Now actually, I have to step in here. 97 00:04:46,810 --> 00:04:49,350 This code has an error. 98 00:04:49,350 --> 00:04:52,000 We don't get the status string like this here, 99 00:04:52,000 --> 00:04:54,540 instead we get the statusObj, 100 00:04:54,540 --> 00:04:57,450 which then has a status property. 101 00:04:57,450 --> 00:04:59,363 And the same is the case here. 102 00:05:00,680 --> 00:05:02,500 We just didn't get an error before, 103 00:05:02,500 --> 00:05:05,100 because even though our code technically didn't work, 104 00:05:05,100 --> 00:05:07,940 we did request their permission still. 105 00:05:07,940 --> 00:05:11,150 But now this properly checks whether we have the permission. 106 00:05:11,150 --> 00:05:14,930 And in addition, we also have to adjust it 107 00:05:14,930 --> 00:05:16,290 in one other place. 108 00:05:16,290 --> 00:05:19,650 Here, if we already did have the permission, 109 00:05:19,650 --> 00:05:23,360 we of course will get granted as a response here, hopefully. 110 00:05:23,360 --> 00:05:25,070 And we'll not ask again. 111 00:05:25,070 --> 00:05:26,930 That means that in the next then block, 112 00:05:26,930 --> 00:05:28,390 we have a problem though. 113 00:05:28,390 --> 00:05:33,110 Because there we now expect to get our statusObj, 114 00:05:33,110 --> 00:05:36,800 but since we didn't ask again because we didn't need to, 115 00:05:36,800 --> 00:05:39,070 we'll not get that object here. 116 00:05:39,070 --> 00:05:42,450 So, accessing status will fail and we'll think 117 00:05:42,450 --> 00:05:45,810 that we didn't get the permission, even though we have it. 118 00:05:45,810 --> 00:05:50,810 So here we should return statusObj in that first then block 119 00:05:51,950 --> 00:05:54,670 so that in the next then block it is available 120 00:05:54,670 --> 00:05:57,910 for the cases where we already had permission. 121 00:05:57,910 --> 00:05:59,620 This is a change you should implement 122 00:05:59,620 --> 00:06:03,510 to ensure that your application properly detects 123 00:06:03,510 --> 00:06:06,170 its notifications permission status 124 00:06:06,170 --> 00:06:08,860 and does not think it doesn't have permissions, 125 00:06:08,860 --> 00:06:10,890 when it actually has them. 126 00:06:10,890 --> 00:06:12,430 So let's now save this. 127 00:06:16,760 --> 00:06:20,950 And make sure to restart that on your iPhone simulator. 128 00:06:20,950 --> 00:06:22,480 And now, right at the start, 129 00:06:22,480 --> 00:06:25,070 I'm asked whether I wanna grant this permission, 130 00:06:25,070 --> 00:06:27,290 because of that code we just added. 131 00:06:27,290 --> 00:06:29,560 And if we now click allow here, 132 00:06:29,560 --> 00:06:32,910 and trigger the notification and close the application, 133 00:06:32,910 --> 00:06:36,800 let's see if that now works here on iOS. 134 00:06:36,800 --> 00:06:40,510 Let's wait for the 10 seconds to go by. 135 00:06:40,510 --> 00:06:45,510 And here's our first local notification sent by our app. 136 00:06:45,720 --> 00:06:49,370 And now we got that working on both iOS and Android. 137 00:06:49,370 --> 00:06:53,063 And just as on Android, if we click on a notification here, 138 00:06:54,300 --> 00:06:56,520 we can open our app. 139 00:06:56,520 --> 00:06:57,690 So that's working. 140 00:06:57,690 --> 00:07:02,590 Now, one thing that did not work or where nothing happened, 141 00:07:02,590 --> 00:07:05,560 was when the app is in the foreground. 142 00:07:05,560 --> 00:07:08,380 Now in some cases that is the behavior you want. 143 00:07:08,380 --> 00:07:10,420 In some cases, if the app is open, 144 00:07:10,420 --> 00:07:14,550 not showing the notification might be absolutely fine. 145 00:07:14,550 --> 00:07:17,670 But if I come back to the reminder app example, 146 00:07:17,670 --> 00:07:19,950 just because it's in the foreground 147 00:07:19,950 --> 00:07:23,500 might not mean that you don't want to let the user know 148 00:07:23,500 --> 00:07:26,070 that some task is due. 149 00:07:26,070 --> 00:07:28,300 So therefore, let me next show you 150 00:07:28,300 --> 00:07:30,720 how you can handle notifications 151 00:07:30,720 --> 00:07:32,763 if the app is in the foreground.