2016年3月23日水曜日

Linkingを利用したアプリの実装方法について



はじめに


Linkingが発表されてからおよそ3か月が経過して、Linkingを利用したいくつかのアプリがプレイストアにアップされています。その中には弊社がリリースした「忘れ物防止」や「迷子防止」、「お天気予報通知」アプリもあります。今回の記事では、Linkingを利用してどのように「忘れ物防止」や「迷子防止」、「お天気予報通知」のアプリが実現されているかの説明を行っていきたいと思います。

弊社からリリースしたアプリと利用している機能は以下の通りです。

大きく分けて、2種類の機能を利用しています。今回はLinkingを利用した「距離変化通知」と「ビーコンの検知」の方法に関して紹介したいと思います。

LinkingのAPI仕様書はこちらからダウンロードすることができます。

※本記事は、Androidアプリに関しての説明を行います。

関連記事

距離変化通知

Linkingを利用して距離の変化通知を受信するには、Linkingアプリからの距離変化通知のブロードキャストレシーバーを準備することで、デバイスとLinkingアプリの距離が変化した通知を受けることができます。また、Linkingアプリにて「近づいた時の通知距離」、「離れた時の通知距離」を設定することで、「一定範囲内に入った」「一定範囲外へ離れた」場合に通知する距離を設定することもできます。


図 距離変化通知

デバイスとLinkingアプリの距離が変化した場合、以下の情報が通知されます。この情報を元にLinkingデバイスとの距離を計測することができます。

※障害物により、正確な距離が通知されない場合があります。



図 距離変更時に通知される情報

それでは、Linkingを利用して実際に距離変化通知の検知を行う方法を説明します。

周辺機器通知対応をマニフェストに宣言

Linkingの機能を利用するには、まずアプリのマニフェストに「周辺機器通知対応」の宣言を行います。
※Linkingアプリから距離変化などの通知が必要なく、アプリからデバイスへ通知を行うのみであれば、以下の宣言を行うことでデバイスへの通知機能が利用可能になります。

<AndroidManifest.xml>
<meta-data
    android:name="com.nttdocomo.android.smartdeviceagent.feature.support" android:value="true" />
マニフェストに宣言を行うことでLinkingアプリにて通知に関する設定を行うことができるようになります。

<Linkingアプリの設定画面>
※Linkingアプリからペアリングしているデバイスを選択することで、以下の画面に遷移します。



図 (左図)Linkingアプリの設定画面、(右図)デバイスへの通知設定画面


距離変化通知の利用をマニフェストに宣言

Linkingの「距離変化通知」を利用するには、マニフェストに距離変化通知の機能を利用する旨を宣言しておきます。

<AndroidManifest.xml>
<meta-data
    android:name="com.nttdocomo.android.smartdeviceagent.feature.notify_distance" android:value="true" />
宣言を行うことで、Linkingアプリにて「近づいた時の通知距離」、「離れた時の通知距離」を設定することが可能になります。

<Linkingアプリの設定画面>
※Linkingアプリからペアリングしているデバイスを選択し、「近づいた時の通知距離」、「離れた時の通知距離」を設定したいアプリを選択すると以下の画面に遷移します。

図 デバイスへの通知設定画面(距離変化通知の利用宣言後)

距離変化通知の受信用ブロードキャストレシーバーの作成

次に、距離変化通知受信用のブロードキャストレシーバーを作成します。Linkingライブラリで提供されている「NotifyRange」クラスを利用することで、距離変化の通知を検知することができるようになります。(Linkingライブラリを利用する場合、距離が変化した情報は「RangeInformation」という名前でSharedPreferencesにデータが保存されています。)

※「NotifyRange」クラスを利用しなくても、独自でブロードキャストレシーバーを作成することでも実現可能です。通知されるブロードキャストは以下の通りです。(サンプルコードはAPI仕様書の「周辺デバイスからデータを受信」の「距離変化通知」での「【外部IFのみ使用した例】」を参照)

  • com.nttdocomo.android.smartdeviceagent.action.RANGE_CHANGE
    • 距離が変化した際に通知される
サンプルコード
距離変化通知を受信して、距離変化の情報をログ出力するサンプルコードです。

<AndroidManifest.xml>
<meta-data
    android:name="com.nttdocomo.android.smartdeviceagent.feature.support" android:value="true" />
<meta-data
    android:name="com.nttdocomo.android.smartdeviceagent.feature.notify_distance" android:value="true" />
<MainActivity.java>
import com.nttdocomo.android.sdaiflib.Define;
import com.nttdocomo.android.sdaiflib.NotifyRange;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "LinkingSample";

    // 距離通知を受信するクラス
    private NotifyRange mNotifyRange;

    // 距離変化通知を受けるインターフェイス
    private NotifyRange.RangeInterface mRangeInterface = new NotifyRange.RangeInterface() {
        @Override
        public void onRangeChange() {

            // 距離変化の情報を取得する
            SharedPreferences preference = getSharedPreferences(Define.RangeInfo, Context.MODE_PRIVATE);
            int range = preference.getInt("RANGE", -1);
            int rangeSetting = preference.getInt("RANGE_SETTING", -1);
            String address = preference.getString("BD_ADDRESS", "");

            if (range == 0) {
                // 接近の検知
                Log.d(TAG, address + " : は一定範囲内にいます。");
            } else if (range == 1) {
                // 離脱の検知
                Log.d(TAG, address + " : は一定範囲外にいます。");
            }

            switch (rangeSetting) {
                case 1: {
                    Log.d(TAG, address + " : との距離は" + "近い");
                    break;
                }
                case 2: {
                    Log.d(TAG, address + " : との距離は" + "やや近い");
                    break;
                }
                case 3: {
                    Log.d(TAG, address + " : との距離は" + "遠い");
                    break;
                }
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 距離変化通知の受信準備
        mNotifyRange = new NotifyRange(this, mRangeInterface);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 距離変更通知の終了処理
        mNotifyRange.release();
    }
}
以上が、Linkingを利用した距離変化通知の検知方法です。

ビーコンの検知

Linkingを利用してビーコンの検知を行うには、Linkingアプリに対してビーコンのスキャン開始をブロードキャストを介して依頼します。Linkingアプリはビーコンスキャンの開始依頼を受信後、ビーコンスキャンの開始を行い、ブロードキャストを介して「ビーコンスキャンの状態通知」と「ビーコンスキャンの結果」を通知します。受信した結果を元に、検出したビーコンの判別、距離の監視を行うことができます。

※ペアリング中のデバイスからはビーコンの通知は受け取れません。



図 ビーコン検知

それでは、Linkingを利用して実際にビーコンの検出を行う方法を説明します。

ビーコン機能の利用をマニフェストに宣言

Linkingのビーコン機能を利用するには、まずアプリのマニフェストにビーコン機能を利用する旨を宣言しておきます。

<AndroidManifest.xml>
<meta-data
    android:name="com.nttdocomo.android.smartdeviceagent.feature.beacon" android:value="true" />
宣言を行うことで、Linkingアプリにて「ビーコンデバイス利用アプリ」として表示されます。

<Linkingアプリの設定画面>
※Linkingアプリから「ビーコンデバイスの利用設定」をONして、「ビーコンデバイス」を選択すると以下の画面に遷移します。


図 Linkingアプリ「ビーコンデバイス利用アプリ」画面

ビーコンスキャン結果受信用ブロードキャストレシーバーの作成

次に、ビーコンのスキャン結果を受信するブロードキャストレシーバーを作成します。Linkingライブラリで提供されている「BeaconReceiverBase」を継承したブロードキャストレシーバーを作成することで、「ビーコンスキャンの状態」と「ビーコンスキャンの結果」を受信することができます。

※「BeaconReceiverBase」を利用しなくても、以下のブロードキャストを受信するブロードキャストレシーバーを作成することでも実現可能です。通知されるブロードキャストは以下の通りです。(サンプルコードはAPI仕様書「ビーコンの受信」の「外部IFのみ使用した例」を参照)

  • com.nttdocomo.android.smartdeviceagent.action.BEACON_SCAN_RESULT
    • 検出されたビーコンのデータが通知される。
  • com.nttdocomo.android.smartdeviceagent.action.BEACON_SCAN_STATE
    • ビーコンスキャン状態が変化した時に通知される。
ビーコンスキャンの開始/停止依頼

ビーコンスキャンの開始と停止はLinkingライブラリの「BeaconScanner」クラスを利用します。スキャン開始の依頼を行うと、以下のビーコンスキャンの状態(BEACON_SCAN_STATE)を受信することができます。

図 ビーコンスキャン結果詳細コード

また、正常にスキャンが実行され、ビーコンが検出された場合、ビーコンスキャンの結果として以下のビーコン情報が取得出来ます。(「BeaconData」クラスにビーコン情報が格納されています。)

  • ベンダ識別子
  • 個別識別子
  • RSSI
  • ビーコンサービスのバージョン
  • 距離種別
  • Txパワー(dBM)
  • 温度
  • 湿度
  • 気圧
  • 電池残量低下(要充電)フラグ
  • 電池残量
  • 押下されたボタン識別子
  • Rawデータ
スキャン開始後は、スキャン停止されるまで定期的にスキャン結果を通知します。スキャン結果で取得できた情報を比較することで、ビーコンの監視を行うことができます。

※「BeaconScanner」クラスを利用しなくても、以下のブロードキャストを利用してLinkingアプリに依頼することも可能です。(サンプルコードはAPI仕様書「ビーコンの受信」の「外部IFのみ使用した例」を参照)

  • 送信元パッケージ名 + ".sda.action.START_BEACON_SCAN"
  • 送信元パッケージ名 + ".sda.action.STOP_BEACON_SCAN"
サンプルコード
ビーコンのスキャン開始/停止を行い、検出したビーコンの情報をログ出力するサンプルコードです。

<AndroidManifest.xml>
<meta-data
    android:name="com.nttdocomo.android.smartdeviceagent.feature.beacon" android:value="true" />

<receiver
    android:name=".MainActivity$MyBeaconReceiverBase"
    android:exported="true" >
    <intent-filter>
        <action android:name="com.nttdocomo.android.smartdeviceagent.action.BEACON_SCAN_RESULT" />
        <action android:name="com.nttdocomo.android.smartdeviceagent.action.BEACON_SCAN_STATE" />
    </intent-filter>
</receiver>
<MainActivity.java>
import com.nttdocomo.android.sdaiflib.BeaconData;
import com.nttdocomo.android.sdaiflib.BeaconReceiverBase;
import com.nttdocomo.android.sdaiflib.BeaconScanner;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "LinkingSample";

    private BeaconScanner mBeaconScanner;
    private MyBeaconReceiverBase mMyBeaconReceiverBase;

    // 以下のブロードキャストを受信するブロードキャストレシーバー
    // com.nttdocomo.android.smartdeviceagent.action.BEACON_SCAN_RESULT
    // com.nttdocomo.android.smartdeviceagent.action.BEACON_SCAN_STATE"
    public static class MyBeaconReceiverBase extends BeaconReceiverBase {

        public MyBeaconReceiverBase() {
        }

        @Override
        protected void onReceiveScanResult(BeaconData beaconData) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis(beaconData.getTimestamp());
            String time = String.format("%02d-%02d %02d:%02d:%02d",
                    calendar.get(Calendar.MONTH) + 1,
                    calendar.get(Calendar.DAY_OF_MONTH),
                    calendar.get(Calendar.HOUR_OF_DAY),
                    calendar.get(Calendar.MINUTE),
                    calendar.get(Calendar.SECOND));
            Log.d(TAG, "ビーコン ID[" + beaconData.getExtraId() + "]"+ " 検出時間:" + time);
            Log.d(TAG, "距離の種別:" + beaconData.getDistance());
        }

        @Override
        protected void onReceiveScanState(int scanState, int detail) {
            if (scanState == 0 && detail == 0) {
                Log.d(TAG, "スキャン実行中");
            } else {
                Log.d(TAG, "スキャン要求に失敗しました : " + detail);
            }
        }
    }

    public void onStartBeaconScan(View view) {
        // サービスIDを指定
        // すべての検出されたビーコンサービスID/データが含まれるビーコン情報を通知
        mBeaconScanner.startScan(new int[] {0} );
    }

    public void onStopBeaconScan(View view) {
        // スキャン停止依頼
        mBeaconScanner.stopScan();
    }

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

        // ビーコンスキャンの準備
        mBeaconScanner = new BeaconScanner(this);
        mMyBeaconReceiverBase = new MyBeaconReceiverBase();
    }
}

以上が、Linkingを利用したビーコンの検知方法です。


さいごに

今回はLinkingを利用した機能の実装方法を紹介しました。いかがでしたでしょうか。
Linkingの機能を利用する際、Linkingライブラリを利用する方法と、独自にブロードキャストレシーバーを作成して実装する方法の選択ができるので、用途に合わせて実装方法を選択していただければと思います。

また、現在Linkingに対応した新しいデバイスの発売が続々と告知されています。アプリとデバイスの組み合わせが充実し、さまざまな新しいサービスが見られるのではないかとわくわくしています。

図 発売予定のデバイスLinking公式サイトを参照)

また、新たな情報があれば更新したいと思います。
140 180 Android , BLE , IoT , Linking , ドコモ

記載されている会社名、および商品名等は、各社の商標または登録商標です。

0 コメント:

コメントを投稿

Related Posts Plugin for WordPress, Blogger...