Java tutorial
/* Copyright (c) 2011 - Andago * * author: Daniel Tizn, Idoia Olalde, Iigo Gonzlez * modified: Luke BrownGold * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package org.lsc.hellocordova; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Set; import org.json.JSONArray; import android.net.ConnectivityManager; import android.os.Looper; import android.util.Log; import org.apache.cordova.api.Plugin; import org.apache.cordova.api.PluginResult; import org.apache.cordova.api.PluginResult.Status; import android.bluetooth.BluetoothAdapter; 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 java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Set; import java.util.UUID; public class BluetoothPlugin extends Plugin { public static final String ACTION_DISCOVER_DEVICES = "listDevices"; public static final String ACTION_LIST_BOUND_DEVICES = "listBoundDevices"; public static final String ACTION_IS_BT_ENABLED = "isBTEnabled"; public static final String ACTION_ENABLE_BT = "enableBT"; public static final String ACTION_DISABLE_BT = "disableBT"; public static final String ACTION_PAIR_BT = "pairBT"; public static final String ACTION_UNPAIR_BT = "unPairBT"; public static final String ACTION_STOP_DISCOVERING_BT = "stopDiscovering"; public static final String ACTION_IS_BOUND_BT = "isBound"; public static final String ACTION_OPEN_SOCKET = "openSocket"; public static final String ACTION_MESSAGE_SOCKET = "messageSocket"; public static final String ACTION_PING_SOCKET = "pingSocket"; public static final String ACTION_CLOSE_SOCKET = "closeSocket"; private static BluetoothAdapter btadapter; private ArrayList<BluetoothDevice> found_devices; private boolean discovering = false; private Context context; /* Sockets Stuff */ private BluetoothSocket mmSocket; private OutputStream mmOutputStream; private InputStream mmInputStream; private Thread workerThread; private byte[] readBuffer; private int readBufferPosition; private int counter; private volatile boolean stopWorker; private ArrayList<String> pingData = new ArrayList<String>(); private int pingCount = 0; /* (non-Javadoc) * @see com.phonegap.api.Plugin#execute(java.lang.String, org.json.JSONArray, java.lang.String) */ @Override public PluginResult execute(String action, JSONArray arg1, String callbackId) { Log.d("BluetoothPlugin", "Plugin Called"); PluginResult result = null; context = (Context) this.ctx; // Register for broadcasts when a device is discovered IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); context.registerReceiver(mReceiver, filter); // Register for broadcasts when discovery starts filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED); context.registerReceiver(mReceiver, filter); // Register for broadcasts when discovery has finished filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); context.registerReceiver(mReceiver, filter); // Register for broadcasts when connectivity state changes filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); context.registerReceiver(mReceiver, filter); Looper.prepare(); btadapter = BluetoothAdapter.getDefaultAdapter(); found_devices = new ArrayList<BluetoothDevice>(); if (ACTION_DISCOVER_DEVICES.equals(action)) { try { Log.d("BluetoothPlugin", "We're in " + ACTION_DISCOVER_DEVICES); found_devices.clear(); discovering = true; if (btadapter.isDiscovering()) { btadapter.cancelDiscovery(); } Log.i("BluetoothPlugin", "Discovering devices..."); btadapter.startDiscovery(); while (discovering) { } String devicesFound = null; int count = 0; devicesFound = "["; for (BluetoothDevice device : found_devices) { Log.i("BluetoothPlugin", device.getName() + " " + device.getAddress() + " " + device.getBondState()); if ((device.getName() != null) && (device.getBluetoothClass() != null)) { devicesFound = devicesFound + " { \"name\" : \"" + device.getName() + "\" ," + "\"address\" : \"" + device.getAddress() + "\" ," + "\"class\" : \"" + device.getBluetoothClass().getDeviceClass() + "\" }"; if (count < found_devices.size() - 1) devicesFound = devicesFound + ","; } else Log.i("BluetoothPlugin", device.getName() + " Problems retrieving attributes. Device not added "); count++; } devicesFound = devicesFound + "] "; Log.d("BluetoothPlugin - " + ACTION_DISCOVER_DEVICES, "Returning: " + devicesFound); result = new PluginResult(Status.OK, devicesFound); } catch (Exception Ex) { Log.d("BluetoothPlugin - " + ACTION_DISCOVER_DEVICES, "Got Exception " + Ex.getMessage()); result = new PluginResult(Status.ERROR); } } else if (ACTION_IS_BT_ENABLED.equals(action)) { try { Log.d("BluetoothPlugin", "We're in " + ACTION_IS_BT_ENABLED); boolean isEnabled = btadapter.isEnabled(); Log.d("BluetoothPlugin - " + ACTION_IS_BT_ENABLED, "Returning " + "is Bluetooth Enabled? " + isEnabled); result = new PluginResult(Status.OK, isEnabled); } catch (Exception Ex) { Log.d("BluetoothPlugin - " + ACTION_IS_BT_ENABLED, "Got Exception " + Ex.getMessage()); result = new PluginResult(Status.ERROR); } } else if (ACTION_ENABLE_BT.equals(action)) { try { Log.d("BluetoothPlugin", "We're in " + ACTION_ENABLE_BT); boolean enabled = false; Log.d("BluetoothPlugin", "Enabling Bluetooth..."); if (btadapter.isEnabled()) { enabled = true; } else { enabled = btadapter.enable(); } Log.d("BluetoothPlugin - " + ACTION_ENABLE_BT, "Returning " + "Result: " + enabled); result = new PluginResult(Status.OK, enabled); } catch (Exception Ex) { Log.d("BluetoothPlugin - " + ACTION_ENABLE_BT, "Got Exception " + Ex.getMessage()); result = new PluginResult(Status.ERROR); } } else if (ACTION_DISABLE_BT.equals(action)) { try { Log.d("BluetoothPlugin", "We're in " + ACTION_DISABLE_BT); boolean disabled = false; Log.d("BluetoothPlugin", "Disabling Bluetooth..."); if (btadapter.isEnabled()) { disabled = btadapter.disable(); } else { disabled = true; } Log.d("BluetoothPlugin - " + ACTION_DISABLE_BT, "Returning " + "Result: " + disabled); result = new PluginResult(Status.OK, disabled); } catch (Exception Ex) { Log.d("BluetoothPlugin - " + ACTION_DISABLE_BT, "Got Exception " + Ex.getMessage()); result = new PluginResult(Status.ERROR); } } else if (ACTION_PAIR_BT.equals(action)) { try { Log.d("BluetoothPlugin", "We're in " + ACTION_PAIR_BT); String addressDevice = arg1.getString(0); if (btadapter.isDiscovering()) { btadapter.cancelDiscovery(); } BluetoothDevice device = btadapter.getRemoteDevice(addressDevice); boolean paired = false; Log.d("BluetoothPlugin", "Pairing with Bluetooth device with name " + device.getName() + " and address " + device.getAddress()); try { Method m = device.getClass().getMethod("createBond"); paired = (Boolean) m.invoke(device); } catch (Exception e) { e.printStackTrace(); } Log.d("BluetoothPlugin - " + ACTION_PAIR_BT, "Returning " + "Result: " + paired); result = new PluginResult(Status.OK, paired); } catch (Exception Ex) { Log.d("BluetoothPlugin - " + ACTION_PAIR_BT, "Got Exception " + Ex.getMessage()); result = new PluginResult(Status.ERROR); } } else if (ACTION_UNPAIR_BT.equals(action)) { try { Log.d("BluetoothPlugin", "We're in " + ACTION_UNPAIR_BT); String addressDevice = arg1.getString(0); if (btadapter.isDiscovering()) { btadapter.cancelDiscovery(); } BluetoothDevice device = btadapter.getRemoteDevice(addressDevice); boolean unpaired = false; Log.d("BluetoothPlugin", "Unpairing Bluetooth device with " + device.getName() + " and address " + device.getAddress()); try { Method m = device.getClass().getMethod("removeBond"); unpaired = (Boolean) m.invoke(device); } catch (Exception e) { e.printStackTrace(); } Log.d("BluetoothPlugin - " + ACTION_UNPAIR_BT, "Returning " + "Result: " + unpaired); result = new PluginResult(Status.OK, unpaired); } catch (Exception Ex) { Log.d("BluetoothPlugin - " + ACTION_UNPAIR_BT, "Got Exception " + Ex.getMessage()); result = new PluginResult(Status.ERROR); } } else if (ACTION_LIST_BOUND_DEVICES.equals(action)) { try { Log.d("BluetoothPlugin", "We're in " + ACTION_LIST_BOUND_DEVICES); Log.d("BluetoothPlugin", "Getting paired devices..."); Set<BluetoothDevice> pairedDevices = btadapter.getBondedDevices(); int count = 0; String resultBoundDevices = "[ "; if (pairedDevices.size() > 0) { for (BluetoothDevice device : pairedDevices) { Log.i("BluetoothPlugin", device.getName() + " " + device.getAddress() + " " + device.getBondState()); if ((device.getName() != null) && (device.getBluetoothClass() != null)) { resultBoundDevices = resultBoundDevices + " { \"name\" : \"" + device.getName() + "\" ," + "\"address\" : \"" + device.getAddress() + "\" ," + "\"class\" : \"" + device.getBluetoothClass().getDeviceClass() + "\" }"; if (count < pairedDevices.size() - 1) resultBoundDevices = resultBoundDevices + ","; } else Log.i("BluetoothPlugin", device.getName() + " Problems retrieving attributes. Device not added "); count++; } } resultBoundDevices = resultBoundDevices + "] "; Log.d("BluetoothPlugin - " + ACTION_LIST_BOUND_DEVICES, "Returning " + resultBoundDevices); result = new PluginResult(Status.OK, resultBoundDevices); } catch (Exception Ex) { Log.d("BluetoothPlugin - " + ACTION_LIST_BOUND_DEVICES, "Got Exception " + Ex.getMessage()); result = new PluginResult(Status.ERROR); } } else if (ACTION_STOP_DISCOVERING_BT.equals(action)) { try { Log.d("BluetoothPlugin", "We're in " + ACTION_STOP_DISCOVERING_BT); boolean stopped = true; Log.d("BluetoothPlugin", "Stop Discovering Bluetooth Devices..."); if (btadapter.isDiscovering()) { Log.i("BluetoothPlugin", "Stop discovery..."); stopped = btadapter.cancelDiscovery(); discovering = false; } Log.d("BluetoothPlugin - " + ACTION_STOP_DISCOVERING_BT, "Returning " + "Result: " + stopped); result = new PluginResult(Status.OK, stopped); } catch (Exception Ex) { Log.d("BluetoothPlugin - " + ACTION_STOP_DISCOVERING_BT, "Got Exception " + Ex.getMessage()); result = new PluginResult(Status.ERROR); } } else if (ACTION_IS_BOUND_BT.equals(action)) { try { Log.d("BluetoothPlugin", "We're in " + ACTION_IS_BOUND_BT); String addressDevice = arg1.getString(0); BluetoothDevice device = btadapter.getRemoteDevice(addressDevice); Log.i("BluetoothPlugin", "BT Device in state " + device.getBondState()); boolean state = false; if (device != null && device.getBondState() == 12) state = true; else state = false; Log.d("BluetoothPlugin", "Is Bound with " + device.getName() + " - address " + device.getAddress()); Log.d("BluetoothPlugin - " + ACTION_IS_BOUND_BT, "Returning " + "Result: " + state); result = new PluginResult(Status.OK, state); } catch (Exception Ex) { Log.d("BluetoothPlugin - " + ACTION_IS_BOUND_BT, "Got Exception " + Ex.getMessage()); result = new PluginResult(Status.ERROR); } } else if (ACTION_OPEN_SOCKET.equals(action)) { Log.d("BluetoothPlugin", "We're in " + ACTION_OPEN_SOCKET); try { String addressDevice = arg1.getString(0); openSocket(addressDevice); result = new PluginResult(Status.OK, "true"); } catch (Exception Ex) { Log.d("BluetoothPlugin - " + ACTION_OPEN_SOCKET, "Got Exception " + Ex.getMessage()); result = new PluginResult(Status.ERROR); } } else if (ACTION_MESSAGE_SOCKET.equals(action)) { Log.d("BluetoothPlugin", "We're in " + ACTION_MESSAGE_SOCKET); try { String msg = arg1.getString(0); sendData(msg); result = new PluginResult(Status.OK, "true"); } catch (Exception Ex) { Log.d("BluetoothPlugin - " + ACTION_MESSAGE_SOCKET, "Got Exception " + Ex.getMessage()); result = new PluginResult(Status.ERROR); } } else if (ACTION_CLOSE_SOCKET.equals(action)) { Log.d("BluetoothPlugin", "We're in " + ACTION_CLOSE_SOCKET); try { closeSocket(); result = new PluginResult(Status.OK, "true"); } catch (Exception Ex) { Log.d("BluetoothPlugin - " + ACTION_CLOSE_SOCKET, "Got Exception " + Ex.getMessage()); result = new PluginResult(Status.ERROR); } } else if (ACTION_PING_SOCKET.equals(action)) { try { Log.d("BluetoothPlugin", "We're in " + ACTION_PING_SOCKET); String data = "{"; data = data + "\"count\": " + Integer.toString(pingCount) + ","; String items = ""; for (String item : pingData) { items = items + ",\"" + item + "\""; } data = data + " \"data\" : [" + items.substring(1) + " ]"; data = data + "}"; result = new PluginResult(Status.OK, data); } catch (Exception Ex) { Log.d("BluetoothPlugin - " + ACTION_PING_SOCKET, "Got Exception " + Ex.getMessage()); result = new PluginResult(Status.ERROR); } } else { result = new PluginResult(Status.INVALID_ACTION); Log.d("BluetoothPlugin", "Invalid action : " + action + " passed"); } return result; } public void setDiscovering(boolean state) { discovering = state; } public void addDevice(BluetoothDevice device) { if (!found_devices.contains(device)) { Log.i("BluetoothPlugin", "Device stored "); found_devices.add(device); } } @Override public void onDestroy() { // TODO Auto-generated method stub Log.i("BluetoothPlugin", "onDestroy " + this.getClass()); context.unregisterReceiver(mReceiver); super.onDestroy(); } /** BroadcastReceiver to receive bluetooth events */ private final BroadcastReceiver mReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Log.i("BluetoothPlugin", "Action: " + action); // When discovery finds a device if (BluetoothDevice.ACTION_FOUND.equals(action)) { // Get the BluetoothDevice object from the Intent BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); Log.i("BluetoothPlugin", "Device found " + device.getName() + " " + device.getBondState() + " " + device.getAddress()); if (device.getBondState() != BluetoothDevice.BOND_BONDED) { Log.i("BluetoothPlugin", "Device not paired"); addDevice(device); } else Log.i("BluetoothPlugin", "Device already paired"); // When discovery starts } else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) { Log.i("BluetoothPlugin", "Discovery started"); setDiscovering(true); // When discovery finishes } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { Log.i("BluetoothPlugin", "Discovery finilized"); setDiscovering(false); } } }; /* SOCKECT STUFF */ private void openSocket(String addressDevice) throws IOException { BluetoothDevice device = btadapter.getRemoteDevice(addressDevice); UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); //Standard //SerialPortService ID mmSocket = device.createRfcommSocketToServiceRecord(uuid); mmSocket.connect(); mmOutputStream = mmSocket.getOutputStream(); mmInputStream = mmSocket.getInputStream(); beginListenForData(); Log.i("BluetoothPlugin", "Bluetooth Sockets Opened"); } void beginListenForData() { final Handler handler = new Handler(); final byte delimiter = 10; //This is the ASCII code for a newline character stopWorker = false; readBufferPosition = 0; readBuffer = new byte[1024]; workerThread = new Thread(new Runnable() { public void run() { while (!Thread.currentThread().isInterrupted() && !stopWorker) { try { int bytesAvailable = mmInputStream.available(); if (bytesAvailable > 0) { byte[] packetBytes = new byte[bytesAvailable]; mmInputStream.read(packetBytes); for (int i = 0; i < bytesAvailable; i++) { byte b = packetBytes[i]; if (b == delimiter) { byte[] encodedBytes = new byte[readBufferPosition]; System.arraycopy(readBuffer, 0, encodedBytes, 0, encodedBytes.length); final String data = new String(encodedBytes, "US-ASCII"); readBufferPosition = 0; if (pingData.size() == 0) pingData.add("READY"); if (data.equals(pingData.get(pingData.size() - 1)) == false) { pingData.add(data); pingCount += 1; } if (pingData.size() > 100) { pingData.remove(0); } if (pingCount >= Integer.MAX_VALUE - 1) // not cause errors if the device is running for a long time pingCount = 0; //Log.i("BluetoothPlugin","BYTES! "+data); } else { readBuffer[readBufferPosition++] = b; } } } } catch (IOException ex) { stopWorker = true; } } } }); workerThread.start(); } void sendData(String data) throws IOException { String msg = data; //msg += "\n"; mmOutputStream.write(msg.getBytes()); //mmOutputStream.write('A'); Log.i("BluetoothPlugin", "DATA SENT: " + msg); } void closeSocket() throws IOException { stopWorker = true; mmOutputStream.close(); mmInputStream.close(); mmSocket.close(); Log.i("BluetoothPlugin", "Bluetooth Sockets Closed"); } }