・Bluetooth が利用可能かチェック
・Bluetooth が有効になっていない場合は有効にするダイアログを表示
・有効になったらペアリング済みの一覧ダイアログを表示
・BLUETOOTH_ADMIN permission がある場合は、一覧ダイアログにデバイス検索開始のボタンを表示
・バックグラウンドでの通信(読み書き)
が入ってます。
・画面回転考慮してません
・デバイス検索中のクルクルをつけてません
(そのうちやる、と、思う、たぶん)
- /**
- * This fragment process Bluetooth connection. Host Activity have to implements
- * BluetoothCallback.
- *
- * @author yanzm
- */
- public class BluetoothFragment extends Fragment {
- public interface BluetoothCallback {
- /**
- * check whether device support Bluetooth.
- *
- * @param isAvailable
- * true if device support Bluetooth.
- */
- public void onCheckAvailability(boolean isAvailable);
- /**
- * called when bluetooth state be changed.
- *
- * @param enabled
- */
- public void onChangeBluetoothState(boolean enabled);
- /**
- * called when try to connect.
- *
- * @param connected
- */
- public void onConnected(boolean connected);
- /**
- * called when connection established
- *
- * @param in
- * @param out
- */
- public void onOpenConnection();
- public void onDataArrived(int size, byte[] buffer);
- }
- public static final String EXTRA_UUID = "uuid";
- public static final int SPP_MODE = 0;
- private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
- private static final int REQUEST_ENABLE_BT = 11;
- private BluetoothCallback mCallback;
- private BluetoothAdapter mBluetoothAdapter;
- private boolean mIsAvailable;
- private boolean mIsEnable;
- private UUID mUuid;
- private ConnectThread mConnectThread;
- private TransmitThread mTransmitThread;
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- if (activity instanceof BluetoothCallback == false) {
- throw new ClassCastException("Activity have to implement BluetoothCallback");
- }
- mCallback = (BluetoothCallback) activity;
- }
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (mConnectThread != null) {
- mConnectThread.cancel();
- mConnectThread = null;
- }
- if (mTransmitThread != null) {
- mTransmitThread.cancel();
- mTransmitThread = null;
- }
- }
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- Bundle args = getArguments();
- int sppMode = args == null ? 0 : args.getInt(EXTRA_UUID, 0);
- switch (sppMode) {
- case 0:
- mUuid = SPP_UUID;
- break;
- default:
- mUuid = SPP_UUID;
- break;
- }
- // 1. Get the BluetoothAdapter
- mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- mIsAvailable = mBluetoothAdapter != null;
- mCallback.onCheckAvailability(mIsAvailable);
- // 2. Enable Bluetooth
- if (mBluetoothAdapter.isEnabled()) {
- mIsEnable = true;
- onEnabled();
- } else {
- mIsEnable = false;
- Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
- startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
- }
- mCallback.onChangeBluetoothState(mIsEnable);
- }
- BroadcastReceiver mStateReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
- if (state == BluetoothAdapter.STATE_ON) {
- mIsEnable = true;
- onEnabled();
- } else {
- mIsEnable = false;
- }
- mCallback.onChangeBluetoothState(mIsEnable);
- }
- };
- @Override
- public void onResume() {
- super.onResume();
- IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
- getActivity().registerReceiver(mStateReceiver, filter);
- }
- @Override
- public void onPause() {
- super.onPause();
- getActivity().unregisterReceiver(mStateReceiver);
- if (mBluetoothAdapter.isDiscovering()) {
- stopDiscovery();
- }
- }
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (requestCode == REQUEST_ENABLE_BT) {
- if (resultCode == Activity.RESULT_OK) {
- mIsEnable = true;
- onEnabled();
- } else {
- mIsEnable = false;
- }
- mCallback.onChangeBluetoothState(mIsEnable);
- }
- }
- private void onEnabled() {
- selectPairedDevice();
- }
- public void selectPairedDevice() {
- // 3. Querying paired devices
- Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
- if (pairedDevices.size() > 0) {
- ArrayList<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>();
- for (BluetoothDevice device : pairedDevices) {
- deviceList.add(device);
- }
- final BluetoothDeviceAdapter adapter = new BluetoothDeviceAdapter(getActivity(), deviceList);
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setTitle("Paired devices");
- builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int position) {
- BluetoothDevice selectedDevice = adapter.getItem(position);
- connectToDevice(selectedDevice);
- }
- });
- builder.setNegativeButton(android.R.string.cancel, null);
- Context context = getActivity();
- PackageManager manager = context.getPackageManager();
- int permission = manager.checkPermission(Manifest.permission.BLUETOOTH_ADMIN, context.getPackageName());
- if (permission == PackageManager.PERMISSION_GRANTED) {
- builder.setPositiveButton("Search for devices", new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- discoveringDevices();
- }
- });
- }
- builder.show();
- }
- }
- BluetoothDeviceAdapter mDiscoveringAdapter;
- BroadcastReceiver mDiscoveringReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- mDiscoveringAdapter.add(device);
- }
- };
- private void discoveringDevices() {
- // 4. discovering devices
- ArrayList<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>();
- mDiscoveringAdapter = new BluetoothDeviceAdapter(getActivity(), deviceList);
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setAdapter(mDiscoveringAdapter, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int position) {
- stopDiscovery();
- BluetoothDevice selectedDevice = mDiscoveringAdapter.getItem(position);
- connectToDevice(selectedDevice);
- }
- });
- builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- stopDiscovery();
- }
- });
- builder.show();
- startDiscovery();
- }
- private void startDiscovery() {
- IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
- getActivity().registerReceiver(mDiscoveringReceiver, filter);
- mBluetoothAdapter.startDiscovery();
- }
- private void stopDiscovery() {
- mBluetoothAdapter.cancelDiscovery();
- getActivity().unregisterReceiver(mDiscoveringReceiver);
- }
- private void connectToDevice(BluetoothDevice device) {
- mConnectThread = new ConnectThread(device);
- mConnectThread.start();
- }
- private class ConnectThread extends Thread {
- private final BluetoothSocket mSocket;
- public ConnectThread(BluetoothDevice device) {
- BluetoothSocket tmp = null;
- try {
- tmp = device.createRfcommSocketToServiceRecord(mUuid);
- } catch (IOException e) {
- }
- mSocket = tmp;
- }
- public void run() {
- if (mBluetoothAdapter.isDiscovering()) {
- mBluetoothAdapter.cancelDiscovery();
- }
- try {
- mSocket.connect();
- Message msg = mHandler.obtainMessage(MESSAGE_CONNECTED, true);
- mHandler.sendMessage(msg);
- } catch (IOException connectException) {
- try {
- mSocket.close();
- } catch (IOException closeException) {
- }
- Message msg = mHandler.obtainMessage(MESSAGE_CONNECTED, false);
- mHandler.sendMessage(msg);
- return;
- }
- manageConnectedSocket(mSocket);
- }
- public void cancel() {
- try {
- mSocket.close();
- } catch (IOException e) {
- }
- }
- }
- private void manageConnectedSocket(BluetoothSocket socket) {
- mTransmitThread = new TransmitThread(socket);
- mTransmitThread.start();
- }
- private static final int MESSAGE_READ = 1;
- private static final int MESSAGE_CONNECTED = 2;
- private static final int MESSAGE_OPEN = 3;
- final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- int what = msg.what;
- switch (what) {
- case MESSAGE_READ:
- int length = msg.arg1;
- byte[] buffer = (byte[]) msg.obj;
- mCallback.onDataArrived(length, buffer);
- break;
- case MESSAGE_CONNECTED:
- boolean connected = (Boolean) msg.obj;
- mCallback.onConnected(connected);
- break;
- case MESSAGE_OPEN:
- mCallback.onOpenConnection();
- break;
- }
- }
- };
- private class TransmitThread extends Thread {
- private final BluetoothSocket mSocket;
- private final InputStream mInStream;
- private final OutputStream mOutStream;
- public TransmitThread(BluetoothSocket socket) {
- mSocket = socket;
- InputStream tmpIn = null;
- OutputStream tmpOut = null;
- try {
- tmpIn = socket.getInputStream();
- tmpOut = socket.getOutputStream();
- Message msg = mHandler.obtainMessage(MESSAGE_OPEN);
- mHandler.sendMessage(msg);
- } catch (IOException e) {
- }
- mInStream = tmpIn;
- mOutStream = tmpOut;
- }
- public void run() {
- byte[] buffer = new byte[1024];
- int length;
- while (true) {
- try {
- length = mInStream.read(buffer);
- Message msg = mHandler.obtainMessage(MESSAGE_READ, length, -1, buffer);
- mHandler.sendMessage(msg);
- } catch (IOException e) {
- break;
- }
- }
- }
- public boolean write(byte[] bytes) {
- if (mOutStream == null) {
- return false;
- }
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < bytes.length; i++) {
- sb.append(bytes[i] + " ");
- }
- try {
- mOutStream.write(bytes);
- return true;
- } catch (IOException e) {
- }
- return false;
- }
- public void cancel() {
- try {
- mSocket.close();
- } catch (IOException e) {
- }
- try {
- mInStream.close();
- } catch (IOException e) {
- }
- try {
- mOutStream.close();
- } catch (IOException e) {
- }
- }
- }
- public boolean write(int i) {
- byte[] bytes = new byte[4];
- bytes[0] = (byte) (i);
- bytes[1] = (byte) (i >> 8);
- bytes[2] = (byte) (i >> 16);
- bytes[3] = (byte) (i >> 24);
- return write(bytes);
- }
- public boolean write(String s) {
- return write(s.getBytes());
- }
- public boolean write(byte[] bytes) {
- if (mTransmitThread == null) {
- return false;
- }
- return mTransmitThread.write(bytes);
- }
- public static class BluetoothDeviceAdapter extends ArrayAdapter<BluetoothDevice> {
- public BluetoothDeviceAdapter(Context context, List<BluetoothDevice> objects) {
- super(context, 0, objects);
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- LayoutInflater inflater = LayoutInflater.from(getContext());
- convertView = inflater.inflate(android.R.layout.simple_list_item_2, parent, false);
- }
- BluetoothDevice device = getItem(position);
- TextView nameView = (TextView) convertView.findViewById(android.R.id.text1);
- nameView.setText(device.getName());
- TextView addressView = (TextView) convertView.findViewById(android.R.id.text2);
- addressView.setText(device.getAddress());
- return convertView;
- }
- }
- }
こんな感じで Activity には BluetoothCallback を implements して利用します。
- public class MainActivity extends FragmentActivity implements BluetoothCallback {
- private static final String TAG = "MainActivity";
- BluetoothFragment mBluetoothFragment;
- View mButton;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- Bundle args = new Bundle();
- args.putInt(BluetoothFragment.EXTRA_UUID, BluetoothFragment.SPP_MODE);
- if (mBluetoothFragment == null) {
- mBluetoothFragment = new BluetoothFragment();
- getSupportFragmentManager().beginTransaction().add(mBluetoothFragment, "BluetoothFragment").commit();
- }
- mButton = findViewById(R.id.button1);
- mButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- write(new byte[] { 0x50, 0x4d, 0x03 });
- }
- });
- mButton.setEnabled(false);
- }
- public void onCheckAvailability(boolean isAvailable) {
- String text = "onCheckAvailability : " + isAvailable;
- Log.d(TAG, text);
- showToast(text);
- }
- public void onChangeBluetoothState(boolean enabled) {
- String text = "onChangeBluetoothState : " + enabled;
- Log.d(TAG, text);
- showToast(text);
- }
- public void onConnected(boolean connected) {
- String text = "onConnected : " + connected;
- Log.d(TAG, text);
- showToast(text);
- }
- public void onOpenConnection() {
- mButton.setEnabled(true);
- Log.d(TAG, "onOpenConnection");
- showToast("onOpenConnection");
- }
- public void onDataArrived(int length, byte[] buffer) {
- StringBuilder sb = new StringBuilder();
- for(int i = 0; i < length; i++) {
- sb.append(buffer[i] + " ");
- }
- String text = "onDataArrived : " + length + ", " + sb.toString();
- Log.d(TAG, text);
- showToast(text);
- }
- private void write(byte[] bytes) {
- if (mBluetoothFragment != null) {
- mBluetoothFragment.write(bytes);
- }
- }
- private void showToast(String text) {
- Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
- }
- }
初心者の幸太郎と申します。
返信削除ネット上に数多くのソースが公開されていますが、結局yanzmさんのソースが一番わかりやすく綺麗なソースなのでとても参考になります。
今回はBluetoothをやろうと思っているのですが、公開されているソースでいくつか疑問があります。
もし可能でしたらご解答頂けますと助かります。
まだまだ勉強不足で、チンプンカンプンな質問をしてしまうかもしれませんが、お許しください。
1)公開ソースで動かしてみました。
スマホ<->タブレット 間で接続を試みました。
対象機器は表示されたのですが、接続ができませんでした。
(onConnected:falseです)
ソースを追っていくと、他のサイトでは、サーバー側listenUsingRfcommWithServiceRecord()、
クライアント側createRfcommSocketToServiceRecord()
を使ってサーバー<->クライアント間を通信しているような作りが
多いように思えますが、
こちらのソースでは、createRfcommSocketToServiceRecord()のみ。
ということはもしかしてクライアント用ソースでしょうか?
もしそうだとしますと、サーバー側のソースは公開される予定はありますでしょうか?
2)レイアウトxmlの公開はして頂けないのでしょうか?
3)Androidを勉強するにあたって参考になる書籍やブログ(英語はよめません)がありましたら、教えてください。
以上になります。
お忙しい所恐縮ですが、よろしくお願いいたします。