忍者ブログ

Azukish

消えゆく世界と流れる未来に最後の灯を since 2006/4/3

2016/10/08

【備忘録】周りのBluetoothを検索するプログラムを書いてみる。



AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.example.azuki.myapplication">

  <!--下記2行Bluetoothのために必要-->
  <uses-permission android:name="android.permission.BLUETOOTH" />
  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
  <application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
  </application>

</manifest>

ぶっちゃけuses-permissionな行を2行追加するだけ。
これが無いとBluetoothにアクセスする権利が得られない。



activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.azuki.myapplication.MainActivity">

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true" />
</RelativeLayout>

idの付いたListViewさえあればどんなでもおkかと思う。



MainActivity.java
package com.example.azuki.myapplication;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.content.IntentFilter;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import static android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_FINISHED;
import static android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_STARTED;
import static android.bluetooth.BluetoothDevice.ACTION_FOUND;
import static android.bluetooth.BluetoothDevice.ACTION_NAME_CHANGED;
import static android.bluetooth.BluetoothDevice.EXTRA_DEVICE;

public class MainActivity extends AppCompatActivity {
  public static final int ACTION_REQUEST_ENABLE_BLUETOOTH = 10;
  public ListView listView;
  public ArrayAdapter<String> adapter;
  public BluetoothAdapter bt;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    listView = (ListView) findViewById(R.id.listView);
    adapter = new ArrayAdapter<String>(getApplicationContext(), R.layout.activity_main_text_listview);

    bt = BluetoothAdapter.getDefaultAdapter();

    if (!bt.isEnabled()) {
      // もしもBluetoothがオフになっていたら、オンにするように促すダイアログを表示
      // ユーザの操作後onActivityResult()が呼ばれる
      startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), ACTION_REQUEST_ENABLE_BLUETOOTH);
    } else
      searchDevice();
  }

  private void searchDevice() {
    // ブロードキャストを受信するにあたって、どんなものが受信したいか決めておく
    IntentFilter filter = new IntentFilter();
    filter.addAction(ACTION_DISCOVERY_STARTED);   // 検索開始
    filter.addAction(ACTION_FOUND);               // 何か見つかった
    filter.addAction(ACTION_NAME_CHANGED);        // デバイス名が変わった
    filter.addAction(ACTION_DISCOVERY_FINISHED);  // 検索が終わった
    registerReceiver(DeviceFoundReceiver, filter);
    bt.startDiscovery();
  }

  private BroadcastReceiver DeviceFoundReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
      String action = intent.getAction();
      BluetoothDevice foundDevice;
      if (action.equals(null)) {  // ぬるぽ対策
        return;
      } else {
        switch (action) {
          case ACTION_DISCOVERY_STARTED:
            Log.d("a", "start");
            break;
          case ACTION_FOUND:
            foundDevice = intent.getParcelableExtra(EXTRA_DEVICE);
            Log.d("a", foundDevice.getName() + " " + foundDevice.getAddress());
            adapter.add(foundDevice.getName());
            listView.setAdapter(adapter);
            break;
          case ACTION_DISCOVERY_FINISHED:
            Log.d("a","finished");
          default:
            break;
        }
      }
    }
  };

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    // Bluetoothをオンにするように促すダイアログ
    if (requestCode == ACTION_REQUEST_ENABLE_BLUETOOTH) {
      if (resultCode == Activity.RESULT_OK) {
        Log.d("a", "Bluetooth on");
        searchDevice();
      } else {
        Log.d("a", "Bluetooth cannot be on. Abort.");
        finish();
      }
    }
  }
}

ここがメインの部分。
まずonCreate()が呼ばれて、ここで初期化的な処理が入る。
(Bluetoothがオフならば)Bluetoothをオンにするようなダイアログを表示する。
→ユーザがオンにするかオフのままにするかを選択することで、onActivityResult()が呼ばれる。
→Bluetoothがオフのままなら死ぬ。
無事Bluetoothがオンになったら、searchDevice()を呼び、周りのBluetoothデバイスを検索するような処理が始まる(詳しくは知らない)
周りのBluetoothのデバイスが見つかったらDeviceFoundReceiverが呼ばれ、デバイスをListViewに表示して終了。



activity_main_text_listview.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textColor="#555"
    android:text="aaa"
    android:padding="20dp"
    />

もはやオマケの部分。
何故かデフォルトだとListViewのアイテムの色がめちゃくちゃ淡かったので追加。
ArrayAdapterに設定した文字列が、ここで指定したTextViewに表示されて、activity_main.xmlのListViewに追加されていく。



こんな感じ。かなり備忘録的に作ったので、抜かってるところがあるかも。とりあえず動きました。
以下、実行時のConsole(関係のあるとこだけ):
D/a: start
D/a: localhost.localdomain 00:00:00:00:00:00
D/a: RNA0601254 00:00:00:00:00:00
D/a: finished
プライバシー保護()のため、見つかったデバイスのアドレスは全部ゼロにしてある。
本来的には0からFまでの文字の羅列になるはず。

プロジェクトの中のファイル構成はこんな感じ:

2016/10/9追記:
LinuxでBluetoothなデバイスを発見可能な状態かつBluetooth通信受付状態にするには以下を実行する。ただしセキュリティ的には良くないので必要最低限にすること。
# hciconfig hci0 piscan
# sdptool add --channel=22 SP
hci0の部分は後ろに何も付けずにただhciconfigを実行した時に表示されるものを入力すれば良い。SPPサービスの設定例の大半がなぜチャンネル22を指定するのかは謎。

拍手

コメント













カウンター

カレンダー

03 2017/04 05
S M T W T F S
1
2 3 4 5 6 7
9 10 11 12 13 14 15
16 17 18 19 20 21 22
24 25 26 27 28 29
30

アーカイブ

AD

Azkishはamazon.co.jpを宣伝しリンクすることによって サイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。