1
00:00:04,800 --> 00:00:07,300
Welcome back. In this video,

2
00:00:07,300 --> 00:00:10,600
we're going to observe the changes to the device configuration

3
00:00:10,900 --> 00:00:14,800
to allow our app to respond when the locale changes.

4
00:00:15,460 --> 00:00:17,260
When something like this happens,

5
00:00:17,260 --> 00:00:21,160
the system will broadcast a message to any broadcast receivers

6
00:00:21,160 --> 00:00:23,160
that have registered to be notified.

7
00:00:23,960 --> 00:00:25,960
Setting up a BroadcastReceiver

8
00:00:26,260 --> 00:00:29,260
follows the same pattern as setting up a ContentObserver.

9
00:00:30,250 --> 00:00:34,650
We have to create an object that will respond to the messages then register it.

10
00:00:35,310 --> 00:00:37,910
When we no longer need it, we unregister it.

11
00:00:39,110 --> 00:00:43,310
One difference is how we specify which broadcasts we're interested in.

12
00:00:44,190 --> 00:00:46,290
When using a ContentObserver,

13
00:00:46,290 --> 00:00:48,790
we tell it which URI to observe.

14
00:00:49,190 --> 00:00:53,390
With a BroadcastReceiver, we use an IntentFilter instead.

15
00:00:53,690 --> 00:00:54,990
Let's see some code.

16
00:00:57,490 --> 00:01:00,790
I'll start by creating a BroadcastReceiver object

17
00:01:00,790 --> 00:01:02,690
in our DurationsViewModel.

18
00:01:43,350 --> 00:01:47,850
We've got an error because we need to implement the OnReceive function.

19
00:01:48,950 --> 00:01:52,950
I'll use control I to get android studio to generate the stub.

20
00:01:56,550 --> 00:01:59,320
The OnReceive function is an abstract function

21
00:01:59,320 --> 00:02:01,120
in the BroadcastReceiver class,

22
00:02:01,120 --> 00:02:02,420
which is also abstract.

23
00:02:03,120 --> 00:02:06,420
That means we have to provide the implementation ourselves.

24
00:02:07,280 --> 00:02:11,280
An abstract class is similar to an interface in many ways.

25
00:02:11,780 --> 00:02:13,580
There are some important differences.

26
00:02:13,880 --> 00:02:16,680
And if you don't already know about abstract classes,

27
00:02:16,680 --> 00:02:20,580
it's worth Googling for something like "JavaAbstract class

28
00:02:20,580 --> 00:02:23,180
versus interface" to learn more about them.

29
00:02:23,980 --> 00:02:27,280
An abstract class can provide some implementation itself,

30
00:02:27,640 --> 00:02:29,140
which an interface couldn't

31
00:02:29,440 --> 00:02:32,040
but that distinction has faded a bit recently

32
00:02:32,700 --> 00:02:36,000
because interfaces can now provide some implementation

33
00:02:36,300 --> 00:02:37,900
in later java versions.

34
00:02:38,200 --> 00:02:40,400
All right. What do we want to do

35
00:02:40,400 --> 00:02:43,900
when we receive a notification that the locale has changed.

36
00:02:44,800 --> 00:02:46,700
We've already discussed that in fact.

37
00:02:47,100 --> 00:02:50,400
We need to create a new Gregorian calendar instance,

38
00:02:50,760 --> 00:02:54,360
so that the calendar is using the settings for the new locale.

39
00:02:55,020 --> 00:02:57,520
The user may have changed the calendar's date

40
00:02:57,920 --> 00:03:00,520
and will probably expect to still see that date.

41
00:03:01,070 --> 00:03:05,060
That means we should store the date then set a new calendar instance

42
00:03:05,060 --> 00:03:05,960
to use it.

43
00:03:25,260 --> 00:03:28,260
There's no way to change the locale of a calendar instance,

44
00:03:28,510 --> 00:03:30,210
which is why we create a new one.

45
00:03:30,810 --> 00:03:34,210
That means we have to declare our calendar as var

46
00:03:34,210 --> 00:03:35,710
rather than val.

47
00:03:40,710 --> 00:03:41,910
That's fixed the error.

48
00:03:42,570 --> 00:03:47,170
After creating a new calendar instance, we call the ApplyFilter function,

49
00:03:47,770 --> 00:03:51,540
that re-queries the database and make sure the report reflects

50
00:03:51,540 --> 00:03:53,040
what the user expects.

51
00:03:53,840 --> 00:03:55,340
There's something else we should do,

52
00:03:55,840 --> 00:03:59,830
and that's described in the docs string for the BroadcastReceivers

53
00:03:59,830 --> 00:04:01,330
OnReceive method.

54
00:04:01,730 --> 00:04:05,730
Control click on BroadcastReceiver on line 44

55
00:04:06,230 --> 00:04:07,630
to see the source code,

56
00:04:13,130 --> 00:04:15,330
that takes us to the class constructor

57
00:04:15,930 --> 00:04:19,529
and the docs string below that relates to the OnReceive method.

58
00:04:22,530 --> 00:04:26,090
This is java code remember which is why I'm saying method

59
00:04:26,090 --> 00:04:27,190
instead of function.

60
00:04:27,990 --> 00:04:29,990
It's worth reading the docs strings

61
00:04:29,990 --> 00:04:32,290
or the google documentation if you prefer

62
00:04:32,790 --> 00:04:35,790
for any classes and methods that you use in your apps.

63
00:04:36,290 --> 00:04:40,590
You'll often find unexpected details that can save you getting into difficulties.

64
00:04:42,890 --> 00:04:45,090
I'm interested in the last paragraph here,

65
00:04:45,090 --> 00:04:47,290
just above the parameter descriptions.

66
00:04:47,650 --> 00:04:49,250
But I'm not going to read it just yet.

67
00:04:49,650 --> 00:04:53,900
It'll make a bit more sense once we've finished setting up the BroadcastReceiver.

68
00:04:54,400 --> 00:04:59,000
Back in our DurationsViewModel class, we need to register the receiver,

69
00:05:00,800 --> 00:05:03,400
that involves creating an IntentFilter

70
00:05:03,400 --> 00:05:05,400
for the messages we want to receive.

71
00:05:06,200 --> 00:05:08,500
I'll add the code in the init block.

72
00:05:24,800 --> 00:05:28,900
The IntentFilter tells android which broadcast messages

73
00:05:28,900 --> 00:05:30,000
we want to receive.

74
00:05:30,600 --> 00:05:33,400
Here, we're going to create a new calendar instance

75
00:05:33,400 --> 00:05:35,900
if the user changes the locale

76
00:05:35,900 --> 00:05:39,260
because that changes things like which day the week starts on.

77
00:05:40,060 --> 00:05:43,560
We also create a new calendar if they change time zones

78
00:05:44,000 --> 00:05:47,300
that's obviously something our calendar needs to know about.

79
00:05:48,600 --> 00:05:51,600
You can add as many IntentFilters as you need

80
00:05:51,960 --> 00:05:54,560
by calling the AddAction method

81
00:05:54,810 --> 00:05:56,810
and providing the action you're interested in.

82
00:05:57,810 --> 00:06:00,110
We finish by registering our server

83
00:06:00,360 --> 00:06:04,560
by calling the RegisterReceiver method of the application object.

84
00:06:05,760 --> 00:06:08,120
In the documentation that you google for,

85
00:06:08,120 --> 00:06:11,720
you'll find a discussion about the context of your receiver.

86
00:06:12,520 --> 00:06:14,920
If we were doing this in an activity,

87
00:06:14,920 --> 00:06:18,420
we'd call the activities RegisterReceiver method

88
00:06:19,220 --> 00:06:22,420
that would allow the activity to receive the broadcasts

89
00:06:22,420 --> 00:06:24,320
until the activity gets destroyed.

90
00:06:25,620 --> 00:06:28,720
We're using the application to register our receiver,

91
00:06:28,720 --> 00:06:32,120
which means it will remain registered as long as the app is running.

92
00:06:33,420 --> 00:06:36,520
Of course, we're going to do things properly

93
00:06:36,520 --> 00:06:40,520
and unregister the receiver when our ViewModel gets destroyed.

94
00:06:40,880 --> 00:06:43,380
We do that in the uncleared function.

95
00:07:06,880 --> 00:07:11,280
Before we test it, let's have another look at the code in our init block.

96
00:07:13,680 --> 00:07:17,280
We've created an intent filter that specifies

97
00:07:17,830 --> 00:07:20,530
action time zone changed and

98
00:07:20,830 --> 00:07:22,430
action locale changed.

99
00:07:23,230 --> 00:07:27,630
That means we should only receive messages when those events are broadcast.

100
00:07:28,180 --> 00:07:31,480
I'm going to add some more code to the OnReceive function,

101
00:07:31,480 --> 00:07:32,980
then we'll have a look why.

102
00:08:03,780 --> 00:08:05,780
Okay. Why have I done that.

103
00:08:06,280 --> 00:08:10,080
If we're only going to get called when one of those actions is broadcast,

104
00:08:10,480 --> 00:08:11,680
why bother checking?

105
00:08:12,930 --> 00:08:16,530
The reason's described in the last paragraph of that doc string.

106
00:08:17,190 --> 00:08:18,690
Let's have another look at it.

107
00:08:19,190 --> 00:08:23,390
Ctrl click on BroadcastReceiver to go back to the source for the class.

108
00:08:24,290 --> 00:08:28,790
It says that the Intent filters are not guaranteed to be exclusive,

109
00:08:29,490 --> 00:08:33,789
they're hints to the android framework but we may get other messages,

110
00:08:34,289 --> 00:08:38,490
that's why we should check that the actions are only the ones that we are interested in.

111
00:08:39,150 --> 00:08:41,350
Now in this particular app,

112
00:08:41,549 --> 00:08:44,250
it's not crucial if we create a new calendar

113
00:08:44,250 --> 00:08:45,850
when some other event occurs,

114
00:08:46,510 --> 00:08:49,510
it's inefficient but it won't cause serious problems.

115
00:08:50,310 --> 00:08:53,010
But there may be situations where it is important.

116
00:08:53,410 --> 00:08:56,310
So make sure you always check the intent action

117
00:08:56,310 --> 00:08:58,310
that causes your receiver to be called.

118
00:08:59,190 --> 00:09:01,090
All right. That code's finished.

119
00:09:01,690 --> 00:09:06,090
In the next video, we'll test the app to make sure that we've fixed the bug.

120
00:09:06,490 --> 00:09:07,390
See you there.

