Back to project page accessory-samples.
The source code is released under:
Copyright (c) 2012 Wireless Designs, LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in ...
If you think the Android project accessory-samples listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/** * MainBluetoothActivity is a GameActivity that monitors a Bluetooth * accessory device and uses the input from that device to control * the game.//from w ww .j a v a 2s . c o m */ package com.examples.accessory.controller; import android.app.ProgressDialog; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Handler; import android.os.Message; import android.os.ParcelUuid; import android.util.Log; import android.view.View; import android.widget.Toast; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Method; import java.util.UUID; public class MainBluetoothActivity extends GameActivity implements Runnable { //Friendly name of the Bluetooth device we are looking to connect with private static final String CONTROLLER_NAME = "adccontroller"; private static final int CONTROLLER_CLASS = BluetoothClass.Device.TOY_CONTROLLER; //RFCOMM Service UUID on our device private static final UUID BT_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private static final int MESSAGE_SWITCH = 1; private static final int MESSAGE_JOY = 4; private static final int MESSAGE_VIBE = 5; private static final int MESSAGE_CONNECTED = 100; private static final int MESSAGE_CONNECTFAIL = 101; ProgressDialog mProgress; BluetoothDevice mControllerDevice; BluetoothSocket mSocket; InputStream mInputStream; OutputStream mOutputStream; @Override protected void onResume() { super.onResume(); IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED); registerReceiver(mAclConnectReceiver, filter); mSocket = null; } @Override protected void onPause() { super.onPause(); unregisterReceiver(mAclConnectReceiver); closeConnection(); } @Override protected boolean isControllerConnected() { return (mSocket != null); } @Override protected void sendVibeControl(boolean longDuration) { byte[] command = {0x02, longDuration ? (byte)0x64 : (byte)0x32, 0x00}; Message msg = Message.obtain(null, MESSAGE_VIBE, command); mHandler.sendMessage(msg); } @Override protected void hideControls() { setContentView(R.layout.no_device_bluetooth); super.hideControls(); } private void closeConnection() { enableControls(false); try { mSocket.close(); } catch (Exception e) { } } public void onConnectClick(View v) { //Register for the device discovery callbacks IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); registerReceiver(mDiscoveryReceiver, filter); //Begin device discovery BluetoothAdapter.getDefaultAdapter().startDiscovery(); mProgress = ProgressDialog.show(this, "", "Scanning for Devices...", true); } /* * Helper method to create a polling thread for the accessory and * load the game. */ private void beginGame() { //Create a new thread using this Activity's Runnable as the execution block Thread thread = new Thread(null, this, "BluetoothController"); thread.start(); //Show the game view Log.d(TAG, "Bluetooth Connected"); enableControls(true); } /* * This receiver will log out the lower level ACL connection events, Android will not * auto-connect a paired device for us, so these events will only come as a result of * use initiating and tearing down the connection, but they are still interesting to watch */ private BroadcastReceiver mAclConnectReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(intent.getAction())) { Log.i("AccessoryController", "ACL Connect Device: "+device.getName()); } if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(intent.getAction()) || BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED.equals(intent.getAction())) { Log.i("AccessoryController", "ACL Disconnect Device: "+device.getName()); closeConnection(); } } }; /* * This receiver will listen during the discovery process for each device located. * If a device with the same friendly name as our controller is found, we abort * discovery and move to the connecting phase. If no device has been located by * the time discovery finishes, we alert the user. */ private BroadcastReceiver mDiscoveryReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (BluetoothDevice.ACTION_FOUND.equals(intent.getAction())) { BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); Log.d("AccessoryController", "Device Found: "+device.getName()); if (CONTROLLER_NAME.equals(device.getName()) && CONTROLLER_CLASS == device.getBluetoothClass().getDeviceClass()) { // We found our controller mControllerDevice = device; //Start a thread to establish connection ConnectThread thread = new ConnectThread(); thread.start(); finishDiscovery(); mProgress = ProgressDialog.show(MainBluetoothActivity.this, "", "Connecting...", true); } } if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent .getAction())) { if (mControllerDevice == null) { // We didn't find anything Toast.makeText(context, "No Controller Device Found.", Toast.LENGTH_SHORT).show(); finishDiscovery(); } } } private void finishDiscovery() { BluetoothAdapter.getDefaultAdapter().cancelDiscovery(); unregisterReceiver(this); if (mProgress != null) { mProgress.dismiss(); mProgress = null; } } }; /* * We create a new thread to do the work of connecting to the remote device * and setting up the data transfer because this process is blocking and * can take some time to complete. */ private class ConnectThread extends Thread { public void run() { try { //Create a socket to the RFCOMM service mSocket = mControllerDevice.createInsecureRfcommSocketToServiceRecord(BT_UUID); // Connect the device through the socket. This will block // until it succeeds or throws an exception mSocket.connect(); //Once connected, get the read/write data streams mInputStream = mSocket.getInputStream(); mOutputStream = mSocket.getOutputStream(); } catch (IOException connectException) { Log.w(TAG, "Error Connecting Bluetooth"); // Unable to connect; close the socket and get out try { mSocket.close(); } catch (IOException closeException) { } mHandler.sendEmptyMessage(MESSAGE_CONNECTFAIL); return; } mHandler.sendEmptyMessage(MESSAGE_CONNECTED); } //In SDK15 (4.0.3) this method is now public as //Bluetooth.fetchUuisWithSdp() and BluetoothDevice.getUuids() public ParcelUuid[] servicesFromDevice(BluetoothDevice device) { try { Class cl = Class.forName("android.bluetooth.BluetoothDevice"); Class[] par = {}; Method method = cl.getMethod("getUuids", par); Object[] args = {}; ParcelUuid[] retval = (ParcelUuid[]) method.invoke(device, args); return retval; } catch (Exception e) { e.printStackTrace(); return null; } } }; /* * Runnable block that will poll the accessory InputStream for * regular data updates, and post each message it encounters to * a Handler. This is executed on a spawned background thread. */ public void run() { byte[] buffer = new byte[16]; int i; boolean running = true; //Wrap the stream to allow for fixed reads DataInputStream input = new DataInputStream(mInputStream); while (running) { try { input.readFully(buffer, 0, 3); } catch (IOException e) { break; } switch (buffer[0]) { case 0x1: { Message m = Message.obtain(mHandler, MESSAGE_SWITCH); m.obj = new SwitchMsg(buffer[1], buffer[2]); mHandler.sendMessage(m); break; } case 0x6: { Message m = Message.obtain(mHandler, MESSAGE_JOY); m.obj = new JoyMsg(buffer[1], buffer[2]); mHandler.sendMessage(m); break; } default: Log.d(TAG, "unknown msg: " + buffer[0]); break; } } } /* * This Handler receives messages from the polling thread and * injects them into the GameActivity methods on the main thread. * * It also responds to connect events posted from the connect thread * in order to update the UI state. */ Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_CONNECTED: beginGame(); case MESSAGE_CONNECTFAIL: if (mProgress != null) { mProgress.dismiss(); mProgress = null; } break; case MESSAGE_SWITCH: SwitchMsg o = (SwitchMsg) msg.obj; handleSwitchMessage(o); break; case MESSAGE_JOY: JoyMsg j = (JoyMsg) msg.obj; handleJoyMessage(j); break; case MESSAGE_VIBE: try { byte[] v = (byte[]) msg.obj; mOutputStream.write(v); mOutputStream.flush(); } catch (IOException e) { Log.w("AccessoryController", "Error writing vibe output"); } break; } } }; }