マイペースなプログラミング日記

DTMやプログラミングにお熱なd-kamiがマイペースに書くブログ

Bluetoothデバイスを探索する

Android 2.0から備わっているというBluetooth用のAPIを使ってみようと思い、通信まで頑張ろうとしたが今日は探索までしかいかなかった。そしてListViewの使い方を俺がわかってない。

とりあえず探索までのながれ

  1. BluetoothAdapterを取得する
  2. BluetoothAdapterが利用可能ならデバイス探索、そうでなければ利用許可をユーザに求める
  3. 利用許可をユーザから貰えたら探索開始
  4. BroadcastReceiverで見つけたデバイスを受け取る

という感じ。Android SDKのサンプルにBluetoothチャットがあるのでそれ見ながら作成した。android.permission.BLUETOOTHandroid.permission.BLUETOOTH_ADMINが必要なpermissionになっている

以下ソースコード

package test.bluetooth;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import android.os.Bundle;

import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.BaseAdapter;
import android.graphics.Color;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothAdapter;

import java.util.List;
import java.util.ArrayList;
import java.util.Set;

public class BluetoothActivity extends Activity {
    private static final int REQUEST_ENABLE_BLUETOOTH = 1;
    
    private BluetoothAdapter adapter;
    private BroadcastReceiver receiver;
    private ListView listView;
    private DeviceList deviceList;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        listView = new ListView(this);
        deviceList = new DeviceList(this);

        listView.setAdapter(deviceList);
        listView.setBackgroundColor(Color.WHITE);
        
        if(createAdapter()){
            //デバイス探索用のBroadcastReceiverの準備
            setReceiver();
            
            //レシーバで受け取るメッセージの設定
            IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
            registerReceiver(receiver, filter);
            
            filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
            registerReceiver(receiver, filter);
            
            bluetoothEnable();
        }
        
        setContentView(listView);
    }

    //アダプタの作成。成功したらtrueを、失敗したらfalseを返す
    private boolean  createAdapter(){
        adapter = BluetoothAdapter.getDefaultAdapter();
        
        if(adapter == null){
            return false;
        }
        
        return true;
    }
    
    private void bluetoothEnable(){
        if(adapter.isEnabled()){
            //Bluetoothが利用可能な状態ならデバイスの探索開始
            doDiscovery();
        }else{
            //Bluetoothの利用許可を求めるダイアログ表示。結果はonActibityResultで受け取る
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, BluetoothActivity.REQUEST_ENABLE_BLUETOOTH);
        }
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data){
        if(requestCode == BluetoothActivity.REQUEST_ENABLE_BLUETOOTH){
            if(resultCode == Activity.RESULT_OK){
                //Bluetoothの仕様許可が来たらデバイスの探索開始
                doDiscovery();
            }else{
                error("Bluetoothを利用出来ません");
            }
        }
    }

    //デバイスを探索を始める。結果はBroadcastReceiverで受け取る
    private void doDiscovery(){
        if(adapter.isDiscovering()){
            adapter.cancelDiscovery();
        }
        
        adapter.startDiscovery();
    }
    
    //
    private void setReceiver(){
        receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();

                //デバイスを見つけたらアダプタに名前とアドレスを追加
                if(BluetoothDevice.ACTION_FOUND.equals(action)) {
                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                    if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
                        deviceList.addDeviceInfo(device.getName(), device.getAddress());
                        listView.invalidateViews();
                    }
                }else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                    //デバイスを見つけられなければメッセージを表示
                    if(deviceList.getCount() == 0){
                        deviceList.addDeviceInfo("Not Found Device", "");
                    }
                }
            }
        };
    }
    
    //デバイスのリストを格納するアダプター
    private static class DeviceList extends BaseAdapter{
        private Context context;
        private List<DeviceInfo> infoList;
        
        private DeviceList(Context context){
            this.context = context;
            infoList = new ArrayList<DeviceInfo>();
        }
        
        public void addDeviceInfo(String name, String address){
            infoList.add(new DeviceInfo(name, address));
        }
        
        @Override
        public int getCount(){
            return infoList.size();
        }
        
        @Override
        public Object getItem(int position){
            return infoList.get(position);
        }
        
        @Override
        public long getItemId(int position){
            return position;
        }
        
        @Override
        public View getView(int position, View convertView, ViewGroup parent){
            //デバイスの名前を取得してTextViewで表示
            DeviceInfo info = infoList.get(position);
            TextView deviceView = new TextView(context);
            deviceView.setText(info.getName());
            deviceView.setTextSize(16f);
            
            return deviceView;
        }
        
        //デバイスの名前とアドレスを持つクラス
        private static class DeviceInfo{
            private final String name;
            private final String address;
            
            private DeviceInfo(String name, String address){
                this.name = name;
                this.address = address;
            }
            
            private String getName(){
                return name;
            }
            
            private String getAddress(){
                return address;
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        // デバイスの探索を止める
        if (adapter != null) {
            adapter.cancelDiscovery();
        }

        // ブロードキャストのレシーバを外す
        this.unregisterReceiver(receiver);
    }
    
    //エラーメッセージをアラートで表示
    private void error(String msg){
        AlertDialog.Builder builder = new AlertDialog.Builder (this);
        builder.setTitle("エラー");
        builder.setMessage(msg);
        builder.setCancelable(true);
        
        AlertDialog dialog = builder.create();
        dialog.show();

    }
}