質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • Android

    6528questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

  • Arduino

    539questions

    Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

  • Bluetooth

    233questions

    Bluetoothとは短距離の間でデータを交換するための無線通信規格である。固定・モバイル両方のデバイスから、短波の電波送信を行うことで、高いセキュリティをもつパーソナルエリアネットワーク(PAN)を構築する。

ボタンを押すことなくCharacteristicの値を更新・表示したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 388

tmn

score 7

前提・実現したいこと

https://qiita.com/maki02/items/27d5a6f50016097875ae
http://greety.sakura.ne.jp/redo/2013/11/androidblecharacteristicsreadwrite.html
上記のサイトを参考にし、Android端末とGenuino 101をBLEで接続するアプリを作成しています。
上記サイトのソースコードとの変更点は
・onServicesDiscoveredの部分をGenuinoで設定したカスタムUUIDに対応付けさせた
・CharacteristicReadの部分をCharacteristicの値を表示できるようにした
という2点になります。
これにより、アプリ上のボタンを押すことでCharacteristicの値を読み取ることができています。

実現したいことは、BLE接続後Genuinoから送られてきたCharacteristicの値を操作することなく画面上に常時更新・表示することです。
常時表示でなくても何秒かごとに更新される、といった動きでも構いません。
どの部分にどのような変更が必要なのかご教授願います。

該当のソースコード

public class DeviceActivity extends Activity implements View.OnClickListener {
    private static final String TAG = "BLEDevice";
    public static final String EXTRA_BLUETOOTH_DEVICE = "BT_DEVICE";
    private BluetoothAdapter mBTAdapter;
    private BluetoothDevice mDevice;
    private BluetoothGatt mConnGatt;
    private int mStatus;
    private ToggleButton mWriteGenuinoButton;
    private Button mReadGenuinoButton;
    private final BluetoothGattCallback mGattcallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status,
                int newState) {
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                mStatus = newState;
                mConnGatt.discoverServices();
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                mStatus = newState;
                runOnUiThread(new Runnable() {
                    public void run() {
                        mWriteGenuinoButton.setEnabled(false);
                        mReadGenuinoButton.setEnabled(false);
                    };
                });
            }
        };

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            for (BluetoothGattService service : gatt.getServices()) {
                if ((service == null) || (service.getUuid() == null)) {
                    continue;
                }
                if (BleUuid.GENUINO_UUID.equalsIgnoreCase(service.getUuid().toString())){
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mWriteGenuinoButton.setEnabled(true);
                            mReadGenuinoButton.setEnabled(true);
                        };
                    });
                    mWriteGenuinoButton.setTag(service.getCharacteristic((UUID.fromString(BleUuid.WRITE_VALUE))));
                    mReadGenuinoButton.setTag(service.getCharacteristic((UUID.fromString(BleUuid.READ_VALUE))));
                }
            }
            runOnUiThread(new Runnable() {
                public void run() {
                    setProgressBarIndeterminateVisibility(false);
                };
            });
        };


        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                if (BleUuid.READ_VALUE.equalsIgnoreCase(characteristic.getUuid().toString())) {
                    final byte[] val = characteristic.getValue();
                    runOnUiThread(new Runnable() {
                        public void run() {
                            mReadGenuinoButton.setText(getString(R.string.ble_read)+":"+val[0]);
                            setProgressBarIndeterminateVisibility(false);
                        };
                    });
                }
            }
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic, int status) {
            runOnUiThread(new Runnable() {
                public void run() {
                    setProgressBarIndeterminateVisibility(false);
                }
            });
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        setContentView(R.layout.activity_device);
        // state
        mStatus = BluetoothProfile.STATE_DISCONNECTED;
        mWriteGenuinoButton = (ToggleButton) findViewById(R.id.write_genuino_button);
        mWriteGenuinoButton.setOnClickListener(this);
        mReadGenuinoButton = (Button) findViewById(R.id.read_genuino_button);
        mReadGenuinoButton.setOnClickListener(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        init();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mConnGatt != null) {
            if ((mStatus != BluetoothProfile.STATE_DISCONNECTING)
                    && (mStatus != BluetoothProfile.STATE_DISCONNECTED)) {
                mConnGatt.disconnect();
            }
            mConnGatt.close();
            mConnGatt = null;
        }
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.write_genuino_button) {
            byte[] data = (mWriteGenuinoButton.isChecked())? new byte[] { (byte) 0x00} : new byte[] {(byte) 0x01};
            if ((v.getTag() != null) && (v.getTag() instanceof BluetoothGattCharacteristic)) {
                BluetoothGattCharacteristic ch = (BluetoothGattCharacteristic) v.getTag();
                ch.setValue(data);
                if (mConnGatt.writeCharacteristic(ch)) {
                    setProgressBarIndeterminateVisibility(true);
                }
            }
        } else if (v.getId() == R.id.read_genuino_button) {
            if ((v.getTag() != null) && (v.getTag() instanceof BluetoothGattCharacteristic)) {
                BluetoothGattCharacteristic ch = (BluetoothGattCharacteristic) v.getTag();
                if (mConnGatt.readCharacteristic(ch)) {
                    setProgressBarIndeterminateVisibility(true);
                }
            }
        }
    }

    private void init() {
        // BLE check
        if (!BleUtil.isBLESupported(this)) {
            Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT)
                    .show();
            finish();
            return;
        }

        // BT check
        BluetoothManager manager = BleUtil.getManager(this);
        if (manager != null) {
            mBTAdapter = manager.getAdapter();
        }
        if (mBTAdapter == null) {
            Toast.makeText(this, R.string.bt_unavailable, Toast.LENGTH_SHORT)
                    .show();
            finish();
            return;
        }

        // check BluetoothDevice
        if (mDevice == null) {
            mDevice = getBTDeviceExtra();
            if (mDevice == null) {
                finish();
                return;
            }
        }

        mWriteGenuinoButton.setEnabled(false);
        mReadGenuinoButton.setEnabled(false);

        // connect to Gatt
        if ((mConnGatt == null)
                && (mStatus == BluetoothProfile.STATE_DISCONNECTED)) {
            // try to connect
            mConnGatt = mDevice.connectGatt(this, false, mGattcallback);
            mStatus = BluetoothProfile.STATE_CONNECTING;
        } else {
            if (mConnGatt != null) {
                // re-connect and re-discover Services
                mConnGatt.connect();
                mConnGatt.discoverServices();
            } else {
                Log.e(TAG, "state error");
                finish();
                return;
            }
        }
        setProgressBarIndeterminateVisibility(true);
    }

    private BluetoothDevice getBTDeviceExtra() {
        Intent intent = getIntent();
        if (intent == null) {
            return null;
        }

        Bundle extras = intent.getExtras();
        if (extras == null) {
            return null;
        }

        return extras.getParcelable(EXTRA_BLUETOOTH_DEVICE);
    }
}

試したこと

参考にさせていただいたサイトのプログラムのうちDviceActivityに対して変更を加えています。それ以外の部分はUUIDの設定以外は触っていません。
常に実行されているスレッドがあればそこに追加すればいいと思い、Logを出力して常に実行されている処理があるかを確認しようとしましたが、どの部分が常に実行されているか分かっていません。
Genuinoに関してはArduino IDEのスケッチ例にあるCurieBLE⇒Peripheral⇒LEDに少し変更を加えたものを利用しています。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

参考資料の回答のみ致します。

一定時間置きに更新するというのが目的のようなので、タイマーを紹介しておきます。
https://techbooster.org/android/application/934/

Characteristic の Notify(CCCD Write/Characteristic の値変化通知)が有効であるならば、そのイベントが発生したときに変更するのが理想的です。
もし、Notifyが使えるのでしたら、以下を参考にして通知を有効にして、
https://developer.android.com/guide/topics/connectivity/bluetooth-le.html#notification
提示していただいたコードのmGattcallbackのクラス(?)にonCharacteristicChangedを定義して、characteristic == PROPERTY_NOTIFYイベントを拾って、画面更新を行うようにしたほうが良いかと存じます。

※もうご存知かとは思いますが、BLE系のデバッグを助けるnRF ConnectというAndroid アプリがあります。これを使うと、ServiceDiscoveryや対象機器のCharacteristicに対してRead・Write等が容易にできます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/22 16:17

    回答ありがとうございます。
    この質問投降後Notifyというものを知り、AndroidLeGattを改造し常時表示を行おうと考え、新たに質問を投稿させていただきました。
    https://teratail.com/questions/101319
    そちらでも書いたのですが、使い方があっているかどうかがわかりません。
    もしよろしければそちらも参照いただき、回答お願いします。

    アドバイスありがとうございます。nRF Connectについてはすでに使っていますので、また確認のために使っていきますね。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Android

    6528questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

  • Arduino

    539questions

    Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

  • Bluetooth

    233questions

    Bluetoothとは短距離の間でデータを交換するための無線通信規格である。固定・モバイル両方のデバイスから、短波の電波送信を行うことで、高いセキュリティをもつパーソナルエリアネットワーク(PAN)を構築する。