次の方法で共有


Android アプリのリンク

Web サイトとモバイル アプリを接続し、Web サイト上のリンクによってモバイル アプリが起動し、モバイル アプリにコンテンツが表示されるようにするのが望ましい場合がよくあります。 "アプリ リンク" ("ディープ リンク" とも呼ばれます) は、モバイル デバイスが URI に応答し、URI で表されるモバイル アプリでコンテンツを起動できるようにする手法です。

Android は、インテント システムを介してアプリ リンクを処理します。 モバイル ブラウザーでリンクをタップすると、Android が登録されているアプリに委任するインテントが、ブラウザーによってディスパッチされます。 これらのリンクでは、myappname:// などのカスタム スキームに基づくこと、または HTTP や HTTPS スキームを使うことができます。 たとえば、レシピ Web サイトのリンクをクリックすると、その Web サイトに関連付けられているモバイル アプリが開き、特定のレシピがユーザーに表示されます。 インテントを処理するためのアプリが複数登録されている場合、Android はインテントを処理するアプリの選択をユーザーに求める明確化ダイアログを表示します。 アプリをインストールしていないユーザーは、Web サイト上のコンテンツに移動させられます。

Android では、アプリ リンクは 3 つのカテゴリに分類されます。

  • "ディープ リンク" は、アプリ内の特定のコンテンツにユーザーを移動させるスキームの URI です。 ディープ リンクをクリックすると、ユーザーにディープ リンクを処理するアプリの選択を求める明確化ダイアログが表示されることがあります。
  • "Web リンク" は、HTTP または HTTPS スキームを使うディープ リンクです。 Android 12 以降の Web リンクでは、常にコンテンツが Web ブラウザーに表示されます。 以前のバージョンの Android では、アプリが Web リンクを処理できる場合は、Web リンクを処理するアプリの選択をユーザーに求める明確化ダイアログが表示されます。
  • "Android アプリ リンク" (API 23 以降で利用可能) は、HTTP または HTTPS スキームを使い、autoVerify 属性を含む Web リンクです。 この属性を使うと、アプリをアプリ リンクの既定のハンドラーにできます。 そのため、アプリ リンクをクリックすると、明確化ダイアログが表示されずにアプリが開きます。

.NET MAUI Android アプリは、アプリ リンクの 3 つのカテゴリをすべてサポートできます。 ただし、この記事では Android アプリ リンクに焦点を当てます。 これには、ドメインの所有権を証明するだけでなく、アプリとの関係が記述されているデジタル資産リンク ファイル JSON ファイルをドメインでホストする必要があります。 これにより、Android は、URI を処理しようとしているアプリが URI ドメインの所有権を持っていることを検証して、悪意のあるアプリがアプリ リンクをインターセプトするのを防ぐことができます。

.NET MAUI Android アプリで Android アプリのリンクを処理するプロセスは次のとおりです。

  1. ドメインの所有権を検証します。 詳しくは、「ドメインの所有権を検証する」をご覧ください。
  2. デジタル資産リンク ファイルを作成して Web サイトでホストします。 詳しくは、「デジタル資産リンク ファイルを作成してホストする」をご覧ください。
  3. アプリで Web サイト URI 用のインテント フィルターを構成します。 詳しくは、「インテント フィルターを構成する」をご覧ください。
  4. 受け取ったインテントからデータを読み取ります。 詳しくは、「受け取ったインテントからデータを読み取る」をご覧ください。

重要

Android アプリ リンクを使うには:

  • お使いのアプリのバージョンが、Google Play で公開されている必要があります。
  • Google の Developer Console で、コンパニオン Web サイトをアプリに対して登録する必要があります。 アプリと Web サイトを関連付けると、Web サイトとアプリの両方で機能するインデックスを URI に付けることができ、それを検索結果で提供できます。 詳しくは、support.google.com の「Google 検索での App Indexing」をご覧ください。

Android のアプリ リンクについて詳しくは、「Android アプリ リンクの処理」をご覧ください。

ドメインの所有権を検証する

Google Search Console 内からアプリ リンクを提供しているドメインの所有権を検証する必要があります。 所有権の検証とは、ユーザーが特定の Web サイトを所有していることを証明することを意味します。 Google Search Console では、複数の検証方法がサポートされています。 詳しくは、support.google.com で「サイトの所有権を確認する」をご覧ください。

Android アプリ リンクでは、Android は、アプリを URI の既定のハンドラーとして設定する前に、アプリと Web サイトの間の関連付けを検証する必要があります。 この検証は、アプリが最初にインストールされる時点で行われます。 デジタル資産リンク ファイルは JSON ファイルであり、次の場所にある関連 Web ドメインでホストされている必要があります: https://domain.name/.well-known/assetlinks.json

デジタル資産ファイルには、Android が関連付けを検証するために必要なメタデータが含まれています。 このファイルには、次のキーと値のペアが必要です。

  • namespace - Android アプリの名前空間。
  • package_name - Android アプリのパッケージ名。
  • sha256_cert_fingerprints - .keystore ファイルから取得された、署名済みアプリの SHA256 フィンガープリント。 キーストアの署名の検索については、「キーストアの署名を検索する」をご覧ください。

次の例の assetlinks.json ファイルでは、com.companyname.myrecipeapp Android アプリにリンクを開く権限が付与されます。

[
   {
      "relation": [
         "delegate_permission/common.handle_all_urls"
      ],
      "target": {
         "namespace": "android_app",
         "package_name": "com.companyname.myrecipeapp",
         "sha256_cert_fingerprints": [
            "14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"
         ]
      }
   }
]

複数の SHA256 フィンガープリントを登録して、アプリの異なるバージョンまたはビルドをサポートできます。 次の例の assetlinks.json ファイルでは、com.companyname.myrecipeappcom.companyname.mycookingapp 両方の Android アプリにリンクを開く権限が付与されます。

[
   {
      "relation": [
         "delegate_permission/common.handle_all_urls"
      ],
      "target": {
         "namespace": "android_app",
         "package_name": "com.companyname.myrecipeapp",
         "sha256_cert_fingerprints": [
            "14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"
         ]
      }
   },
   {
      "relation": [
         "delegate_permission/common.handle_all_urls"
      ],
      "target": {
         "namespace": "android_app",
         "package_name": "com.companyname.mycookingapp",
         "sha256_cert_fingerprints": [
            "14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"
         ]
      }
   }
]

ヒント

正しい JSON の生成と検証には、ステートメント リスト ジェネレータとテスター ツールを使います。

JSON 検証ファイルを https://domain.name/.well-known/assetlinks.json に発行するときは、次のことを確認する必要があります。

  • ファイルは、コンテンツ タイプ application/json で提供します。
  • アプリでスキームとして HTTPS が使われているかどうかに関係なく、ファイルには HTTPS 経由でアクセスできる必要があります。
  • ファイルにはリダイレクトなしでアクセスできる必要があります。
  • アプリ リンクで複数のドメインがサポートされている場合、ドメインごとに assetlinks.json ファイルを発行する必要があります。

デジタル資産ファイルが適切な形式で、適切にホストされていることは、Google のデジタル資産リンク API を使って確認できます。

https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=
  https://<WEB SITE ADDRESS>:&relation=delegate_permission/common.handle_all_urls

詳しくは、developer.android.com の「ウェブサイトの関連付けを宣言する」をご覧ください。

インテント フィルターを構成する

Web サイトから Android アプリのアクティビティに URI または URI のセットをマップするインテント フィルターを構成する必要があります。 .NET MAUI では、アクティビティに IntentFilterAttribute を追加すると、これを実現できます。 インテント フィルターでは、次の情報を宣言する必要があります。

  • ActionView - これは、情報を表示する要求に応答するインテント フィルターを登録します。
  • Categories - Web URI を正しく処理できるためには、インテント フィルターで CategoryDefaultCategoryBrowsable の両方を登録する必要があります。
  • DataScheme - インテント フィルターでは、カスタム スキーム、HTTP、HTTPS のいずれか 1 つ、2 つ、またはすべてを宣言する必要があります。
  • DataHost - これは URI の基になっているドメインです。
  • DataPathPrefix - これは、Web サイト上のリソースへの省略可能なパスです。/ で始まっている必要があります。
  • AutoVerify - これは、アプリと Web サイトの間の関係を検証するよう Android に指示します。 true に設定する必要があります。そうしないと、Android はアプリと Web サイトの間の関連付けを検証しないため、アプリを URI の既定のハンドラーとして設定しません。

次に示すのは、IntentFilterAttribute を使って https://www.recipe-app.com/recipes からのリンクを処理する方法の例です。

using Android.App;
using Android.Content;
using Android.Content.PM;

namespace MyNamespace;

[Activity(
    Theme = "@style/Maui.SplashTheme",
    MainLauncher = true,
    ConfigurationChanges = ConfigChanges.ScreenSize |
        ConfigChanges.Orientation |
        ConfigChanges.UiMode |
        ConfigChanges.ScreenLayout |
        ConfigChanges.SmallestScreenSize |
        ConfigChanges.KeyboardHidden |
        ConfigChanges.Density)]
[IntentFilter(
    new string[] { Intent.ActionView },
    Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },
    DataScheme = "https",
    DataHost = "recipe-app.com",
    DataPath = "/recipe",
    AutoVerify = true,)]    
public class MainActivity : MauiAppCompatActivity
{
}

Note

インテント フィルターでは、複数のスキームとホストを指定できます。 詳しくは、developer.android.com の「アプリ コンテンツ用のディープリンクを作成する」をご覧ください。

Android は、アプリを URI の既定のハンドラーとして登録する前に、インテント フィルターで識別されたすべてのホストを、Web サイト上のデジタル資産ファイルと比べて検証します。 Android がアプリを既定のハンドラーとして設定するには、すべてのインテント フィルターが検証を通過している必要があります。 アクティビティ コンテンツの URI を含むインテント フィルターを追加すると、Android は、実行時に URI が一致するインテントをアプリにルーティングできます。

アクティビティを他のアプリで起動できるように、アクティビティをエクスポート可能として指定することが必要な場合もあります。 これは、既存の ActivityAttributeExported = true を追加して実現できます。 詳しくは、developer.android.com の activity 要素に関する記事をご覧ください。

Web URI のインテントが呼び出されると、Android は要求が成功するまで次のアクションを試みます。

  1. URI を処理する優先アプリを開きます。
  2. URI を処理するために使用できる唯一のアプリを開きます。
  3. ユーザーが URI を処理するアプリを選択できるようにします。

インテントとインテント フィルターについて詳しくは、developer.android.com の「インテントとインテント フィルタ」をご覧ください。

受け取ったインテントからデータを読み取る

Android がインテント フィルターを通じてアクティビティを開始するとき、ユーザーはインテントによって提供されるデータを使って、何を行うかを決定できます。 これは、ライフサイクルの早い段階のデリゲート (理想的には OnCreate) で実行する必要があります。 OnCreate デリゲートは、アクティビティの作成時に呼び出されます。 ライフサイクルのデリゲートについて詳しくは、「プラットフォーム ライフサイクル イベント」をご覧ください。

呼び出されている Android ライフサイクル デリゲートに応答するには、MauiProgram クラスの CreateMauiapp メソッド内の MauiAppBuilder オブジェクトに対して ConfigureLifecycleEvents メソッドを呼び出します。 次に、ILifecycleBuilder オブジェクトで AddAndroid メソッドを呼び出して、必要なデリゲートのハンドラーを登録する Action を指定します。

using Microsoft.Maui.LifecycleEvents;
using Microsoft.Extensions.Logging;

namespace MyNamespace;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            })
            .ConfigureLifecycleEvents(lifecycle =>
            {
#if ANDROID
                lifecycle.AddAndroid(android =>
                {
                    android.OnCreate((activity, bundle) =>
                    {
                        var action = activity.Intent?.Action;
                        var data = activity.Intent?.Data?.ToString();

                        if (action == Android.Content.Intent.ActionView && data is not null)
                        {
                            Task.Run(() => HandleAppLink(data));
                        }
                    });
                });
#endif
            });

#if DEBUG
        builder.Logging.AddDebug();
#endif

        return builder.Build();
    }

    static void HandleAppLink(string url)
    {
        if (Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out var uri))
            App.Current?.SendOnAppLinkRequestReceived(uri);
    }
}

Intent.Action プロパティは受け取ったインテントに関連付けられているアクションを取得し、Intent.Data プロパティは受け取ったインテントに関連付けられているデータを取得します。 インテントのアクションが ActionView に設定されている場合は、SendOnAppLinkRequestReceived メソッドを使ってインテントのデータを App クラスに渡すことができます。

警告

アプリ リンクはアプリへの攻撃ベクトルになる可能性があるため、必ずすべての URI パラメーターを検証し、形式に誤りがある URI を破棄してください。

インテント データを受け取って処理するには、App クラスの OnAppLinkRequestReceived メソッドをオーバーライドします。

namespace MyNamespace;

public partial class App : Application
{
    public App()
    {
        InitializeComponent();

        MainPage = new AppShell();
    }

    protected override async void OnAppLinkRequestReceived(Uri uri)
    {
        base.OnAppLinkRequestReceived(uri);

        // Show an alert to test that the app link was received.
        await Dispatcher.DispatchAsync(async () =>
        {
            await Windows[0].Page!.DisplayAlert("App link received", uri.ToString(), "OK");
        });

        Console.WriteLine("App link: " + uri.ToString());
    }
}

上の例では、OnAppLinkRequestReceived オーバーライドによってアプリ リンクの URI が表示されます。 実際には、ユーザーは、アプリ リンクによって、プロンプト、ログイン、またはその他の中断なしに、URI で表されるコンテンツに直接移動する必要があります。 したがって、OnAppLinkRequestReceived のオーバーライドの中で、URI によって表されるコンテンツへのナビゲーションを呼び出します。

デジタル資産ファイルが正しくホストされている場合は、Android Debug Bridge adb とアクティビティ マネージャー ツール am を使って URI を開く操作をシミュレートし、アプリ リンクが正しく動作することを確認できます。 たとえば、次のコマンドは、URI に関連付けられているターゲット アプリのアクティビティの表示を試みます。

adb shell am start -W -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d YOUR_URI_HERE

このコマンドは、Android がモバイル アプリに渡す必要があるインテントをディスパッチします。これにより、URI に登録されているアクティビティが起動されて表示されるはずです。

Note

エミュレーターまたはデバイスに対して adb を実行できます。

さらに、デバイスにインストールされているアプリの既存のリンク処理ポリシーを表示できます。

adb shell dumpsys package domain-preferred-apps

このコマンドを実行すると、次の情報が表示されます。

  • Package - アプリのパッケージ名。
  • Domain - その Web リンクがアプリによって処理されるドメイン (スペース区切り)。
  • Status - アプリの現在のリンク処理状態。 always という値は、アプリで AutoVerifytrue に設定されていて、アプリがシステム検証に合格したことを意味します。 その後に、ユーザー設定のレコードを表す 16 進数が続きます。

adb コマンドについて詳しくは、「Android Debug Bridge」をご覧ください。

さらに、Play Console を使って Android アプリ リンクの管理と検証を行うことができます。 詳しくは、developer.android.com の「Android アプリ リンクを管理、確認する」をご覧ください。

トラブルシューティングのアドバイスについては、developer.android.com の「一般的な実装エラーを修正する」をご覧ください。