Downloadable Fonts

activity_main.xmlMainActivity.javaeater.xmlfont_certs.xmlAndroidManifest.xmlpreloaded_fonts.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="16dp"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="@font/eater"
        android:text="Hello World!"
        android:textSize="30sp" />

    <EditText
        android:id="@+id/edit_text_font"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Font" />

    <Button
        android:id="@+id/button_load_font"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Load font" />

</LinearLayout>
package com.codinginflow.downloadablefontsexample;

import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.provider.FontRequest;
import androidx.core.provider.FontsContractCompat;

import static androidx.core.provider.FontsContractCompat.FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR;
import static androidx.core.provider.FontsContractCompat.FontRequestCallback.FAIL_REASON_FONT_NOT_FOUND;
import static androidx.core.provider.FontsContractCompat.FontRequestCallback.FAIL_REASON_FONT_UNAVAILABLE;
import static androidx.core.provider.FontsContractCompat.FontRequestCallback.FAIL_REASON_MALFORMED_QUERY;
import static androidx.core.provider.FontsContractCompat.FontRequestCallback.FAIL_REASON_PROVIDER_NOT_FOUND;
import static androidx.core.provider.FontsContractCompat.FontRequestCallback.FAIL_REASON_WRONG_CERTIFICATES;

public class MainActivity extends AppCompatActivity {
    private TextView textView;
    private EditText editTextFont;
    private Button buttonLoadFont;

    private HandlerThread handlerThread;
    private Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.text_view);
        editTextFont = findViewById(R.id.edit_text_font);
        buttonLoadFont = findViewById(R.id.button_load_font);

        buttonLoadFont.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loadFont();
            }
        });

        handlerThread = new HandlerThread("FontThread");
        handlerThread.start();
        handler = new Handler(handlerThread.getLooper());
    }

    private void loadFont() {
        String query = editTextFont.getText().toString();

        FontRequest request = new FontRequest(
                "com.google.android.gms.fonts",
                "com.google.android.gms",
                query,
                R.array.com_google_android_gms_fonts_certs
        );

        FontsContractCompat.FontRequestCallback callback =
                new FontsContractCompat.FontRequestCallback() {
                    @Override
                    public void onTypefaceRetrieved(Typeface typeface) {
                        textView.setTypeface(typeface);
                    }

                    @Override
                    public void onTypefaceRequestFailed(int reason) {
                        showError(reason);
                    }
                };

        FontsContractCompat.requestFont(this, request, callback, handler);
    }

    private void showError(int reason) {
        String errorText;

        switch (reason) {
            case FAIL_REASON_PROVIDER_NOT_FOUND:
                errorText = "FAIL_REASON_PROVIDER_NOT_FOUND";
                break;
            case FAIL_REASON_FONT_NOT_FOUND:
                errorText = "FAIL_REASON_FONT_NOT_FOUND";
                break;
            case FAIL_REASON_FONT_LOAD_ERROR:
                errorText = "FAIL_REASON_FONT_LOAD_ERROR";
                break;
            case FAIL_REASON_FONT_UNAVAILABLE:
                errorText = "FAIL_REASON_FONT_UNAVAILABLE";
                break;
            case FAIL_REASON_MALFORMED_QUERY:
                errorText = "FAIL_REASON_MALFORMED_QUERY";
                break;
            case FAIL_REASON_WRONG_CERTIFICATES:
                errorText = "FAIL_REASON_WRONG_CERTIFICATES";
                break;
            default:
                errorText = "Unknown error number: " + reason;
                break;
        }

        Toast.makeText(this, errorText, Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        handlerThread.quit();
    }
}
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:app="http://schemas.android.com/apk/res-auto"
        app:fontProviderAuthority="com.google.android.gms.fonts"
        app:fontProviderPackage="com.google.android.gms"
        app:fontProviderQuery="Eater"
        app:fontProviderCerts="@array/com_google_android_gms_fonts_certs">
</font-family>
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <array name="com_google_android_gms_fonts_certs">
        <item>@array/com_google_android_gms_fonts_certs_dev</item>
        <item>@array/com_google_android_gms_fonts_certs_prod</item>
    </array>
    <string-array name="com_google_android_gms_fonts_certs_dev">
        <item>
            MIIEqDCCA5CgAwIBAgIJANWFuGx90071MA0GCSqGSIb3DQEBBAU[...]
        </item>
    </string-array>
    <string-array name="com_google_android_gms_fonts_certs_prod">
        <item>
            MIIEQzCCAyugAwIBAgIJAMLgh0ZkSjCNMA0GCSqGSIb3DQEBBAU[...]
        </item>
    </string-array>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.codinginflow.downloadablefontsexample">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <meta-data
            android:name="preloaded_fonts"
            android:resource="@array/preloaded_fonts" />
    </application>

</manifest>
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <array name="preloaded_fonts" translatable="false">
        <item>@font/eater</item>
    </array>
</resources>