Google I/O 2017 announced API that allows the user to request fonts from the application, instead of attaching them inside APK. This feature is available on devices with Android 4.0 and higher through Support Library 26. There are about 850 open source fonts available that can be used for any purpose (including commercial). All of them can be viewed on Google Fonts page.
There are multiple advantages of using Downloadable Fonts:
- Reduced APK size, because there is no more need to attach fonts to the application,
- downloaded fonts are shared across multiple applications so it improves the overall health of the system.
Fig. 1 Downloadable Fonts process
Figure 2 shows the simplified process of downloading fonts. As you can see, every application gets fonts from FontProvider through FontContract. When a font is requested by an application, FontProvider checks if the desired font is already cached. If not, API will automatically download and cache it. Then, the font is provided to the application. Sounds a little bit complicated, but implementation is easy.
Let’s get started!
Downloadable fonts API require Support Library 26 or newer, so let’s start by adding it to module
It’s worth adding that newest appcompat lib moved from SDK Manager to Google’s Maven repository, so it’s also required to add
google() to repositories inside the project’s
As an example I will use the following layout:
Downloadable fonts via XML
To set downloadable font via XML go to Layout Editor, select TextView, and then under Properties, select fontFamily > More fonts… as shown in figure 2.
Fig. 2 Selecting a font for the chosen TextView
Set source to Google Fonts, select the desired font, check “Create downloadable font” and press OK.
Fig. 3 Selecting a downloadable font
Android Studio will automatically create three files:
- res/font/selected_font_name.xml (in my case abril_fatface.xml)
When a font provider is not preinstalled or if you are using the support library (our case), certificates must be declared to verify the font provider’s identity.
providerAuthority — the authority of the Font Provider to be used for the request,
providerPackage — the package for the Font Provider to be used for the request. This is used for verifying the identity of the provider,
query — the query to be sent over to the provider,
certificates — a resource array with a list of sets of hashes for the certificates the provider should sign with. This is used for verifying the identity of the provider.
This file provides metadata to Android Studio, so it can be later referred to as
This generated file is not essential, but it improves user experience. Layout inflation and resource retrieval are usually synchronous tasks (let’s forget about AsyncLayoutInflater for now). By default, the first attempt to retrieve fonts triggers a request to
FontProvider which may increase the first layout inflation time. To avoid it, we can pre-declare fonts inside AndroidManifest.xml with the following line:
After the system gets the font from
FontProvider it’s immediately avaiable. It’s worth mentioning, when font retrieval takes longer time than expected, the whole process is cancelled and the application will display a default font.
Now we are ready to set our font inside XML
Let’s add the following line to our
Fig. 5 Changed font via XML
The selected font has been successfully changed with one line (Fig. 5), but in most scenarios, we want to use the same font in the entire app, but adding to
fontFamily every view we want to change will obfuscate our code. Fortunately, downloadable fonts are also compatible with styles. Let’s look at the example:
We need to make sure that our
AppTheme style is set to the application inside AndroidManifest.xml:
The result if shown below (Fig. 6):
Fig. 6 Default downloadable font for the entire application
Downloadable fonts via Code
Downloadable fonts can also be set dynamically in code with method
FontsContractCompat.requestFont(final @NonNull Context context, final @NonNull FontRequest request, final @NonNull FontRequestCallback callback, final @NonNull Handler handler).
Let’s declare a few font names:
The function that creates the
FontRequestobject with a specific font name:
Note that parameters are the same as inside res/font/abril_fatface.xml file.
Finally, let’s set the button
onClickListener to call the
requestFont method :
Results of work are shown below:
All samples from this article are available as a working project in the repository linked here.