DeepLinkDispatchで手軽にAndroidのディープリンクを実装する

Androidアプリにディープリンクを簡単に組み込めるオープンソースライブラリです。Airbnbが公開しています。

https://github.com/airbnb/DeepLinkDispatch

# 使い方

APIは超簡単なので、大体公式のREADME見ればわかります。以下ほとんどただの意訳です^^;

## 基本

ディープリンクを張りたいActivityに、アノテーションを付けます。あとはonCreateの中で渡ってくるパラメータを受け取るだけ。

```java
@DeepLink("foo://example.com/deepLink/{id}")
public class MainActivity extends AppCompatActivity {

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

        if (getIntent().getBooleanExtra(DeepLink.IS_DEEP_LINK, false)) {
            Bundle parameters = getIntent().getExtras();

            String idString = parameters.getString("id");

            // Do something with the ID...
            Log.v("main", "id = " + idString);
        }
    }
}
```

これでビルド時に`DeepLinkActivity`というActivityが自動生成されます。なので、AndroidManifest.xmlに以下を追記しときます。

```xml
<activity
    android:name="com.airbnb.deeplinkdispatch.DeepLinkActivity"
    android:theme="@android:style/Theme.NoDisplay">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <!-- スキームはアプリで決める -->
        <data android:scheme="foo" />
    </intent-filter>
</activity>
```

## ひとつのActivityに複数のディープリンクを張りたい

`@DeepLink`の中に複数渡すだけ

```java
@DeepLink({"foo://example.com/deepLink/{id}", "foo://example.com/anotherDeepLink"})
public class MainActivity extends Activity {
  @Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (getIntent().getBooleanExtra(DeepLink.IS_DEEP_LINK, false)) {
      Bundle parameters = getIntent().getExtras();

      String idString = parameters.getString("id");

      // Do something with the ID...
    }
    ...
  }
}
```

## Activityを起動するIntentを指定する

Method annotationを使えばできます。使いドコロは、IntentのActionを指定したり、フラグをつけたりするとか？

```java
@DeepLink("foo://example.com/methodDeepLink/{param1}")
public static Intent intentForDeepLinkMethod(Context context) {
  return new Intent(context, MainActivity.class).setAction(ACTION_DEEP_LINK_METHOD);
}
```

## ディープリンクが発行されたときにコールバックを受け取る

DeepLinkActivityはディープリンクによってActivityが起動できたかどうかをIntentでブロードキャストしているので、BroadcastReceiverを用意すれば受け取れます。

```java
public class DeepLinkReceiver extends BroadcastReceiver {
  private static final String TAG = DeepLinkReceiver.class.getSimpleName();

  @Override
  public void onReceive(Context context, Intent intent) {
    String deepLinkUri = intent.getStringExtra(DeepLinkActivity.EXTRA_URI);

    if (intent.getBooleanExtra(DeepLinkActivity.EXTRA_SUCCESSFUL, false)) {
      Log.i(TAG, "Success deep linking: " + deepLinkUri);
    } else {
      String errorMessage = intent.getStringExtra(DeepLinkActivity.EXTRA_ERROR_MESSAGE);
      Log.e(TAG, "Error deep linking: " + deepLinkUri + " with error message +" + errorMessage);
    }
  }
}

public class YourApplication extends Application {
  @Override public void onCreate() {
    super.onCreate();
    IntentFilter intentFilter = new IntentFilter(DeepLinkActivity.ACTION);
    LocalBroadcastManager.getInstance(this).registerReceiver(new DeepLinkReceiver(), intentFilter);
  }
}
```

# おまけ：生成されるコード

## DeepLinkActivity

実際にディープリンクによって起動されるActivity。こいつが下記のDeepLinkLoaderを使ってURIをパースして、合致するActivityを起動している。Intentのブロードキャストもこいつが行う。最後にはfinishするので、ユーザーには見えない。

Method annotationによる起動時はリフレクションを使っているので、proguard必須。

## DeepLinkLoader

どのURIがどのActivity（やそのメソッド）に対応するかを判定するクラス