Beacon検知

「ふぁみここ」を作成する際に、ビーコンの情報を取得しないといけない時にやり方が調べてもよくわからず、先輩に話を聞いたりして作成したので、そのやり方

engineer.recruit-lifestyle.co.jp

こちらのサイトを参考にさせていただきました。

やりたいこと

ボタンを押すとビーコンの検知を開始して、もう一度押すと終了するアプリ。
検知したビーコンの情報はログに出す。

開発環境

MacOS sierra
AndroidStudio 2.2.3
java8

準備

まずプロジェクトを作成します。
プロジェクト名「GetBeacon」
API 21:Android5.0 Lollipop
Empty Activity

ボタン配置

デフォルトで入っているTextVIewを削除して、Buttonを追加します。
自分は、真ん中に配置しました。

<!--省略-->
<Button
    android:text="Button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true"
    android:id="@+id/button" />
<!--省略-->

ボタンを押した時のリスナー用意

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

     Button btn = (Button)findViewById(R.id.button);
     btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

        }
    });
 }

ビーコン検知する

パーミッションを追加

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

をmanifests(app/src/main/AndroidManifest.xml)フォルダ内の<applicationと同じ高さに追加します。
このアプリが動作する端末をBLEが利用可能な端末のみにするには
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
も追加します

ビーコンを検知した時に呼ばれるCallBackを用意

新しくJavaClassを作成して、その名前をIbeaconScanCallBackにします。
このコールバックの中身は後で記述します。

BLE受信開始するためのコードを用意

BluetoothLeScanner mBLEScanner;
IbeaconScanCallback scanCallback;

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

    // Bluetoothの生成(ここは5.0以前も一緒)
    final BluetoothManager bManager = (BluetoothManager)getSystemService(BLUETOOTH_SERVICE);
    final BluetoothAdapter bAdapter = bManager.getAdapter();

    // Bluetoothサポートチェック
    final boolean isBluetoothSupported = bAdapter != null;
    if (!isBluetoothSupported) {
        // 非サポート時の処理を書く
        return;
    }

     // Bluetoothオンかチェック
     if (!bAdapter.isEnabled()) {
         // オフ時の処理を書く
         return;
     }


    mBLEScanner = bAdapter.getBluetoothLeScanner();
    scanCallback = new IbeaconScanCallback();

    Button btn = (Button)findViewById(R.id.button);
    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

         }
     });
}

2つほどエラーが出ていると思いますが今は気にしないでください。

IbeaconScanCallbackの内容を記述していく

public class IbeaconScanCallback extends ScanCallback{
    final String TAG = "Beacon";

    @Override
    public void onScanResult(int callbackType, ScanResult result) {
        super.onScanResult(callbackType, result);
        // スキャン結果が返ってきます
        // このメソッドかonBatchScanResultsのいずれかが呼び出されます。
        // 通常はこちらが呼び出されます。
        //スキャン結果からビーコンの情報を取得する
        BluetoothDevice bDevice = result.getDevice();
        //情報からアドレスをログに出す
        Log.d(TAG, bDevice.getAddress());
    }


    @Override
    public void onScanFailed(int errorCode) {
        super.onScanFailed(errorCode);
        // エラーが発生するとこちらが呼び出されます
        String errorMessage = "";
        switch (errorCode) {
            case SCAN_FAILED_ALREADY_STARTED:
                errorMessage = "既にBLEスキャンを実行中です";
                break;
            case SCAN_FAILED_APPLICATION_REGISTRATION_FAILED:
                errorMessage = "BLEスキャンを開始できませんでした";
                break;
            case SCAN_FAILED_FEATURE_UNSUPPORTED:
                errorMessage = "BLEの検索をサポートしていません。";
                break;
            case SCAN_FAILED_INTERNAL_ERROR:
                errorMessage = "内部エラーが発生しました";
                break;
        }
        Log.d("ERROR", errorMessage);
    }
}

BluetoothScanを開始

スキャンが開始しているかのためにflag変数を用意します。
その後、ボタンのリスナー内にスキャンを開始させるためのコードを記述します。

btn.setOnClickListener(new View.OnClickListener() {
    @Override
     public void onClick(View view) {
         if (flag) {
             //スキャン開始
             mBLEScanner.startScan(scanCallback);
         }
         else {
             //スキャン停止
             mBLEScanner.stopScan(scanCallback);
         }
         flag = !flag;
    }
});

以上でボタンを押したらビーコンの検知を開始、もう一度押すと停止。
これで検知したビーコンのアドレスをログに出すことができたと思います。
詳しい説明等は参考元を見てみてください。
参考元と変わっている部分が多々あるので気をつけてください。

参考元

http://engineer.recruit-lifestyle.co.jp/techblog/2015-01-15-using-ibeacon-on-android5/

mito.

2/23 追記
Githubにて今回説明したアプリのプロジェクトファイルを公開しました。
https://github.com/mitohato/GetBeacon

2/23 追記 ↑のGithubリポジトリにてkotlinで書いた同アプリのプロジェクトを作成・公開しました。

2018/11/9 追記
Android 6.0からはパーミッションに以下のいずれかを追加しないといけなくなりました。
android.permission.ACCESS_COARSE_LOCATION or android.permission.ACCESS_FINE_LOCATION