GitHub PagesでApp Linksの構築

投稿日:  更新日:

GitHub PagesでAndroid App Linksの構築を行ってみました。

App Linksの構築は、Android StudioにAssistant機能が備わっているので、至って簡単です。

GitHub Pagesは、App Linksで使うには少し癖があります。理解せずに構築すると、「所有者の検証」が出来ずに失敗すると思います。その点についても、記載しましたので参考にして下さい。

ちなみに、ローカルWebサーバーでApp Linksを構築する方法も検討したのですが、所有者の検証でシステムに自己署名証明書を信頼できる証明書と認識させる方法が見つからず、断念しました。

※環境:Android Studio Otter | 2025.2.1 Patch 1

スポンサーリンク

App Links

「App Links(正式にはAndroid App Links)」は、Web Linksの中でアプリとWebサイトの所有者が同じ場合に、実行するすことが可能なリンクです。

「同じである?」の検証結果が「偽」ならば、リンクできません。

また、Webサイトを参照するアプリが一意に定まる(Webサイトがアプリを指定する)ので、アプリチューザーが開くことはありません。リンクを行うと直ちに目的のアプリが呼び出されます。

App Linksの概要

このような条件を設けることにより、リンクのセキュリティの崩壊が回避できます。

ですので、Web Linksを行う場合は、App Linksにすることが推奨されています。
※リンクとセキュリティの詳細は「リンクの種類(Deep/Web/App Links)と違い」を参照

スポンサーリンク

所有者の検証

「アプリとWebサイトの所有者が同じであるかどうか?」の検証は、アプリが携帯端末へインストールされる時に行われます。

Digital Asset Linksの構成

前もって、フィンガープリントを記入したAsset Linksファイル(assetlinks.json)をWebサイトへ登録しておきます。

アプリのインストール時に、AndroidManifestファイルのインテントフィルターにautoVerify=”true”が存在すると、システムはWebサイトのAsset Linskファイルを取得し、アプリとWebサイトのフィンガープリントを比較します。

両者のフィンガープリントが一致していれば、「アプリとWebサイトの所有者は同じ」と判断されます。そして、この検証結果はシステム内に保持されます。

この仕組みを「Digital Asset Links」といいます。

ちなみに、AndroidシステムとWebサイトのフィンガープリントのやり取りは、httpsで行われる点に注意して下さい。

スポンサーリンク

Webサイトの構築

Webサイトとして「GitHub Pages」を用います。

GitHub Pagesの作成

GitHub Pagesは、ユーザーアカウントはたは共有アカウント(Organization)のどちらで作成しても構いません。今回はOrganizationで作成しました。
※Organizationについては「GitHubのOrganization/Team/Repositoryの作成」を参照

作成後に公開設定も行ってください。※ここでは省略

GitHub Pagesの作成

作成時の注意点があります。

リポジトリ名は「アカウント名+”.github.io”」にして下さい。GitHub PagesのURLからパス(リポジトリ名)を省くことが出来ます。

GitHub PagesのURL

「Digital Asset Links」が、ドメイン(ホスト名)の直下にassetlinks.jsonがあることを期待するからです。※assetlinks.jsonの配置は後述

スポンサーリンク

Webコンテンツの登録

GitHub Pagesへコンテンツをアップロードします。

サンプルはJavaScriptと画像を含む簡単なコンテンツにしました。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1"/>
    <title>MyContent</title>
</head>
<body>
    <p id="text"></p>
    <script>
        const text = document.getElementById('text');
        const mesg = 'このパージのURLは「'+location.href+'」です。';
        text.innerHTML = mesg;
    </script>
    <center><p>【 My Content 】</p></center>
    <center><img src="./Droid.png" alt="Droid-Kun"></center>
</body>
</html>

Droid.png

スポンサーリンク

リンクの構築

Add Linksでリンクが可能なアプリを構築したい場合、Android Studioの「App Links Assistant」を使うと便利です。

App Links Assistantを開く

Toolsメニューから「App Links Assistant」を選びます。

App Links Assistantを開く1

「Create Applink」を押すと、Assistantが開きます。

App Links Assistantを開く2

リンクの構築は、番号の順番に実行して行けば、おのずと完成します。

App Links Assistantを開く3

スポンサーリンク

(0)コンポーネントの準備

呼び出し先アプリ(アプリコンポーネント)は、WebViewによる簡易ブラウザーを実装したActivityを用います。

先に、空のActivity(サンプルはMySaiteActivity)を作成して下さい。※作成方法は省略

(1)Add URL intent filters

呼び出し先のアプリ(アプリコンポーネント)のインテントフィルターを定義します。

図のように操作して、Host(GitHub PagesのURL)とActivity(呼び出し先のアプリコンポーネント)を入力して下さい。

Add URL intent filters(1)

Add URL intent filters(2)

入力した内容に従い、インテントフィルターがAndroidManifestファイルへ書き込まれます。

ポイントは「autoVerify=”true”」です。この記述があることで、「所有者の検証」が行われるようになります。

Add URL intent filters(3)

		...
        <activity
            android:name=".MySiteActivity"
            android:exported="true"
            android:label="@string/title_activity_my_site"
            android:theme="@style/Theme.ResAppLinks">
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data android:scheme="https" />
                <data android:host="mysite-2025.github.io" />
            </intent-filter>
        </activity>
		...

また、次の2点の変更も、追加で行ってい下さい。

  • ・android.permission.INTERNETを追記
  •   ⇒ コンポーネントがネットワークへアクセスするため
  • ・exported=”true”に変更
  •   ⇒ コンポーネントを他から呼び出し可能にするため
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.INTERNET" />

    <application ...>
		...
    </application>

</manifest>
スポンサーリンク

(2)Add logic to handle the intent

呼び出し先が受け取ったインテントから、URLを取得する定型コードを埋め込みます。

Activity(呼び出し先のアプリコンポーネント)を指定してください。

URLを取得する定型コード

この定型コードから得られるURLで、呼び出し先アプリの処理(簡易Webブラウズー)を記述することになります。

class MySiteActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            ...
        }
        // ATTENTION: This was auto-generated to handle app links.
        val appLinkIntent: Intent = intent
        val appLinkAction: String? = appLinkIntent.action
        val appLinkData: Uri? = appLinkIntent.data
    }
}

取得されるURLは、インテントフィルターのdataに書き込んだURL(https://mysite.github.io)です。

スポンサーリンク

(3)Associate website

フィンガープリントの作成とAsset Linskファイルの配置を行います。

フィンガープリントの作成とAsset Linskファイルの配置

スポンサーリンク

フィンガープリントの作成

(a)と(b)から作成元になる署名設定を選び、「Generate …」ボタン押すと、フィンガープリントがPreview欄に作成されます。

今回は「アプリの開発中」を想定し、Signing Configを選択しました。

(a) Signing config ... アプリ(APK)の署名設定

  debug   : debugはAndroid Studioが自動でキー(署名鍵)を作成
            そのキーでアプリを署名

(b) Keystore file  ... キーストア内の署名設定

Asset Linksファイルの配置

Preview欄の表示はAsset Lilnksのフォーマットになっています。そのまま、ファイルassetlinks.jsonへ保存してください。そして、Webサイトへ配置します。

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.example.myapp",
    "sha256_cert_fingerprints":
    ["B4:04:39: ... :D0:1E:DB"]
  }
}]

配置先は「WebサイトのRoot/.well-known/assetlinks.json」です。これは、Digital Asset Linksで決められています。

WebサイトのRoot
│  Droid.png		... Webコンテンツ
│  index.html		... 〃
│  README.md		... GitHub PagesのMarkdown
│  _config.yml		... Jekyllの設定
│
└─.well-known               ... このフォルダに配置
        assetlinks.json     ... Asset Linksファイル
 注意:_config.ymlの作成 
GitHub PagesはJekyll(静的サイトジェネレータ)により作られます。

Jekyllはデフォルトでカレントフォルダー内のみを参照し、下位フォルダー内を参照しません。

ですので、assetlinks.jsonは参照されません。

Jekyllが下位フォルダー内を参照するように、設定ファイル(_config.yml)を作り、以下の項目を記載して下さい。

include: [".well-known"]
スポンサーリンク

リンクの検証

「Link and Verify」ボタンを押すと、ここまで行った設定をチェックします。

緑レ」が付けばOKです。

赤×」はNGです。NGの理由が表示されます。理由を参考に問題個所を探して修正して下さい。

(4)Test on device or emulator

実機またはエミュレーターを使って、App Linksで呼び出し先アプリ(アプリコンポーネント)が実行されることをテストします。

App Linksのテスト

緑レ」が付けばOKです。

赤×」はNGです。NGの理由が表示されます。理由を参考に問題個所を探して修正して下さい。

ただし、まだ、アプリの実装(WebViewによる簡易ブラウザー)を行っていないので、動作はプロジェクト作成時のままです。

App Linksのテスト

スポンサーリンク

アプリの実装

WebViewを用いた簡易ブラウザーを構築します。

class MySiteActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // ATTENTION: This was auto-generated to handle app links.
        val appLinkIntent: Intent = intent
        val appLinkAction: String? = appLinkIntent.action
        val appLinkData: Uri? = appLinkIntent.data
        
        enableEdgeToEdge()
        setContent {
            ResAppLinksTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    Column(
                        modifier = Modifier.padding(innerPadding).fillMaxSize()
                    ) {
                        AndroidView(
                            factory = ::WebView,
                            update = { webView ->
                                webView.settings.javaScriptEnabled = true
                                webView.webViewClient = WebViewClient()
                                appLinkData?.let {
                                    webView.loadUrl(it.toString())
                                }
                            },
                            modifier = Modifier
                                .background(Color.Gray)
                                .padding(10.dp).fillMaxWidth().height(300.dp)
                        )
                    }
                }
            }
        }
    }
}
スポンサーリンク

App Linksの実行

構築したApp Linksでアプリの呼び出しを行います。

App Linksの実行

別途用意したアプリ(呼び出し元)から、下記のようにIntentを発行して下さい。

                                val _appComponentIntent = Intent().apply {
                                    action = Intent.ACTION_VIEW
                                    addCategory(Intent.CATEGORY_BROWSABLE)
                                    data = Uri.parse("https://mysite-2025.github.io")
                                }
                                startActivity(_appComponentIntent)

Webサイトと所有者の同じアプリが選択されて、実行されます。

App Linksの実行

URI:httpsに対応するアプリは他にもあります。例えば、Chromeです。

しかし、アプリチューザーは起動されません。直ちに、MySiteActivityが選択されています。

スポンサーリンク

関連記事:

アプリを構成する最上位の構成要素がアプリケーションコンポーネント(App component)です。 アプリケーションコンポーネントの概要をまとめます。 ...
「インテントの解決」はシステム内でアプリケーションコンポーネントを選択する処理のことです。 この選択する処理の流れが複雑で、ちょっと癖がありあます。 ここでは「インテントの解決」の処理の流れについてまとめます。 ...
アプリを構成する最上位の構成要素がアプリケーションコンポーネント(App component)です。 Activityはアプリケーションコンポーネントの1つです。アプリケーションの画面と処理を構築します。 Activityについてまとめます。 ...
アプリを構成する最上位の構成要素がアプリケーションコンポーネント(App component)です。 Content Providerはアプリケーションコンポーネントの1つです。アプリケーションが管理するデータを公開(共有)します。 Content Providerについてまとめます。 ...
アプリケーションコンポーネントの連携は、容易にアプリの機能を拡充できる、優れた仕組みです。 このコンポーネントの連携でYouTube動画を再生する場合、インテントの解決に癖があり、少々難解です。 ですので、後々、困らないように、ここへまとめます。 ※環境:Android Studio Meerkat | 2024.3.1 Patch 1     Kotlin 2.0.0 ...
コンピュータの世界で「リンク」というと、次の2つが頭に浮かびます。 ウェッブページのハイパーテキスト ファイルシステムのファイル(ディレクトリ)リンク しかし、携帯端末で稼働するモバイルアプリでは、また別の意味を持ちます。 モバイルアプリの「リンク」とは「アプリから同一端末内の他アプリを呼び出すこと」です。 3つの種類に分類されているので、違いと特徴をここに整理します。 ...
スポンサーリンク