Google絵文字フォントポリシーのサポート
GoogleはAndroidを導入しました:Android絵文字ポリシーは、アプリ開発者にUnicode絵文字の最新バージョンをサポートすることを強制します。このポリシーでは、次のように述べています:
サードパーティのライブラリによって提供されるものを含め、カスタム絵文字実装を持つアプリは、新しいUnicode絵文字がリリースされてから4ヶ月以内にAndroid 12+上で実行する場合、最新のUnicodeバージョンを完全にサポートする必要があります。
このガイドでは、絵文字フォントをバンドルするか、Androidを使用することによって、このポリシーをサポートする方法を示します:Googleダウンロード可能フォント。
絵文字フォントのバンドル VS Googleダウンロード可能フォント
最新の絵文字をサポートするために、両方の方法にはいくつかの利点と欠点があります。ここでは、2つの方法のメリットとデメリットをご紹介します:
バンドルフォントの利点
- フォントの読み込みが速い
- インターネットがない環境でも使用可能
- すべてのオペレーティングシステムで動作
- 独立(Qt以外の依存関係がない)
- よりシンプルなソリューション
フォントをバンドルするデメリット
- アプリケーションのサイズが大きくなる(NotoColorEmojiは10MB程度)
- 新しいリリースでフォントを更新する必要がある。
- 古いアプリでは絵文字が自動的に更新されない
Googleダウンロードフォントの利点
- アプリケーションのサイズを変更しない
- 自動更新
- 関係のない複数のアプリが同じフォントを共有する
Googleダウンロードフォントのデメリット
- Googleモバイルサービスに依存
- アンドロイドのみ
- キャッシュされていないフォントはダウンロードされる
- 事前にキャッシュされていない場合、インターネットなしでは動作しない
- フォントをバンドルするよりも複雑
フォントをバンドルする方法
フォントを入手してバンドルし、後でQMLまたはC++を使って読み込む必要があります。
フォントの入手
このガイドでは、GoogleNotoColorEmojiフォントを使用します。NotoColorEmojiはSIL OPEN FONT LICENSEによってライセンスされたフォントです。
注意: リポジトリからダウンロードする場合は、NotoColorEmoji.ttfの代わりにNotoColorEmoji_WindowsCompatible.ttfフォントをダウンロードしてください。NotoColorEmoji.ttf は異なるフォーマットで内部的にビルドされており、Android/Chrome/Chromium OS でのみサポートされています。Qtは他のプラットフォームでも動作するため、Qtのフォントローダーは標準的な形式のTrueType/OpenTypeフォントを必要とします。
フォントの追加
フォントをバンドルする適切な方法は、Qt Resource Systemファイルに追加することです。例えば、NotoColorEmoji_WindowsCompatible.ttfを含むフォント用のリソースファイル "font.qrc "を作成します。新しいリソースファイルを埋め込むには、CMakeLists.txt に以下のコードを記述します:
qt_add_big_resources(PROJECT_SOURCES font.qrc)
バンドルされているフォントを C++ で読み込む
C++ を使っ て フ ォ ン ト を読み込むには、QFontDatabase を使います。
// Loading NotoColorEmoji bundled using C++ QFontDatabase QFontDatabase::addApplicationFont(QStringLiteral(":/NotoColorEmoji_WindowsCompatible.ttf"));
注: 上記のコードは、QQmlApplicationEngine が QML をロードする前に使用する必要があります。そうすれば、QML がロードされたときにフォントはすでに存在し、使用する準備ができています。
バンドルされているフォントを QML で読み込む
QML でフォントを読み込むには、FontLoader を使います:
// Loading NotoColorEmoji using QML FontLoader FontLoader { source:"NotoColorEmoji_WindowsCompatible.ttf" }
Googleダウンロードフォントを使う
絵文字フォントにGoogleダウンロードフォントを使用することで、アプリケーションのサイズを大きくすることなく、自動的に絵文字フォントを更新することができます。ダウンロード可能なフォント機能を使ってフォントをダウンロードする手順は、Androidで詳しく見ることができます:ダウンロード可能なフォントのプロセス
このガイドでは、以下のプロセスを説明します:
- C++コードの開始
- C++がJava関数を呼び出す
- JavaがGDFを呼び出してフォントを取得
- JavaがフォントURIを開く
- Javaがファイル記述子をC++に返す
- C++がQFontDatabase
設定
Google Downloadable FontsはAPIレベル26(Android 8.0)で利用可能です。しかし、アプリがAndroidXを使用している場合、API 14以前のAPIに対応することも可能です。
注: Androidのドキュメントでは、AndroidX.Support Libraryではなく、Android.SupportLibraryを参照しています:注:Androidのドキュメントでは、AndroidXではなくAndroid:Support Libraryを参照しています。しかし、サポート・ライブラリのメンテナンスは終了しており、AndroidXに取って代わられているため、Googleの推奨に従ってAndroidXを使用することにしました。
Androidパッケージ・テンプレートのカスタマイズ
まず、Androidパッケージ・テンプレートをカスタマイズする必要がある。そのためには、Qt Creator 、「Projects」タブを開き、「Build Settings」で「Build Android APK」を検索する。Build Steps」の中にあるはずです。詳細を展開すると、「Create Templates」というボタンが表示されます。
Create templates "をクリックし、ウィザードに従うと、Android用の設定ファイルがいくつか入ったフォルダが作成される。デフォルトでは、プロジェクト・ディレクトリ内のandroid
というフォルダになります。
qmakeを使ってandroidテンプレートをカスタマイズする方法については、Android Package Templatesを参照してください。
このガイドのようにCMakeとQt 6を使用している場合は、QT_ANDROID_PACKAGE_SOURCE_DIRプロパティを設定する必要があります。例
set_property(TARGET emojiremotefont PROPERTY
QT_ANDROID_PACKAGE_SOURCE_DIR
${CMAKE_CURRENT_SOURCE_DIR}/android)
AndroidXの追加
AndroidXを追加するには、上記で追加したQT_ANDROID_PACKAGE_SOURCE_DIRフォルダ内のbuild.gradle
ファイルを開き、そこに依存関係を追加します:
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) implementation 'androidx.appcompat:appcompat:1.4.1' }
AndroidXを使用するには、フラグを設定する必要があります。そのために、QT_ANDROID_PACKAGE_SOURCE_DIR内にgradle.properties
という名前のファイルを作成し、次の行を追加します:
android.useAndroidX=true
フォント・プロバイダ証明書の追加
AndroidXを使うので、もう1つ必要な設定があります:フォント・プロバイダ証明書を追加します。GMSフォント・プロバイダを使用するには、Android.GMSフォント・プロバイダ証明書をダウンロードしてください:GMSフォント・プロバイダ証明書をダウンロードしてください。他のフォントプロバイダーを使用する場合は、プロバイダー自身から証明書を取得する必要があります。
ファイルをダウンロードしたら、android templates フォルダ内のvalues
フォルダにコピーして、Android Resources に追加します(Qt Resource システムではありません)。以下の画像は(1)の正しいフォルダを示しています:
Javaコード
さて、コードを掘り下げましょう!
Java/KotlinコードをAndroidテンプレートに追加する必要があります。アンドロイド・テンプレート・フォルダーのsrc
フォルダーの下に置いてください。src
フォルダーと java ファイル用のフォルダー構造を作成する必要があるかもしれません。このフォルダ構造は、前節の(2)のAndroid Templates Folderの画像で確認できます。
C++でフォントを取得するには、Javaのコードで以下のことを行う必要があります:
- フォント要求を作成する
- フ ォ ン ト 要求を使っ て FontsContractCompat か ら フ ォ ン ト を取得。
- フ ォ ン ト 情報 と フ ォ ン ト URI (内容ス キーマ フ ァ イ ル) を取得。
- URI を開いてファイル記述子を取得する。
- ファイル記述子をC++コードに返す
フ ォ ン ト 要求を作成す る には、 フ ォ ン ト プ ロ バ イ ダー情報 (権限、 パ ッ ケージ、 証明書) と フ ォ ン ト の検索 ク エ リ が必要です。証明書については、前に Android リソースに追加した GMS Font Provider Certificates ファイルfonts_cert.xml
を使います。
// GMS fonts provider data private static final String PROVIDER_AUTHORITY = "com.google.android.gms.fonts"; private static final String PROVIDER_PACKAGE = "com.google.android.gms"; // Emoji font search query (copied from EmojiCompat source) private static final String EMOJI_QUERY = "emojicompat-emoji-font"; // Font Certificates resources strings (from fonts_certs.xml) private static final String FONT_CERTIFICATE_ID = "com_google_android_gms_fonts_certs"; private static final String FONT_CERTIFICATE_TYPE = "array"; (...) // obtain id for the font_certs.xml int certificateId = context.getResources().getIdentifier( FONT_CERTIFICATE_ID, FONT_CERTIFICATE_TYPE, context.getPackageName()); // creating the request FontRequest request = new FontRequest( PROVIDER_AUTHORITY, PROVIDER_PACKAGE, EMOJI_QUERY, certificateId);
さて、先ほど作成したリクエストを使ってフォントを取得します:
// fetch the font FontsContractCompat.FontFamilyResult result = FontsContractCompat.fetchFonts(context, null, request);
FontInfo と URI を取得:
final FontsContractCompat.FontInfo[] fontInfos = result.getFonts(); final Uri emojiFontUri = fontInfos[0].getUri();
FontInfo と URI を取得 : URI か ら 新規ネ イ テ ィ ブ フ ァ イ ル記述子を開 く :
final ContentResolver resolver = context.getContentResolver(); // in this case the Font URI is always a content scheme file, made // so the app requesting it has permissions to open final ParcelFileDescriptor fileDescriptor = resolver.openFileDescriptor(fontInfos[0].getUri(), "r"); // the detachFd will return a native file descriptor that we must close // later in C++ code int fd = fileDescriptor.detachFd(); // return fd to C++
注: Javaでコーディングされたものはすべて、JNIを使ってC++で行うことができます。このガイドで紹介するコードは簡略化されています。本番用のコードでは、例外のキャッチなどをチェックする必要があります。
C++コード
OK、Java側ではすべて終わりました。C++側に行きましょう。
C++はJavaコードを呼び出し、ファイル記述子を使用してフォントをQtにロードする役割を担います。
Qt 6におけるC++とJava間の通信がどのように行われるかをより深く理解するには、Qt Android Notifierのサンプルをご覧ください。
Java コードからファイル記述子を取得した後、ファイル記述子をQFile クラスにラップし、QFontDatabase を使ってフォントファイルを読み込みます:
QFile file; file.open(fd, QFile::OpenModeFlag::ReadOnly, QFile::FileHandleFlag::AutoCloseHandle); QFontDatabase::addApplicationFontFromData(file->readAll());
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.