Okay, let's continue where we left off in the last video.
The next step is to remove the about_weblink widget from our about layout, and include
the about_web_url layout at the position it was at.
Open about in the designer
and delete the textView about_weblink.
Next, drag an include widget from the containers section,
and place it between about_copyright and about_email.
It's easier to place it on the component tree, rather than trying to position it in the
design window. When the resources dialogue appears, choose about_web_url.
The layout_width should be set to match_parent and the layout_height to wrap_content.
Our layout's looking pretty good in the designer now, but our included layout
won't have a top margin. The "Instructions available at" text appears too close to
the copyright message. We can fix that by setting the top margin on the include
widget to 8dp.
We're good to go, so I'll run the app on my API 28 emulator, and the API 17
emulator as well.
You may struggle to have two emulators running at the same time, in which case,
run the one after the other, but that looks pretty good.
The about dialogue for both versions look as similar as we can expect.
The URL for the API 17 device still isn't clickable. The final thing to fix
that, is to add an onClickListener to the TextView.
It's just a standard onClickListener, only we've attached it to a TextView
instead of a button. When the TextView's tapped we create a new intent, and use
Intent.ACTION_VIEW as the action. Control click on ACTION_VIEW,
or command click on a Mac,
to view the source, and this is the
most common action performed when calling an intent with data. The comment
in the code describes the behavior with different types of data, such as opening
the email program with the To address filled in, or dialing a phone number.
Back to our code.
Next, we get the text from the TextView converted to a string,
and add it to the intent's data as a URI. In the API 21 and above layout,
the about_url TextView won't be found, so the onClickListener won't be set.
We get the URI by calling the uri.parse function, and you'll have found almost
identical code to this, when searching for how to launch the browser using a URL.
Okay, it won't quite work because we haven't started the URL with either http:// or https://
but we'll run it like this, so we
can see which exception we need to catch. Open the about dialogue on the API 17
device and tap the URL.
The app crashes as expected, because there's no scheme in our URI.
Crashing to find out that we get an activity not found exception, was a lot
quicker than reading the documentation. We'll trap that exception in our code.
and we'll test that it doesn't crash before modifying the string resource.
Now, we get a toast message instead of a crash, which is much better.
We're about to go into the strings resource file and this message should really be coming
from a string resource. At the moment, Android Studio isn't giving a warning
about that, but that may change in the future. It's a good idea to put all
messages that the user can see, into a string resource. I'll cut that text into
my clipboard without the speech marks, and replace it with the string resource ID.
Okay, the final change to complete the challenge, is to change our string
resource to include the URL scheme. I'll also create the error resource while
we're there.
I'll also put speech marks around the URL.
Try it without the speech marks to see why they're necessary. Pay careful
attention to the display in the dialogue, and also watch where the browser tries
to go when you click the link. I won't do that in the video, just get into the
habit of enclosing URL string resources in speech marks. Okay.
Run the app and now it works fine.
We can visit the webpage on our API 17 device. You may still get the warning
that a secure connection could not be established, but you can just click OK on that.
On a real device that's receiving updates, that message shouldn't appear.
Alright, check that the link still works in the API 28 emulator, to make
sure that our changes haven't broken anything.
We can tell the different layouts are being used, because the API 28 device
doesn't have https: before the URL. AutoLink takes care of inserting the
schema for things it recognizes as web addresses, so we didn't have to specify it.
If you decided to use the same layout for for all versions, then that's fine.
You can include https:// in an autoLink TextView and it'll work.
And, that's our challenge completed, so congratulations if you got it working.
As we've seen, there can be a certain amount of work involved in supporting earlier
versions of Android, and giving our apps the same features on these earlier
versions. The code in this solution takes advantage of the native capabilities of
API 21 devices and above, and only uses the onClickListener
on devices before API 21. The clever and helpful thing about different
versions of resource files, is that we don't have to include a load of tests
for API versions. Android will automatically use the correct variant,
depending on the device our app's running on. So just like it knows when to use the
landscape and portrait variants of layouts, it also knows when it should use
our API 21 version of the about_web _url layout.
I'll finish by addressing a question that you may be wondering about.
Why didn't I create a v21 version of strings.xml, and put the about_weblink
string resource in there, instead of creating about_weblink_21.
You will sometimes want to do that, but before you do,
it's worth watching this video from Google I/O 2016.
The video's at the URL that you can read in the address bar.
It's worth watching the whole talk, but the bit that's relevant here,
is at about 32 minutes and 40 seconds into the video.
Wojtek Kalicinski, one of Google's engineers, explains about the
impact this can have on the size of your app. As we're creating a separate
layout, there's no advantage to keeping the string resource ID the same, and if
you watch that video, you'll see that there are potentially big disadvantages
in terms of the size of your app. So that's why I didn't create a v21 string
resource file, just for a single string resource. Even with a handful, I still
wouldn't put them in their own resource file. Okay, in the next section, we'll
create a settings dialog for our app. I'll see you then.