[翻訳] Nearby Messages API for Android (Publish and Subscribe)

Nearby Messages API for Androidの [Publish and Subscribe](https://developers.google.com/nearby/messages/android/pub-sub) を翻訳してみました。
お気づきの点があればコメント頂ければと思います。

以下、関連する投稿へのリンクです。
■ Google Play services Nearby　[公式](https://developers.google.com/nearby/)　[翻訳](http://qiita.com/tnagao3000/items/5fb840eaa65747ac4347) 
■ Nearby Messages API (Overview)　[公式](https://developers.google.com/nearby/messages/overview)　[翻訳](http://qiita.com/tnagao3000/items/623b6a855b678dcaa747)
■ Nearby Messages API for Android (Get Started)　[公式](https://developers.google.com/nearby/messages/android/get-started)　[翻訳](http://qiita.com/tnagao3000/items/b166fb06cf91d365f20c)
■ **Nearby Messages API for Android (Publish and Subscribe)**　[公式](https://developers.google.com/nearby/messages/android/pub-sub)　[翻訳](http://qiita.com/tnagao3000/items/a310ae2d2ff45414a678)


※ 公式ドキュメントでリンクがいくつか切れていましたが、修正していません。 ( =①ω①= )

## Publish and Subscribe
>
Nearby Messages is a publish-subscribe API which lets nearby devices exchange small payloads of data. Once a device publishes a message, nearby devices can receive the message. This guide walks you through all of the functionality your app must implement in order to publish messages, and subscribe to messages using the Nearby Messages API.
>
The set of nearby devices is determined by the exchange of small tokens over Bluetooth and ultrasonic (inaudible) audio. When a device detects a token from a nearby device, it sends the token to the Nearby Messages server to validate it and check if there are any messages to deliver for the application’s current set of subscriptions.
>
An application can control the set of mediums used for device discovery, and whether the mediums are used to broadcast tokens and/or scan for tokens. By default, broadcasting and scanning is done on all the mediums. To do discovery on a subset or mediums, and to control whether to broadcast or scan, you must pass additional parameters when you create publications and subscriptions.
>
When actively publishing and subscribing, a "Nearby is in use" notification is presented, informing users that Nearby is active. This notification is only displayed when one or more apps are actively using Nearby, giving users a chance to conserve battery life if Nearby is not needed. It provides users with the following options:
>
+ Navigate to an app to disable Nearby.
+ Force an app to stop using Nearby.
+ Navigate to the **Nearby Settings** screen.
>
You can use [PublishCallback()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/PublishCallback) and [SubscribeCallback()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/SubscribeCallback) to listen for cases when a user forces the app to stop using Nearby. When this happens, the [onExpired()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/SubscribeCallback.html#onExpired()) method is triggered.
>
Because the Nearby Messages APIs have the potential to impact battery life, they should only be used from a foreground activity (with the exception of [BLE background subscribe](https://developers.google.com/nearby/messages/android/get-beacon-messages#subscribe_in_the_background)). Your activity should [publish()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages#publish(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.Message)) or [subscribe()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages.html#subscribe(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.MessageListener)) either in [onStart()](https://developers.google.com/reference/android/app/Activity.html#onStart()) or in response to a user action in a visible activity. Your app should always symetrically [unpublish()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages#unpublish(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.Message)) or [unsubscribe()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages#unsubscribe(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.MessageListener)) in [onStop()](https://developers.google.com/reference/android/app/Activity.html#onStop()). Once there are no active publishes or subscribes, your app should call [GoogleApiClient.disconnect()](https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient.html#disconnect()).
>
The code examples in this guide are based on the [NearbyDevices](https://github.com/googlesamples/android-nearby/tree/master/messages/NearbyDevices) example app.


Nearby Messagesは、近くのデバイス間で小さなデータペイロードを取り交わせるようにするパブリッシュ-サブスクライブ APIです。　デバイスがメッセージをパブリッシュすると、近くのデバイスは、メッセージを受け取ることができます。　このガイドでは、あなたのアプリがNearby Messages APIを使用してメッセージをパブリッシュし、そしてメッセージをサブスクライブするために実装する必要があるすべての機能を紹介します。

近くのデバイスのセットは、Bluetoothと超音波を使った小さなトークンの取り交わしによって決定されます。　デバイスが近くのデバイスからのトークンを検出すると、そのトークンを検証し、アプリの現在のサブスクリプションセットに配信する何らかのメッセージがあるかチェックするため、そのトークンをNearby Messagesサーバーに送信します。

アプリはデバイスの検出に使われる導体のセットと、導体がトークンのブロードキャストやトークンのスキャンに使われるかどうかを制御できます。　デフォルトでは、ブロードキャストとスキャンはすべての導体で行われます。　導体のすべてまたは一部で検出を行うため、またブロードキャストまたはスキャンするかどうかを制御するために、あなたがパブリケーションとサブスクリプションを作成するとき、追加パラメータを渡す必要があります。

パブリッシュやサブスクライブしているとき、Nearbyが稼働していることをユーザーに知らせるため"Nearby使用中"の通知が表示されます。　この通知は一つ以上のアプリがNearbyを使用しているときのみ表示されます。　そしてNearbyが不要な時にユーザーがバッテリを節約する機会を与えます。　それは、次のオプションをユーザーに提供します：

+ Nearbyを無効にするためアプリに移動する。
+ Nearbyの使用を停止するようアプリに強制する。
+ **Nearby設定画面**に移動する。

ユーザーがNearbyの使用を停止するようアプリに強制したケースを受け取るため、 [PublishCallback()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/PublishCallback) と [SubscribeCallback()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/SubscribeCallback) が使えます。　これが発生した時は[onExpired()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/SubscribeCallback.html#onExpired())メソッドが呼ばれます。

Nearby Messages APIはバッテリ寿命に影響を与える可能性があるので、([BLEのバックグラウンド サブスクライブ](https://developers.google.com/nearby/messages/android/get-beacon-messages#subscribe_in_the_background)を除き)フォアグラウンドのactivityからのみ使われるべきです。　あなたのactivityは[publish()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages#publish(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.Message))や[subscribe()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages.html#subscribe(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.MessageListener))を、[onStart()](https://developers.google.com/reference/android/app/Activity.html#onStart())または前面に見えているactivityに対するユーザー操作への応答として行うべきです。　あなたのアプリは[unpublish()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages#unpublish(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.Message))や[unsubscribe()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages#unsubscribe(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.MessageListener))を[onStop()](https://developers.google.com/reference/android/app/Activity.html#onStop())で行うべきです。　アクティブなパブリッシュやサブスクライブが無くなったら、あなたのアプリは[GoogleApiClient.disconnect()](https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient.html#disconnect())を呼ぶ必要があります。

このガイドのコード例は、[NearbyDevices](https://github.com/googlesamples/android-nearby/tree/master/messages/NearbyDevices)サンプルアプリに基づいています。


## Anatomy of a request
>
When making a request to publish a message, or to subscribe to messages from nearby devices, your app should do the following:
>
1. Ensure that the Google API Client is connected.
1. Call the appropriate method (`publish()`, `subscribe()`, `unpublish()`, `unsubscribe()`), using a result callback to handle the result code. In the case of subscriptions, also use a `MessageListener` to handle any messages that are received when subscribing.
1. Set a flag to track the method that has been called (`publish()`, `subscribe()`, `unpublish()`, `unsubscribe()`). If a request fails for any reason, it goes away and must be re-initiated by the app. Your app can use this flag to resume any outstanding requests in the event of an error.
1. Handle errors in the result callback. For example, if an error with the status code `APP_NOT_OPTED_IN` is received, the error handler calls `startResolutionForResult` to prompt the user for their consent.
1. After handling any error, use `onActivityResult` to re-initiate the original request. If consent was not granted at the time of the original publish or subscribe request, you must re-call publish and/or subscribe in `onActivityResult` after getting user consent. The original request does not go through after consent is granted.
1. Upon ending the activity stop all publish and subscribe tasks in `onStop()`.

メッセージのパブリッシュや近くのデバイスからのメッセージのサブスクライブを行うときは、次のことを行う必要があります：

1. Google API Clientに接続していることを確認します。

1. 応答コードを受け取るためコールバックを使用して、適切なメソッド(`publish()`, `subscribe()`, `unpublish()`, `unsubscribe()`)を呼び出します。　またサブスクリプションではメッセージ受信を処理するために`MessageListener`も使用します。

1. 呼び出されたメソッド(`publish()`, `subscribe()`, `unpublish()`, `unsubscribe()`)を追跡するためにフラグを設定します。　何らかの理由でリクエストが失敗した場合、フラグは消え、アプリによって再開される必要があります。　エラーイベントが発生した際に、アプリは未処理のリクエストを再開するためこのフラグを使用することが出来ます。

1. コールバックに含まれるエラーに対応します。　例えば、`APP_NOT_OPTED_IN`というステータスコードを受信した場合、エラーハンドラはユーザーに承諾を促す`startResolutionForResult`を呼び出します。

1. すべてのエラーを処理した後、元々のリクエストを再開するために`onActivityResult`を使用します。　元々のパブリッシュまたはサブスクライブ時に承諾されていなかった場合、ユーザーの承諾を得た後に`onActivityResult`でパブリッシュやサブスクライブを再呼出する必要があります。　承諾が得られた後でも、元々のリクエストは継続されません。

1. activity終了時には、`onStop()`で全てのパブリッシュとサブスクライブを停止します。

## Publish a message
>
To publish a message, call [Nearby.Messages.publish()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages#publish(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.Message)) passing your message byte array. Message size should be kept to 3KB or less to maintain good performance. This service is not meant for exchanging larger objects such as photos and videos.
>
Your app's implementation for publishing should do the following:
>
+ Check for a connection to the Google API Client, and connect the app if it is not already connected.
+ Use [PublishOptions.Builder()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/PublishOptions.Builder) to set the [PublishOptions](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/PublishOptions), calling [setCallback()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/PublishOptions.Builder.html#setCallback(com.google.android.gms.nearby.messages.PublishCallback)) to set a callback which is triggered when the publish task ends.
+ Optionally, call [setStrategy()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/PublishOptions.Builder.html#setStrategy(com.google.android.gms.nearby.messages.Strategy)) to set the [strategy](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Strategy) to use. If this is not explicitly set, default strategy values will be used.
+ Call [publish()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages#publish(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.Message)), setting a [ResultCallback](https://developers.google.com/android/reference/com/google/android/gms/common/api/ResultCallback) with an error handler. The primary job of this handler is to detect whether the user has provided consent to use Nearby, and call the appropriate method to display a consent prompt for the user. You can also use this handler to deal with other error conditions that may arise.
>
The following example demonstrates calling `publish()` to send a small text message:
>
```java
private void publish() {
    Log.i(TAG, "Trying to publish.");
    // Set a simple message payload.
    String strMsg = "This is NearbyPubSub.";
    mDeviceInfoMessage = new Message(strMsg.getBytes());
    // Cannot proceed without a connected GoogleApiClient.
    // Reconnect and execute the pending task in onConnected().
    if (!mGoogleApiClient.isConnected()) {
        if (!mGoogleApiClient.isConnecting()) {
            mGoogleApiClient.connect();
        }
    } else {
        PublishOptions options = new PublishOptions.Builder()
                .setCallback(new PublishCallback() {
                    @Override
                    public void onExpired() {
                        Log.i(TAG, "No longer publishing.");
                    }
                }).build();
        Nearby.Messages.publish(mGoogleApiClient, mDeviceInfoMessage, options)
                .setResultCallback(new ResultCallback<Status>() {
                    @Override
                    public void onResult(Status status) {
                        if (status.isSuccess()) {
                            Log.i(TAG, "Published successfully.");
                        } else {
                            Log.i(TAG, "Could not publish.");
                            // Check whether consent was given;
                            // if not, prompt the user for consent.
                            handleUnsuccessfulNearbyResult(status);
                        }
                    }
                });
    }
}
```

メッセージをパブリッシュするには、メッセージをバイト配列にして渡して[Nearby.Messages.publish()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages#publish(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.Message))を呼び出します。　良いパフォーマンスを維持するため、メッセージのサイズは3KB以下にするべきです。　このサービスは、写真や動画などの大きなオブジェクトを取り交わすためのものではありません。

パブリッシュを実装するアプリは次のことを行う必要があります：

+ Google API Clientへの接続を確認し、接続されていない場合は接続します。
+ [PublishOptions](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/PublishOptions)を設定するため[PublishOptions.Builder()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/PublishOptions.Builder)を使用します。そしてパブリッシュが終わった時に発生するコールバックを設定するため[setCallback()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/PublishOptions.Builder.html#setCallback(com.google.android.gms.nearby.messages.PublishCallback))を呼びます。

+ オプションで[strategy](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Strategy)を設定するため[setStrategy()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/PublishOptions.Builder.html#setStrategy(com.google.android.gms.nearby.messages.Strategy))を呼びます。　明示的に設定されない場合、デフォルトのstrategyが使用されます。

+ [publish()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages#publish(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.Message))を呼び出し、エラーハンドラと[ResultCallback](https://developers.google.com/android/reference/com/google/android/gms/common/api/ResultCallback)を設定します。　このハンドラの主な仕事はNearbyの使用を承諾しているかどうかを検出し、ユーザーに承諾を促す表示を行うため適切なメソッドを呼び出すことです。　また、発生しうる他のエラーに対処するためにも、このハンドラを使用することができます。

次の例は、小さなテキストメッセージを送信するための`publish()`の呼出を示します。

```java
private void publish() {
    Log.i(TAG, "Trying to publish.");
    // Set a simple message payload.
    String strMsg = "This is NearbyPubSub.";
    mDeviceInfoMessage = new Message(strMsg.getBytes());
    // Cannot proceed without a connected GoogleApiClient.
    // Reconnect and execute the pending task in onConnected().
    if (!mGoogleApiClient.isConnected()) {
        if (!mGoogleApiClient.isConnecting()) {
            mGoogleApiClient.connect();
        }
    } else {
        PublishOptions options = new PublishOptions.Builder()
                .setCallback(new PublishCallback() {
                    @Override
                    public void onExpired() {
                        Log.i(TAG, "No longer publishing.");
                    }
                }).build();
        Nearby.Messages.publish(mGoogleApiClient, mDeviceInfoMessage, options)
                .setResultCallback(new ResultCallback<Status>() {
                    @Override
                    public void onResult(Status status) {
                        if (status.isSuccess()) {
                            Log.i(TAG, "Published successfully.");
                        } else {
                            Log.i(TAG, "Could not publish.");
                            // Check whether consent was given;
                            // if not, prompt the user for consent.
                            handleUnsuccessfulNearbyResult(status);
                        }
                    }
                });
    }
}
```

## Unpublish a message
>
To unpublish a message, call [unpublish()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages.html#unpublish(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.Message)). At minimum your app should call unpublish in its [onStop()](https://developers.google.com/reference/android/app/Activity.html#onStop()) method.
>
Your app's implementation for unpublishing should do the following:
>
+ Call [unpublish()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages.html#unpublish(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.Message)) with the same [Message](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Message) object that was used to publish (`mDeviceInfoMessage` in this example).
>
The following code example shows calling `unpublish()`:
>
```java
private void unpublish() {
    Log.i(TAG, "Trying to unpublish.");
    Nearby.Messages.unpublish(mGoogleApiClient, mDeviceInfoMessage);
}
```

メッセージのパブリッシュを止めるため、[unpublish()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages.html#unpublish(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.Message))を呼び出します。　最低でもあなたのアプリは、[onStop()](https://developers.google.com/reference/android/app/Activity.html#onStop())でunpublishを呼び出すべきです。

パブリッシュを止める実装は、次のことを行う必要があります。

+ publishで使用したのと同じ[Message](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Message)オブジェクトで[unpublish()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages.html#unpublish(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.Message))を呼び出します。（この例では`mDeviceInfoMessage`）

次のコードの例は、`unpublish()`の呼出を示します。

```java
private void unpublish() {
    Log.i(TAG, "Trying to unpublish.");
    Nearby.Messages.unpublish(mGoogleApiClient, mDeviceInfoMessage);
}
```

## Subscribe to messages
>
To subscribe to messages from other devices, call [Nearby.Messages.subscribe()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages#subscribe(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.MessageListener)).
>
Your app's implementation for subscribing should do the following:
>
+ Check for a connection to the Google API Client, and connect the app if it is not already connected.
+ Use [SubscribeOptions.Builder()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/SubscribeOptions.Builder) to set the [SubscribeOptions](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/SubscribeOptions), calling [setStrategy()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/PublishOptions.Builder.html#setStrategy(com.google.android.gms.nearby.messages.Strategy)) to set the subscribe strategy, and [setCallback()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/PublishOptions.Builder.html#setCallback(com.google.android.gms.nearby.messages.PublishCallback)) to set a callback which is triggered when the subscribe task ends.
+ Call [subscribe()](https://developers.google.com/nearby/messages/android/(/android/reference/com/google/android/gms/nearby/messages/Messages#subscribe(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.MessageListener))), setting a [ResultCallback](https://developers.google.com/android/reference/com/google/android/gms/common/api/ResultCallback) with an error handler. The primary job of this handler is to detect whether the user has provided consent to use Nearby, and call the appropriate method to display a consent prompt for the user. You can also use this handler to deal with other error conditions that may arise.
+ Create a [MessageListener](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/MessageListener) instance to handle receiving subscribed messages. In this example, the `MessageListener` instance is defined in the [onCreateView()](https://developers.google.com/reference/android/app/Fragment.html#onCreateView(android.view.LayoutInflater,%20android.view.ViewGroup,%20android.os.Bundle)) method for the Fragment.
>
The following example demonstrates subscribing to messages:
>
```java
// Subscribe to receive messages.
private void subscribe() {
    Log.i(TAG, "Trying to subscribe.");
    // Cannot proceed without a connected GoogleApiClient.
    // Reconnect and execute the pending task in onConnected().
    if (!mGoogleApiClient.isConnected()) {
        if (!mGoogleApiClient.isConnecting()) {
            mGoogleApiClient.connect();
        }
    } else {
        SubscribeOptions options = new SubscribeOptions.Builder()
                .setCallback(new SubscribeCallback() {
                    @Override
                    public void onExpired() {
                        Log.i(TAG, "No longer subscribing.");
                    }
                }).build();
        Nearby.Messages.subscribe(mGoogleApiClient, mMessageListener, options)
                .setResultCallback(new ResultCallback<Status>() {
                    @Override
                    public void onResult(Status status) {
                        if (status.isSuccess()) {
                            Log.i(TAG, "Subscribed successfully.");
                        } else {
                            Log.i(TAG, "Could not subscribe.");
                            // Check whether consent was given;
                            // if not, prompt the user for consent.
                            handleUnsuccessfulNearbyResult(status);
                        }
                    }
                });
    }
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view =  inflater.inflate(R.layout.fragment_main, container, false);
    // Create a new message listener.
    mMessageListener = new MessageListener() {
        @Override
        public void onFound(final Message message) {
            final String nearbyMessageString = new String(message.getContent());
            // Do something with the message string.
            Log.i(TAG, nearbyMessageString);
        }
        // Called when a message is no longer detectable nearby.
        public void onLost(final Message message) {
            final String nearbyMessageString = new String(message.getContent());
            // Take appropriate action here (update UI, etc.)
        }
    }
    return view;
}
```

他のデバイスからのメッセージをサブスクライブするには、[Nearby.Messages.subscribe()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages#subscribe(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.MessageListener))を呼び出します。

サブスクライブの実装では、次のことを行う必要があります。

+ Google API Clientへの接続を確認し、接続されていない場合は接続します。

+ [SubscribeOptions](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/SubscribeOptions)を設定するため[SubscribeOptions.Builder()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/SubscribeOptions.Builder)を使用し、サブスクライブのstrategyを設定するため[setStrategy()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/PublishOptions.Builder.html#setStrategy(com.google.android.gms.nearby.messages.Strategy))を呼び出し、サブスクライブが終わったときに発生するコールバックを設定するため、[setCallback()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/PublishOptions.Builder.html#setCallback(com.google.android.gms.nearby.messages.PublishCallback))を呼び出します。

+ [subscribe()](https://developers.google.com/nearby/messages/android/\(/android/reference/com/google/android/gms/nearby/messages/Messages#subscribe(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.MessageListener) ) を呼び出し、エラーハンドラと[ResultCallback](https://developers.google.com/android/reference/com/google/android/gms/common/api/ResultCallback)を設定します。　このハンドラの主な仕事はNearbyの使用を承諾しているかどうかを検出し、ユーザーに承諾を促す表示を行うため適切なメソッドを呼び出すことです。　また発生しうる他のエラーに対処するためにも、このハンドラを使用することができます。

+ サブスクライブされたメッセージの受信を処理するため、[MessageListener](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/MessageListener)のインスタンスを作成します。　この例では、`MessageListener`のインスタンスはFragmentの[onCreateView()](https://developers.google.com/reference/android/app/Fragment.html#onCreateView(android.view.LayoutInflater,%20android.view.ViewGroup,%20android.os.Bundle))メソッドで定義されています。

次の例は、メッセージのサブスクライブを示します：

```java
// Subscribe to receive messages.
private void subscribe() {
    Log.i(TAG, "Trying to subscribe.");
    // Cannot proceed without a connected GoogleApiClient.
    // Reconnect and execute the pending task in onConnected().
    if (!mGoogleApiClient.isConnected()) {
        if (!mGoogleApiClient.isConnecting()) {
            mGoogleApiClient.connect();
        }
    } else {
        SubscribeOptions options = new SubscribeOptions.Builder()
                .setCallback(new SubscribeCallback() {
                    @Override
                    public void onExpired() {
                        Log.i(TAG, "No longer subscribing.");
                    }
                }).build();
        Nearby.Messages.subscribe(mGoogleApiClient, mMessageListener, options)
                .setResultCallback(new ResultCallback<Status>() {
                    @Override
                    public void onResult(Status status) {
                        if (status.isSuccess()) {
                            Log.i(TAG, "Subscribed successfully.");
                        } else {
                            Log.i(TAG, "Could not subscribe.");
                            // Check whether consent was given;
                            // if not, prompt the user for consent.
                            handleUnsuccessfulNearbyResult(status);
                        }
                    }
                });
    }
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view =  inflater.inflate(R.layout.fragment_main, container, false);
    // Create a new message listener.
    mMessageListener = new MessageListener() {
        @Override
        public void onFound(final Message message) {
            final String nearbyMessageString = new String(message.getContent());
            // Do something with the message string.
            Log.i(TAG, nearbyMessageString);
        }
        // Called when a message is no longer detectable nearby.
        public void onLost(final Message message) {
            final String nearbyMessageString = new String(message.getContent());
            // Take appropriate action here (update UI, etc.)
        }
    }
    return view;
}
```

## Unsubscribe
>
To unsubscribe and stop receiving device messages, call [Nearby.Messages.unsubscribe()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages.html#unsubscribe(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.MessageListener)).
>
Your app's implementation for unsubscribing should do the following:
>
+ Call [unsubscribe()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages.html#unsubscribe(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.MessageListener)) with the same [MessageListener](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/MessageListener) object that was used to subscribe (`mMessageListener` in this example).
>
The following code example demonstrates unsubscribing:
>
```java
private void unsubscribe() {
    Log.i(TAG, "Trying to unsubscribe.");
    Nearby.Messages.unsubscribe(mGoogleApiClient, mMessageListener);
}
```

サブスクライブを止めて、デバイスのメッセージ受信を止めるためには、[Nearby.Messages.unsubscribe()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages.html#unsubscribe(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.MessageListener))を呼び出します。

サブスクライブを止める実装では、次のことを行う必要があります：

+ サブスクライブに使用したのと同じ[MessageListener](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/MessageListener)オブジェクトで[unsubscribe()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages.html#unsubscribe(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.nearby.messages.MessageListener))を呼び出します。 （この例では`mMessageListener`）

次のコードの例は、サブスクライブの停止を示します：

```java
private void unsubscribe() {
    Log.i(TAG, "Trying to unsubscribe.");
    Nearby.Messages.unsubscribe(mGoogleApiClient, mMessageListener);
}
```

## Implement the runtime consent flow
>
The Nearby Messages API requires user consent. Prior to making any requests, your app must check to see whether the user has consented, and present them with a consent dialog if they have not. To implement the runtime consent flow in your app, you can either:
>
+ Attach a result callback to `publish()` and `subscribe()` calls.
+ Use [Nearby.Messages.getPermissionStatus()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages.html#getPermissionStatus(com.google.android.gms.common.api.GoogleApiClient)), to check for consent prior to calling `publish()` or `subscribe()`.
>
### Implement a result callback
>
In the result callback, call [status.getStatusCode()](https://developers.google.com/android/reference/com/google/android/gms/common/api/Status.html#getStatusCode()) to check the error status code. If the status code [APP_NOT_OPTED_IN](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/NearbyMessagesStatusCodes.html#APP_NOT_OPTED_IN) is received, display the consent dialog by calling [status.startResolutionForResult()](https://developers.google.com/android/reference/com/google/android/gms/common/api/Status.html#startResolutionForResult(android.app.Activity,%20int)), and use `onActivityResult()` to re-initiate any outstanding subscription or publication requests.
>
The following example shows a simple result callback that checks to see whether the user has provided consent; if the user has not consented, [status.startResolutionForResult()](https://developers.google.com/android/reference/com/google/android/gms/common/api/Status.html#startResolutionForResult(android.app.Activity,%20int)) is called to prompt the user to opt-in to Nearby Messages. In this example, the boolean `mResolvingError` is used to avoid triggering multiple consent prompts.
>
```java
private void handleUnsuccessfulNearbyResult(Status status) {
    Log.i(TAG, "Processing error, status = " + status);
    if (mResolvingError) {
        // Already attempting to resolve an error.
        return;
    } else if (status.hasResolution()) {
        try {
            mResolvingError = true;
            status.startResolutionForResult(getActivity(),
                    Constants.REQUEST_RESOLVE_ERROR);
        } catch (IntentSender.SendIntentException e) {
            mResolvingError = false;
            Log.i(TAG, "Failed to resolve error status.", e);
        }
    } else {
        if (status.getStatusCode() == CommonStatusCodes.NETWORK_ERROR) {
            Toast.makeText(getActivity().getApplicationContext(),
                    "No connectivity, cannot proceed. Fix in 'Settings' and try again.",
                    Toast.LENGTH_LONG).show();
        } else {
            // To keep things simple, pop a toast for all other error messages.
            Toast.makeText(getActivity().getApplicationContext(), "Unsuccessful: " +
                    status.getStatusMessage(), Toast.LENGTH_LONG).show();
        }
    }
}
```
>
You can also use this handler to handle any other [NearbyMessageStatusCodes](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/NearbyMessagesStatusCodes) resulting from the operation, or other status codes such as [CommonStatusCodes.NETWORK_ERROR](https://developers.google.com/android/reference/com/google/android/gms/common/api/CommonStatusCodes#NETWORK_ERROR).
### Re-initiate outstanding requests
>
The following example shows an [onActivityResult()](https://developers.google.com/reference/android/app/Activity.html#onActivityResult(int,%20int,%20android.content.Intent)), which is called after the user has responded to the opt-in dialog. If the user consents, any pending subscription or publication tasks are executed (in this case, a method called `executePendingTasks()` is called).
>
```java
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == Constants.REQUEST_RESOLVE_ERROR) {
        // User was presented with the Nearby opt-in dialog and pressed "Allow".
        mResolvingError = false;
        if (resultCode == Activity.RESULT_OK) {
            // Execute the pending subscription and publication tasks here.
            mMainFragment.executePendingTasks();
        } else if (resultCode == Activity.RESULT_CANCELED) {
            // User declined to opt-in. Reset application state here.
        } else {
            Toast.makeText(this, "Failed to resolve error with code " + resultCode,
                    Toast.LENGTH_LONG).show();
        }
    }
```

Nearby Messages APIはユーザーの承諾を必要とします。　何らかのリクエストを行う前に、あなたのアプリはユーザーが承諾済みかどうかチェックし、未承諾なら承諾を促すダイアログを表示する必要があります。　あなたのアプリが実行時に承諾を得るフローは次のいずれかです：

+ `publish()`と`subscribe()`の呼出にコールバックを加える。
+ `publish()`や`subscribe()`の呼出の前に承諾の有無をチェックするため[Nearby.Messages.getPermissionStatus()](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/Messages.html#getPermissionStatus(com.google.android.gms.common.api.GoogleApiClient))を呼び出す。

### コールバックの実装

コールバックを受け取ったら、エラーステータスコードをチェックするため[status.getStatusCode()](https://developers.google.com/android/reference/com/google/android/gms/common/api/Status.html#getStatusCode())を呼び出します。　もしステータスコード[APP_NOT_OPTED_IN](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/NearbyMessagesStatusCodes.html#APP_NOT_OPTED_IN)を受け取った場合、[status.startResolutionForResult()](https://developers.google.com/android/reference/com/google/android/gms/common/api/Status.html#startResolutionForResult(android.app.Activity,%20int))を呼び出し、承諾を促すダイアログを表示します。　そして未処理のサブスクリプションまたはパブリケーションを再開するため`onActivityResult()`を使用します。

次の例はユーザーが承諾を出したかどうかチェックするためのシンプルなコールバックを示します。　ユーザーが承諾を行っていない場合、ユーザーにNearby Messagesへの同意を促すため[status.startResolutionForResult()](https://developers.google.com/android/reference/com/google/android/gms/common/api/Status.html#startResolutionForResult(android.app.Activity,%20int))を呼び出しています。　この例では、ブール値`mResolvingError`は承諾画面が複数出ることを避けるために使用されています。

```java
private void handleUnsuccessfulNearbyResult(Status status) {
    Log.i(TAG, "Processing error, status = " + status);
    if (mResolvingError) {
        // Already attempting to resolve an error.
        return;
    } else if (status.hasResolution()) {
        try {
            mResolvingError = true;
            status.startResolutionForResult(getActivity(),
                    Constants.REQUEST_RESOLVE_ERROR);
        } catch (IntentSender.SendIntentException e) {
            mResolvingError = false;
            Log.i(TAG, "Failed to resolve error status.", e);
        }
    } else {
        if (status.getStatusCode() == CommonStatusCodes.NETWORK_ERROR) {
            Toast.makeText(getActivity().getApplicationContext(),
                    "No connectivity, cannot proceed. Fix in 'Settings' and try again.",
                    Toast.LENGTH_LONG).show();
        } else {
            // To keep things simple, pop a toast for all other error messages.
            Toast.makeText(getActivity().getApplicationContext(), "Unsuccessful: " +
                    status.getStatusMessage(), Toast.LENGTH_LONG).show();
        }
    }
}
```

あなたはまた、他の[NearbyMessageStatusCodes](https://developers.google.com/android/reference/com/google/android/gms/nearby/messages/NearbyMessagesStatusCodes)や[CommonStatusCodes.NETWORK_ERROR](https://developers.google.com/android/reference/com/google/android/gms/common/api/CommonStatusCodes#NETWORK_ERROR)のようなステータスを処理するためにも、このハンドラを使用できます。

### 未処理のリクエストを再開する

次のサンプルはユーザーが同意ダイアログに応じた後に呼ばれる[onActivityResult()](https://developers.google.com/reference/android/app/Activity.html#onActivityResult(int,%20int,%20android.content.Intent))を示します。　ユーザーが承諾した場合、保留中のサブスクリプションやパブリケーションは実行されます。
(この例では`executePendingTasks()`という名前のメソッドが呼ばれます)

```java
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == Constants.REQUEST_RESOLVE_ERROR) {
        // User was presented with the Nearby opt-in dialog and pressed "Allow".
        mResolvingError = false;
        if (resultCode == Activity.RESULT_OK) {
            // Execute the pending subscription and publication tasks here.
            mMainFragment.executePendingTasks();
        } else if (resultCode == Activity.RESULT_CANCELED) {
            // User declined to opt-in. Reset application state here.
        } else {
            Toast.makeText(this, "Failed to resolve error with code " + resultCode,
                    Toast.LENGTH_LONG).show();
        }
    }
```