1 00:00:04,840 --> 00:00:10,380 Okay, let's continue where we left off in the last video. 2 00:00:10,380 --> 00:00:17,580 The next step is to remove the about_weblink widget from our about layout, and include 3 00:00:17,580 --> 00:00:23,480 the about_web_url layout at the position it was at. 4 00:00:23,480 --> 00:00:30,620 Open about in the designer 5 00:00:30,620 --> 00:00:36,500 and delete the textView about_weblink. 6 00:00:38,269 --> 00:00:44,449 Next, drag an include widget from the containers section, 7 00:00:46,760 --> 00:00:53,940 and place it between about_copyright and about_email. 8 00:00:53,940 --> 00:00:58,520 It's easier to place it on the component tree, rather than trying to position it in the 9 00:00:58,520 --> 00:01:11,620 design window. When the resources dialogue appears, choose about_web_url. 10 00:01:11,620 --> 00:01:18,420 The layout_width should be set to match_parent and the layout_height to wrap_content. 11 00:01:18,420 --> 00:01:23,530 Our layout's looking pretty good in the designer now, but our included layout 12 00:01:23,530 --> 00:01:29,920 won't have a top margin. The "Instructions available at" text appears too close to 13 00:01:29,920 --> 00:01:35,290 the copyright message. We can fix that by setting the top margin on the include 14 00:01:35,290 --> 00:01:38,940 widget to 8dp. 15 00:01:48,530 --> 00:01:54,980 We're good to go, so I'll run the app on my API 28 emulator, and the API 17 16 00:01:54,980 --> 00:01:58,390 emulator as well. 17 00:02:18,209 --> 00:02:23,129 You may struggle to have two emulators running at the same time, in which case, 18 00:02:23,129 --> 00:02:26,790 run the one after the other, but that looks pretty good. 19 00:02:26,790 --> 00:02:33,469 The about dialogue for both versions look as similar as we can expect. 20 00:02:42,569 --> 00:02:49,680 The URL for the API 17 device still isn't clickable. The final thing to fix 21 00:02:49,680 --> 00:02:55,730 that, is to add an onClickListener to the TextView. 22 00:03:26,510 --> 00:03:31,700 It's just a standard onClickListener, only we've attached it to a TextView 23 00:03:31,700 --> 00:03:37,970 instead of a button. When the TextView's tapped we create a new intent, and use 24 00:03:37,970 --> 00:03:44,480 Intent.ACTION_VIEW as the action. Control click on ACTION_VIEW, 25 00:03:44,480 --> 00:03:51,260 or command click on a Mac, 26 00:03:51,260 --> 00:03:53,720 to view the source, and this is the 27 00:03:53,720 --> 00:03:58,579 most common action performed when calling an intent with data. The comment 28 00:03:58,579 --> 00:04:03,680 in the code describes the behavior with different types of data, such as opening 29 00:04:03,680 --> 00:04:08,840 the email program with the To address filled in, or dialing a phone number. 30 00:04:08,840 --> 00:04:13,340 Back to our code. 31 00:04:13,340 --> 00:04:17,740 Next, we get the text from the TextView converted to a string, 32 00:04:17,740 --> 00:04:24,960 and add it to the intent's data as a URI. In the API 21 and above layout, 33 00:04:24,960 --> 00:04:32,280 the about_url TextView won't be found, so the onClickListener won't be set. 34 00:04:32,280 --> 00:04:38,599 We get the URI by calling the uri.parse function, and you'll have found almost 35 00:04:38,600 --> 00:04:44,860 identical code to this, when searching for how to launch the browser using a URL. 36 00:04:44,860 --> 00:04:56,000 Okay, it won't quite work because we haven't started the URL with either http:// or https:// 37 00:04:56,000 --> 00:04:58,120 but we'll run it like this, so we 38 00:04:58,130 --> 00:05:04,010 can see which exception we need to catch. Open the about dialogue on the API 17 39 00:05:04,010 --> 00:05:08,410 device and tap the URL. 40 00:05:20,860 --> 00:05:27,800 The app crashes as expected, because there's no scheme in our URI. 41 00:05:38,580 --> 00:05:43,840 Crashing to find out that we get an activity not found exception, was a lot 42 00:05:43,840 --> 00:05:50,910 quicker than reading the documentation. We'll trap that exception in our code. 43 00:06:02,689 --> 00:06:09,129 and we'll test that it doesn't crash before modifying the string resource. 44 00:06:21,640 --> 00:06:26,940 Now, we get a toast message instead of a crash, which is much better. 45 00:06:26,940 --> 00:06:32,620 We're about to go into the strings resource file and this message should really be coming 46 00:06:32,620 --> 00:06:37,599 from a string resource. At the moment, Android Studio isn't giving a warning 47 00:06:37,599 --> 00:06:42,699 about that, but that may change in the future. It's a good idea to put all 48 00:06:42,699 --> 00:06:48,610 messages that the user can see, into a string resource. I'll cut that text into 49 00:06:48,610 --> 00:07:12,900 my clipboard without the speech marks, and replace it with the string resource ID. 50 00:07:12,900 --> 00:07:18,300 Okay, the final change to complete the challenge, is to change our string 51 00:07:18,300 --> 00:07:23,699 resource to include the URL scheme. I'll also create the error resource while 52 00:07:23,699 --> 00:07:26,120 we're there. 53 00:07:47,719 --> 00:07:53,589 I'll also put speech marks around the URL. 54 00:07:56,169 --> 00:08:01,879 Try it without the speech marks to see why they're necessary. Pay careful 55 00:08:01,879 --> 00:08:06,979 attention to the display in the dialogue, and also watch where the browser tries 56 00:08:06,979 --> 00:08:12,529 to go when you click the link. I won't do that in the video, just get into the 57 00:08:12,529 --> 00:08:18,229 habit of enclosing URL string resources in speech marks. Okay. 58 00:08:18,229 --> 00:08:22,809 Run the app and now it works fine. 59 00:08:32,070 --> 00:08:38,250 We can visit the webpage on our API 17 device. You may still get the warning 60 00:08:38,250 --> 00:08:44,800 that a secure connection could not be established, but you can just click OK on that. 61 00:08:44,800 --> 00:08:49,560 On a real device that's receiving updates, that message shouldn't appear. 62 00:08:49,560 --> 00:08:54,959 Alright, check that the link still works in the API 28 emulator, to make 63 00:08:54,959 --> 00:08:58,970 sure that our changes haven't broken anything. 64 00:09:17,170 --> 00:09:22,089 We can tell the different layouts are being used, because the API 28 device 65 00:09:22,089 --> 00:09:29,559 doesn't have https: before the URL. AutoLink takes care of inserting the 66 00:09:29,560 --> 00:09:36,000 schema for things it recognizes as web addresses, so we didn't have to specify it. 67 00:09:36,000 --> 00:09:40,700 If you decided to use the same layout for for all versions, then that's fine. 68 00:09:40,700 --> 00:09:48,060 You can include https:// in an autoLink TextView and it'll work. 69 00:09:48,060 --> 00:09:53,220 And, that's our challenge completed, so congratulations if you got it working. 70 00:09:53,220 --> 00:09:58,119 As we've seen, there can be a certain amount of work involved in supporting earlier 71 00:09:58,119 --> 00:10:02,559 versions of Android, and giving our apps the same features on these earlier 72 00:10:02,559 --> 00:10:08,319 versions. The code in this solution takes advantage of the native capabilities of 73 00:10:08,319 --> 00:10:13,929 API 21 devices and above, and only uses the onClickListener 74 00:10:13,929 --> 00:10:20,679 on devices before API 21. The clever and helpful thing about different 75 00:10:20,679 --> 00:10:24,910 versions of resource files, is that we don't have to include a load of tests 76 00:10:24,910 --> 00:10:30,129 for API versions. Android will automatically use the correct variant, 77 00:10:30,129 --> 00:10:35,889 depending on the device our app's running on. So just like it knows when to use the 78 00:10:35,889 --> 00:10:40,419 landscape and portrait variants of layouts, it also knows when it should use 79 00:10:40,420 --> 00:10:48,160 our API 21 version of the about_web _url layout. 80 00:10:48,160 --> 00:10:52,700 I'll finish by addressing a question that you may be wondering about. 81 00:10:52,700 --> 00:10:59,259 Why didn't I create a v21 version of strings.xml, and put the about_weblink 82 00:10:59,260 --> 00:11:06,840 string resource in there, instead of creating about_weblink_21. 83 00:11:06,840 --> 00:11:10,860 You will sometimes want to do that, but before you do, 84 00:11:10,860 --> 00:11:16,620 it's worth watching this video from Google I/O 2016. 85 00:11:16,620 --> 00:11:20,200 The video's at the URL that you can read in the address bar. 86 00:11:20,200 --> 00:11:24,520 It's worth watching the whole talk, but the bit that's relevant here, 87 00:11:24,520 --> 00:11:30,200 is at about 32 minutes and 40 seconds into the video. 88 00:11:46,040 --> 00:11:50,460 Wojtek Kalicinski, one of Google's engineers, explains about the 89 00:11:50,470 --> 00:11:55,360 impact this can have on the size of your app. As we're creating a separate 90 00:11:55,360 --> 00:12:00,250 layout, there's no advantage to keeping the string resource ID the same, and if 91 00:12:00,250 --> 00:12:04,779 you watch that video, you'll see that there are potentially big disadvantages 92 00:12:04,779 --> 00:12:10,029 in terms of the size of your app. So that's why I didn't create a v21 string 93 00:12:10,029 --> 00:12:15,820 resource file, just for a single string resource. Even with a handful, I still 94 00:12:15,820 --> 00:12:21,040 wouldn't put them in their own resource file. Okay, in the next section, we'll 95 00:12:21,040 --> 00:12:26,580 create a settings dialog for our app. I'll see you then.