前臺 bluetooth.jsjava
/* Copyright 2013 101.keyandroid
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 atexpress
http://www.apache.org/licenses/LICENSE-2.0apache
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 CO NDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */json
var Bluetooth = function() {};api
/** * 判斷藍牙設備啓用 * * @param successCallback:true or false * @param failureCallback:error message */ Bluetooth.prototype.isBTEnabled = function(successCallback, failureCallback) { return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'isBTEnabled', []); };
/** * 啓用藍牙設備 * * @param successCallback:true * @param failureCallback:error message */ Bluetooth.prototype.enableBT = function(successCallback,failureCallback) { return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'enableBT', []); }
/** * 禁用藍牙設備 * * @param successCallback:true * @param failureCallback:error message */ Bluetooth.prototype.disableBT = function(successCallback,failureCallback) { return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'disableBT', []); }
/** * 開始藍牙設備搜索 * * @param successCallback:JSONArray {'name':'address',...} * @param failureCallback:error message */ Bluetooth.prototype.discoverDevices = function(successCallback, failureCallback) { return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'discoverDevices', []); }
/** * 中止藍牙設備搜索 * * @param successCallback:true or false * @param failureCallback:error message */ Bluetooth.prototype.stopDiscoverDevices = function(successCallback, failureCallback) { return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'stopDiscoverDevices', []); }
/** * 藍牙設備是否已綁定 * * @param successCallback:true or false * @param failureCallback:error message * @param address:設備物理地址 */ Bluetooth.prototype.isBoundBT = function(successCallback, failureCallback, address) { return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'isBoundBT', [address]); };
/** * 綁定藍牙設備 * * @param successCallback:true or false * @param failureCallback:error message * @param address:設備物理地址 */ Bluetooth.prototype.boundBT = function(successCallback, failureCallback, address) { return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'boundBT', [address]); };
/** * 解除藍牙設備綁定 * * @param successCallback:true or false * @param failureCallback:error message */ Bluetooth.prototype.unBoundBT = function(successCallback, failureCallback, address) { return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'unBoundBT', [address]); };
/** * 列出全部已綁定的藍牙設備 * * @param successCallback:JSONArray {'name':'address',...} * @param failureCallback:error message */ Bluetooth.prototype.listBoundDevices = function(successCallback, failureCallback) { return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'listBoundDevices', []); };
/** * 藍牙設備是否已連接 * * @param successCallback:true * @param failureCallback:error message * @param address:設備物理地址 */ Bluetooth.prototype.isConnect = function(successCallback, failureCallback, address) { return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'isConnect', [address]); };
/** * 連接藍牙設備 * * @param successCallback:success message * @param failureCallback:error message * @param address:設備物理地址 */ Bluetooth.prototype.connect = function(successCallback, failureCallback, address) { return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'connect', [address]); };
/** * 解除藍牙設備連接 * * @param successCallback:success message * @param failureCallback:error message * @param address:設備物理地址 */ Bluetooth.prototype.disconnect = function(successCallback, failureCallback, address) { return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'disconnect', [address]); };
/** * 往藍牙設備寫字符串數據 * * @param successCallback:success message * @param failureCallback:error message * @param address:設備物理地址 * @param message:要寫入的數據 * @param encoding:數據編碼格式 */ Bluetooth.prototype.writeString = function(successCallback, failureCallback, address, message, encoding) { return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'writeString', [address,message,encoding]); };
/** * 往藍牙設備寫ASCII碼數據 * * @param address:設備物理地址 * @param ascii:要寫入的ASCII碼數據 */ Bluetooth.prototype.writeASCII = function(address, ascii) { return cordova.exec(function(message) { //alert(message); }, function(error) { // alert( 'Error: ' + error ); },'BluetoothPlugin', 'writeASCII', [address,ascii]); };
if(!window.plugins) { window.plugins = {}; } if (!window.plugins.BluetoothPlugin) { window.plugins.BluetoothPlugin = new Bluetooth(); }app
----------------------------------------------------------------------less
後臺BluetoothPlugin.javasocket
/* Copyright 2013.01 101.key
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.apache.cordova.plugin;
import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.Set;
import org.apache.cordova.api.CallbackContext; import org.apache.cordova.api.CordovaPlugin; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject;
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.util.Log;
public class BluetoothPlugin extends CordovaPlugin {
private static final String ACTION_IS_BT_ENABLED = "isBTEnabled"; // 藍牙是否可用 private static final String ACTION_ENABLE_BT = "enableBT"; // 啓用藍牙 private static final String ACTION_DISABLE_BT = "disableBT"; // 禁用藍牙 private static final String ACTION_DISCOVERDEVICES = "discoverDevices"; // 搜索藍牙設備 private static final String ACTION_STOP_DISCOVERDEVICES = "stopDiscoverDevices"; // 中止藍牙設備搜索
private static final String ACTION_IS_BOUND_BT = "isBoundBT"; // 指定的藍牙設備是否綁定 private static final String ACTION_BOUND_BT = "boundBT"; // 綁定藍牙設備 private static final String ACTION_UNBOUND_BT = "unBoundBT"; // 解除藍牙設備綁定 private static final String ACTION_LIST_BOUND_DEVICES = "listBoundDevices"; // 列出全部已綁定的藍牙設備
private static final String ACTION_IS_CONNECT = "isConnect"; // 指定的藍牙設備是否已連接 private static final String ACTION_CONNECT = "connect"; // 連接藍牙設備 private static final String ACTION_DISCONNECT = "disconnect"; // 斷開藍牙設備連接
private static final String ACTION_WRITE_STRING = "writeString"; // 往藍牙設備寫入字符串數據 private static final String ACTION_WRITE_ASCII = "writeASCII"; // 往藍牙設備寫入ASCII碼數據
private BluetoothAdapter m_bluetoothAdapter = null; // 藍牙適配器 private BPBroadcastReceiver m_bpBroadcastReceiver = null; // 廣播狀態接收者 private boolean m_discovering = false; // 是否正在搜索藍牙 private boolean m_stateChanging = false; // 狀態變化 private JSONArray m_discoveredDevices = null; //已發現的藍牙設備 private JSONArray m_boundDevices = null; //已綁定的藍牙設備 private Map bluetoothSocketMap = new HashMap(); //已連接的藍牙設備socket映射(address to socket)
/** * Constructor for Bluetooth plugin */ public BluetoothPlugin() { m_bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); m_bpBroadcastReceiver = new BPBroadcastReceiver(); }
/** * Execute a bluetooth function */ @Override public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException { // Register for necessary bluetooth events Log.d("BluetoothPlugin", "Action: " + action);
// Check if bluetooth is supported at all if (m_bluetoothAdapter == null) { callbackContext.error("No bluetooth adapter found"); return false; } else { if (ACTION_IS_BT_ENABLED.equals(action)) { try { boolean isEnabled = m_bluetoothAdapter.isEnabled(); callbackContext.success(isEnabled + ""); } catch (Exception Ex) { Log.d("BluetoothPlugin", "Got Exception " + Ex.getMessage()); callbackContext.error(Ex.getMessage()); }
} else if (ACTION_ENABLE_BT.equals(action)) { if (!m_bluetoothAdapter.isEnabled()) { m_stateChanging = true; cordova.startActivityForResult(this, new Intent( BluetoothAdapter.ACTION_REQUEST_ENABLE), 1); while (m_stateChanging) { } ; } if (m_bluetoothAdapter.isEnabled()) { callbackContext.success("true"); } else { callbackContext.error("藍牙設備啓用失敗!"); return false; } } else if (ACTION_DISABLE_BT.equals(action)) { if (!m_bluetoothAdapter.disable() && m_bluetoothAdapter.isEnabled()) { callbackContext.error("藍牙設備禁用失敗!"); return false; } else { callbackContext.success("true"); } } else if (ACTION_DISCOVERDEVICES.equals(action)) { cordova.getActivity().registerReceiver(m_bpBroadcastReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND)); cordova.getActivity().registerReceiver( m_bpBroadcastReceiver, new IntentFilter( BluetoothAdapter.ACTION_DISCOVERY_STARTED)); cordova.getActivity().registerReceiver( m_bpBroadcastReceiver, new IntentFilter( BluetoothAdapter.ACTION_DISCOVERY_FINISHED)); cordova.getThreadPool().execute(new Runnable() { public void run() { m_discoveredDevices = new JSONArray(); if (m_bluetoothAdapter.isDiscovering()) { m_bluetoothAdapter.cancelDiscovery(); } if (!m_bluetoothAdapter.startDiscovery()) { callbackContext.error("沒法啓動藍牙搜索!"); } else { Log.i("BluetoothPlugin", "Discovering devices..."); m_discovering = true; // Wait for discovery to finish while (m_discovering) { } Log.d("BluetoothPlugin", "DiscoveredDevices: " + m_discoveredDevices.length()); callbackContext.success(m_discoveredDevices); } } }); } else if (ACTION_STOP_DISCOVERDEVICES.equals(action)) { try { boolean stopped = true; Log.d("BluetoothPlugin", "Stop Discovering Bluetooth Devices..."); if (m_bluetoothAdapter.isDiscovering()) { Log.i("BluetoothPlugin", "Stop discovery..."); stopped = m_bluetoothAdapter.cancelDiscovery(); m_discovering = false; } callbackContext.success(stopped + ""); } catch (Exception Ex) { Log.d("BluetoothPlugin", "Got Exception " + Ex.getMessage()); callbackContext.error(Ex.getMessage()); } } else if (ACTION_IS_BOUND_BT.equals(action)) { try { String addressDevice = args.getString(0); BluetoothDevice device = m_bluetoothAdapter.getRemoteDevice(addressDevice); boolean state = false; if (device != null && device.getBondState() == BluetoothDevice.BOND_BONDED) state = true; else state = false; Log.d("BluetoothPlugin", device.getName() + "[" + device.getAddress() + "]isBound: " + state); callbackContext.success(state + ""); } catch (Exception Ex) { Log.d("BluetoothPlugin", ACTION_IS_BOUND_BT + " Got Exception " + Ex.getMessage()); callbackContext.error(Ex.getMessage()); } } else if (ACTION_BOUND_BT.equals(action)) { try { String addressDevice = args.getString(0); if (m_bluetoothAdapter.isDiscovering()) { m_bluetoothAdapter.cancelDiscovery(); } boolean paired = false; BluetoothDevice device = m_bluetoothAdapter.getRemoteDevice(addressDevice); if (device != null && device.getBondState() == BluetoothDevice.BOND_BONDED){ paired = true; callbackContext.success(paired + ""); return true; } Log.d("BluetoothPlugin", "start createBond with Bluetooth device with name " + device.getName() + " and address " + device.getAddress()); Method m = device.getClass().getMethod("createBond"); paired = (Boolean) m.invoke(device); Log.d("BluetoothPlugin", "Returning " + "Result: " + paired); callbackContext.success(paired + ""); } catch (Exception Ex) { Log.d("BluetoothPlugin", "Got Exception " + Ex.getMessage()); callbackContext.error(Ex.getMessage()); } } else if (ACTION_UNBOUND_BT.equals(action)) { try { String addressDevice = args.getString(0); if (m_bluetoothAdapter.isDiscovering()) { m_bluetoothAdapter.cancelDiscovery(); } BluetoothDevice device = m_bluetoothAdapter .getRemoteDevice(addressDevice); boolean unpaired = false; Log.d("BluetoothPlugin", "unBouding Bluetooth device with " + device.getName() + " and address " + device.getAddress()); Method m = device.getClass().getMethod("removeBond"); unpaired = (Boolean) m.invoke(device); Log.d("BluetoothPlugin", ACTION_UNBOUND_BT + " Returning " + "Result: " + unpaired); callbackContext.success(unpaired + ""); } catch (Exception Ex) { Log.d("BluetoothPlugin", ACTION_UNBOUND_BT + " Got Exception " + Ex.getMessage()); callbackContext.error(Ex.getMessage()); } } else if (ACTION_LIST_BOUND_DEVICES.equals(action)) { try { Log.d("BluetoothPlugin", "Getting paired devices..."); m_boundDevices = new JSONArray(); Set<BluetoothDevice> pairedDevices = m_bluetoothAdapter .getBondedDevices(); if (pairedDevices.size() > 0) { for (BluetoothDevice device : pairedDevices) { Log.i("BluetoothPlugin", device.getName() + " " + device.getAddress() + " " + device.getBondState());
if ((device.getName() != null) && (device.getBluetoothClass() != null)) { try { JSONObject deviceInfo = new JSONObject(); deviceInfo.put("name", device.getName()); deviceInfo.put("address", device.getAddress()); m_boundDevices.put(deviceInfo); } catch (JSONException e) { Log.e("BluetoothPlugin", e.getMessage()); }
} else Log.i("BluetoothPlugin",device.getName() + " Problems retrieving attributes. Device not added "); } } Log.d("BluetoothPlugin", ACTION_LIST_BOUND_DEVICES + " Returning " + m_boundDevices.toString()); callbackContext.success(m_boundDevices); } catch (Exception Ex) { Log.d("BluetoothPlugin", ACTION_LIST_BOUND_DEVICES + " Got Exception " + Ex.getMessage()); callbackContext.error(Ex.getMessage()); } } else if (ACTION_IS_CONNECT.equals(action)) { String addressDevice = args.getString(0); if (bluetoothSocketMap.containsKey(addressDevice)){ callbackContext.success("true"); }else{ Log.d("BluetoothPlugin", "設備未連接!"); callbackContext.error("設備未連接!"); } } else if (ACTION_CONNECT.equals(action)) { try { String addressDevice = args.getString(0); if (bluetoothSocketMap.containsKey(addressDevice)){ Log.d("BluetoothPlugin", "該設備已連接,再也不從新進行連接"); callbackContext.success("該設備已連接!"); return true; } Log.d("BluetoothPlugin", "Connecting..."); BluetoothDevice bluetoothDevice = m_bluetoothAdapter .getRemoteDevice(addressDevice);
Method m = bluetoothDevice.getClass().getMethod( "createRfcommSocket", new Class[] { int.class }); BluetoothSocket bluetoothSocket = (BluetoothSocket) m.invoke( bluetoothDevice, 1); try { bluetoothSocket.connect(); } catch (IOException e) { Log.d("BluetoothPlugin", "connect fail: " + e.getMessage()); callbackContext.error("設備連接失敗: " + e.getMessage()); return false; } bluetoothSocketMap.put(addressDevice, bluetoothSocket); Log.d("BluetoothPlugin", addressDevice+ " 設備連接成功"); callbackContext.success("設備連接成功!"); } catch (Exception e) { Log.e("BluetoothPlugin", e.toString() + " / " + e.getMessage()); callbackContext.error("連接失敗: " + e.getMessage()); } } else if (ACTION_DISCONNECT.equals(action)) { String addressDevice = args.getString(0); if (bluetoothSocketMap.containsKey(addressDevice)){ BluetoothSocket bluetoothSocket = (BluetoothSocket)bluetoothSocketMap.get(addressDevice); Log.d("BluetoothPlugin", addressDevice+"斷開連接操做中..."); try { bluetoothSocket.close(); } catch (IOException e) { // TODO Auto-generated catch block Log.e("BluetoothPlugin", e.toString() + " / " + e.getMessage()); callbackContext.error("斷開連接失敗: " + e.getMessage()); return false; } bluetoothSocketMap.remove(addressDevice); bluetoothSocket = null; Log.d("BluetoothPlugin", addressDevice+"已成功斷開連接"); callbackContext.success("已成功解除設備連接!"); }else{ Log.d("BluetoothPlugin", addressDevice+" 設備無可用連接可斷開,請從新確認!"); callbackContext.success("該設備無可用連接可斷開,請從新確認!"); } } else if (ACTION_WRITE_STRING.equals(action)) { if (m_bluetoothAdapter.isDiscovering()) { m_bluetoothAdapter.cancelDiscovery(); } try { String addressDevice = args.getString(0); final String message = args.getString(1); final String encoding = args.getString(2); if (!isReady(callbackContext, addressDevice)){ return false; } BluetoothSocket bluetoothSocket = (BluetoothSocket)bluetoothSocketMap.get(addressDevice); Log.d("BluetoothPlugin", "開始寫入數據:"+message); OutputStream outputStream = bluetoothSocket .getOutputStream(); byte[] bytes = message.getBytes(encoding); outputStream.write(bytes); Log.d("BluetoothPlugin", "寫入數據成功"); callbackContext.success(message);
} catch (Exception Ex) { Log.d("BluetoothPlugin", ACTION_WRITE_STRING + " Got Exception " + Ex.getMessage()); callbackContext.error(Ex.getMessage()); } } else if (ACTION_WRITE_ASCII.equals(action)) { if (m_bluetoothAdapter.isDiscovering()) { m_bluetoothAdapter.cancelDiscovery(); } try { String addressDevice = args.getString(0); final String ascii = args.getString(1);
if (!isReady(callbackContext, addressDevice)){ return false; }
BluetoothSocket bluetoothSocket = (BluetoothSocket)bluetoothSocketMap.get(addressDevice);
Log.d("BluetoothPlugin", "開始寫入數據:"+ascii); OutputStream outputStream = bluetoothSocket .getOutputStream(); byte[] bytes = toASCII(ascii); outputStream.write(bytes);
Log.d("BluetoothPlugin", "寫入數據成功"); callbackContext.success(ascii); } catch (Exception Ex) { Log.d("BluetoothPlugin", ACTION_WRITE_ASCII + " Got Exception " + Ex.getMessage()); callbackContext.error(Ex.getMessage()); } }else { callbackContext.error("Action '" + action + "' not supported"); return false; } } return true; }
public void setDiscovering(boolean state) { m_discovering = state; }
/** * Receives activity results */ @Override public void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == 1) { m_stateChanging = false; } }
@Override public void onDestroy() { // TODO Auto-generated method stub Log.i("BluetoothPlugin", "onDestroy " + this.getClass()); cordova.getActivity().unregisterReceiver(m_bpBroadcastReceiver); super.onDestroy(); }
/** * Helper class for handling all bluetooth based events */ private class BPBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Log.d("BluetoothPlugin", "Action: " + action); // Check if we found a new device if (BluetoothDevice.ACTION_FOUND.equals(action)) { BluetoothDevice bluetoothDevice = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); try { JSONObject deviceInfo = new JSONObject(); if (bluetoothDevice.getBondState() == BluetoothDevice.BOND_BONDED) { deviceInfo.put("name", bluetoothDevice.getName() + "(已綁定)"); } else { deviceInfo.put("name", bluetoothDevice.getName()); } deviceInfo.put("address", bluetoothDevice.getAddress()); m_discoveredDevices.put(deviceInfo); Log.i("BluetoothPlugin", "Device[" + bluetoothDevice.getName() + " " + bluetoothDevice.getAddress() + "] add to discoveredDevices"); } catch (JSONException e) { Log.e("BluetoothPlugin", e.getMessage()); } } else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) { Log.i("BluetoothPlugin", "Discovery started"); setDiscovering(true); } // Check if we finished discovering devices else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { Log.i("BluetoothPlugin", "Discovery finished"); setDiscovering(false); } } };
/** * 開始寫數據前,相關前置條件是否準備好 * @param callbackContext * @param addressDevice * @return */ private boolean isReady(CallbackContext callbackContext, String addressDevice){ if (!m_bluetoothAdapter.isEnabled()){ Log.d("BluetoothPlugin", "m_bluetoothAdapter isEnabled 不可用,沒法寫入."); callbackContext.error("藍牙適配器暫不能用,沒法寫入數據!"); return false; }
BluetoothDevice bluetoothDevice = m_bluetoothAdapter .getRemoteDevice(addressDevice);
if (bluetoothDevice == null){//找不到設備 Log.d("BluetoothPlugin", "系統找不到藍牙設備,沒法寫入."); callbackContext.error("系統找不到藍牙設備,沒法寫入數據!"); return false; }
if (bluetoothDevice.getBondState() != BluetoothDevice.BOND_BONDED){//已綁定連接 Log.d("BluetoothPlugin", "該設備未綁定,沒法寫入."); callbackContext.error("該設備未綁定,沒法寫入數據!"); return false; }
if (!bluetoothSocketMap.containsKey(addressDevice)){ Log.d("BluetoothPlugin", "該設備未連接,沒法寫入."); callbackContext.error("該設備未連接,沒法寫入數據!"); return false; }
return true; }
private byte[] toASCII(String ascii) { try { String[] as = ascii.split(","); byte[] bytes = new byte[as.length]; for (int i = 0; i < as.length; i++) { bytes[i] = (byte) Integer.parseInt(as[i]); } return bytes; } catch (Exception e) { Log.d("BluetoothPlugin", "Invalid ASCII code."); return null; } }
}
--------------------------------------------------------
頁面調用
function writeString() { window.plugins.BluetoothPlugin.writeASCII( '設備MAC地址', '27,64' //藍牙打印設備狀態重置、初始化 ); window.plugins.BluetoothPlugin.writeString( function(message) { alert(message); }, function(error) { alert( 'Error: ' + error ); }, '設備MAC地址', $('#msg').val(), 'GBK' ); window.plugins.BluetoothPlugin.writeASCII( '設備MAC地址', '10,10,10,10' //換行打印 ); }