package com.safemobile.bluetooth; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Timer; import java.util.TimerTask; import java.util.UUID; import com.safemobile.bluetooth.BlueEvent; import com.safemobile.bluetooth.IBlueListener; import com.safemobile.lib.AppParams; import com.safemobile.lib.R; import com.safemobile.lib.SM; import android.annotation.TargetApi; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothSocket; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.media.AudioManager; import android.os.AsyncTask; import android.os.Build; import android.os.Handler; import android.util.Log; import android.widget.Toast; @TargetApi(Build.VERSION_CODES.HONEYCOMB) public class BluetoothTether { private Context mContext; private Activity activity; private AudioManager audioManager; private BluetoothAdapter bluetoothAdapter; private BluetoothHeadset bluetoothHeadset = null; private BluetoothDevice bluetoothDevice= null; /* For bluComm Microphone */ private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private List _listeners = new ArrayList(); private Thread bluCommThread = null; private int bluetoothProfile; private BluetoothProfile bluetoothProxy; private BluetoothSocket bluetoothSocket = null; private InputStream inputStream =null; private Boolean socketIsConnected = false; public BluetoothTether(Context context, Activity activity) { this.mContext = context; this.activity = activity; audioManager = (AudioManager) activity.getSystemService(Context.AUDIO_SERVICE); bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); bluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET); IntentFilter filter1 = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED); IntentFilter filter2 = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED); IntentFilter filter3 = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED); activity.registerReceiver(mReceiver, filter1); activity.registerReceiver(mReceiver, filter2); activity.registerReceiver(mReceiver, filter3); filter3 = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); activity.registerReceiver(mReceiver, filter3); } private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() { @Override public void onServiceDisconnected(int profile) { } @Override public void onServiceConnected(int profile, BluetoothProfile proxy) { SM.Debug("###BluetoothProfile###", "###Connected###"); bluetoothProfile = profile; bluetoothProxy = proxy; if(profile == BluetoothProfile.HEADSET) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } bluetoothHeadset = (BluetoothHeadset) proxy; List test; test = bluetoothHeadset.getConnectedDevices(); SM.Debug("###BluetoothProfile###", "Headset Connected devices nr: " + test.size()); // check if one of three headsets are connected for(BluetoothDevice dev : test) bluetoothDevice = dev; /* if(dev.getAddress().contains(AppParams.MotorolaH730) || dev.getAddress().contains(AppParams.SamsungWep460) || dev.getAddress().contains(AppParams.BluCom)) bluetoothDevice = dev; */ if(bluetoothDevice!=null) { if(AppParams.TETHERSOUND) { SM.Debug("###BluetoothProfile###", "Device : " + bluetoothDevice.getName() + " [" + bluetoothDevice.getAddress() + "]"); new Handler().post(new Runnable() { @Override public void run() { Toast.makeText(mContext, String.format(mContext.getString(R.string.bthDeviceConnected), bluetoothDevice.getName()), Toast.LENGTH_SHORT).show(); TetherSound(bluetoothDevice, true); //* SM.Debug("### blueComm ###", "BLUEcOMMFunction"); new connectTask().execute(); //blueCommFunction(bluetoothProfile, bluetoothProxy); _fireBluetoothTethered(true); final Timer t = new Timer(); t.schedule(new TimerTask() { @Override public void run() { // start thread that will manage bluComm button press bluCommThread = new Thread(bluCommRunnable); bluCommThread.start(); t.cancel(); t.purge(); } }, 2500); //*/ } }); } } } } }; /** Function that will intercept bluComm button press */ private void blueCommFunction(int profile, BluetoothProfile proxy) { //Boolean result = true; SM.Debug("################"); if(profile == BluetoothProfile.HEADSET) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } // if device connected -> redundant check if(bluetoothDevice != null) { SM.Debug("###HEADSET###","Connected Device Address: " + bluetoothDevice.getAddress()); final Timer t = new Timer(); t.scheduleAtFixedRate(new TimerTask() { @Override public void run() { try { if(bluetoothDevice!=null) { // create socket and then connect to it bluetoothSocket = bluetoothDevice.createRfcommSocketToServiceRecord(MY_UUID); bluetoothSocket.connect(); inputStream = bluetoothSocket.getInputStream(); SM.Debug("##BTSocketConnected##", "Connection socket ok"); socketIsConnected = true; t.cancel(); t.purge(); } else { t.cancel(); t.purge(); } } catch (IOException e) { //result = false; //SM.Exception("###BTSocketError###", e.toString()); socketIsConnected = false; if(bluetoothSocket!=null) try { bluetoothSocket.close(); bluetoothSocket = null; } catch (IOException e1) { SM.Exception("###BTSocketError2###", e.toString()); } } try { Thread.sleep(1000); SM.Debug("BTSocketCreated", "bluetooth socket creation ended with result: " + socketIsConnected); /* if(result) _fireDataArrived(blueSOCKET,-1); else _fireDataArrived(noBlueSOCKET,-1); */ } catch (InterruptedException e) { SM.Exception("###BTSocketInterruptedException###", e.toString()); } } }, 500, 3000); } } }; /** Runnable to intercept bluComm button press */ private Runnable bluCommRunnable = new Runnable() { @Override public void run() { SM.Debug("####HERE####", "after Profile"); int read = 0; byte[] buffer = new byte[20]; while(true) { try { while (socketIsConnected) { //SM.Debug("####Socket####", "Socket is Connected"); try { //Log.d("DECIVE STATUS", bhead.getConnectionState(mybluedev) + ""); read = inputStream.read(buffer); /* String buf = ""; for(int k=0;k10) { _fireDataArrived(-1,0); Disconect(); } */ } } Thread.sleep(1000); } catch (InterruptedException e) { Log.d("bigutag", "Error on"); } } } }; /** BroadcastReceiver that will manage BlueTooth Connection and Disconnection */ public final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if(device!=null) Log.d("BlueTooth State Changed", "DEVICE " + device.getName() + " [" + device.getAddress() + "]" + " is now : " + action ); // Tether sound only if selected in setup if(AppParams.TETHERSOUND) { if(BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) { if(intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_OFF) untetherSound(bluetoothDevice); } else if (BluetoothDevice.ACTION_FOUND.equals(action)) { Toast.makeText(mContext, mContext.getString(R.string.bthDeviceFound) + ":" + bluetoothDevice.getName(), Toast.LENGTH_SHORT).show(); } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { //Toast.makeText(mContext, "Done searching", Toast.LENGTH_SHORT).show(); } else if(device.getAddress()!= null) /* && (device.getAddress().contains(AppParams.MotorolaH730) || device.getAddress().contains(AppParams.SamsungWep460) || device.getAddress().contains(AppParams.BluCom)))*/ { // save device bluetoothDevice = device; // if bluetooth device has disconnected if(action.contains("_DISCONNECTED")) { untetherSound(device); } // if bluetooth device had connected else { new Handler().post(new Runnable() { @Override public void run() { Toast.makeText(mContext, String.format(mContext.getString(R.string.bthDeviceConnected), bluetoothDevice.getName()), Toast.LENGTH_SHORT).show(); // set that bluComm Microphone is connected if(bluetoothDevice != null) { TetherSound(bluetoothDevice, true); if(bluetoothDevice.getAddress().contains(AppParams.BluCom)) { AppParams.BluCommState = 1; //TetherSound(bluetoothDevice, true); _fireBluetoothTethered(true); // create bluComm socket new connectTask().execute(); /* * if bluComm is not connected when RadioPad starts i will need * to create the Thread that reads on socket */ if(bluCommThread == null) { final Timer t = new Timer(); t.schedule(new TimerTask() { @Override public void run() { SM.Exception("bluComm", "creating blu comm thread"); // start thread that will manage bluComm button press bluCommThread = new Thread(bluCommRunnable); bluCommThread.start(); t.cancel(); t.purge(); } }, 2500); } } } } }); } } } } }; /** * UnTether all the sound when a device is disconnected or then the BlueTooth is turned off * @param device The BlueTooth device which needs to be unTethered */ private void untetherSound(final BluetoothDevice device) { new Handler().post(new Runnable() { @Override public void run() { if(device == null) return; Toast.makeText(mContext, String.format(mContext.getString(R.string.bthDeviceDisconnected), (bluetoothDevice.getName() == null ? "?" : bluetoothDevice.getName())), Toast.LENGTH_SHORT).show(); _fireBluetoothTethered(false); // set that bluComm Microphone is disconnected if(bluetoothDevice!=null && bluetoothDevice.getAddress().contains(AppParams.BluCom)) AppParams.BluCommState = 0; socketIsConnected = false; Disconect(); TetherSound(device, false); } }); } /** Unregister BroadcastReceiver **/ public void UnregisterReceiver() { try { if(mReceiver!=null && activity!=null) { SM.Debug("#### unregister Receiver ### ", "unregister receiver"); activity.unregisterReceiver(mReceiver); } if(mProfileListener!=null) activity.unbindService((ServiceConnection) mProfileListener); } catch(Exception ex) { } } /** Tether sound */ private void TetherSound(final BluetoothDevice device, Boolean enable) { if(enable && AppParams.TETHERSOUND) { final Timer t = new Timer(); t.schedule(new TimerTask() { @Override public void run() { SM.Debug("### Start Tethering ###", "tethering " + device.getName()); audioManager.setBluetoothScoOn(true); audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); audioManager.startBluetoothSco(); t.cancel(); t.purge(); } }, 2000); } else { audioManager.stopBluetoothSco(); audioManager.setMode(AudioManager.MODE_NORMAL); socketIsConnected = false; } } /** Stop BluetoothTether and unregister BroadcastReceiver */ public void Stop() { TetherSound(null, false); UnregisterReceiver(); Disconect(); } public void Disconect() { try { if(bluetoothSocket!=null) bluetoothSocket.close(); socketIsConnected = false; socketIsConnected = false; bluetoothDevice = null; bluetoothSocket = null; //bhead.stopVoiceRecognition(mybluedev); //_fireDataArrived(-1,0); } catch (Exception e) { socketIsConnected = false; bluetoothDevice = null; bluetoothSocket = null; SM.Exception("##BTDisconnectError",e.toString()); } } public synchronized void addBlueListener( IBlueListener l ) { _listeners.add( l ); } public synchronized void removeBlueListener( IBlueListener l ) { _listeners.remove( l ); } private synchronized void _fireDataArrived(int PTTClicked, int Connected) { BlueEvent event = new BlueEvent( this,PTTClicked,Connected); Iterator listeners = _listeners.iterator(); while( listeners.hasNext() ) { ( (IBlueListener) listeners.next() ).dataRecv(event); } } private synchronized void _fireBluetoothTethered (boolean isTethered) { Iterator listeners = _listeners.iterator(); while( listeners.hasNext() ) { ( (IBlueListener) listeners.next() ).bluetoothTethered(isTethered);; } } public class connectTask extends AsyncTask { @Override protected Void doInBackground(String... params) { SM.Debug("### blueComm ###", "recreate bluComm socket"); blueCommFunction(bluetoothProfile, bluetoothProxy); return null; } } }