safedispatch-mobile/libSafeMobile/src/main/java/com/safemobile/bluetooth/BluetoothTether.java

526 lines
16 KiB
Java

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<IBlueListener> _listeners = new ArrayList<IBlueListener>();
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<BluetoothDevice> 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;k<read;k++)
buf += buffer[k] + " | "; */
//SM.Debug("###SocketRead###", buf);
if (read==6)
{
if (buffer[5]==80)
{
SM.Debug("##BTpttPress##", "PTTON");
AppParams.BluCommState = 2;
_fireDataArrived(AppParams.PTTON,-1);
}
if (buffer[5]==82)
{
SM.Debug("##BTpttPress##", "PTTOFF");
AppParams.BluCommState = 1;
_fireDataArrived(AppParams.PTTOFF,-1);
}
}
}
catch (IOException e)
{
//Log.d("bigutag", "Error on read");
/*
cntError++;
if (cntError>10)
{
_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<IBlueListener> listeners = _listeners.iterator();
while( listeners.hasNext() ) {
( (IBlueListener) listeners.next() ).dataRecv(event);
}
}
private synchronized void _fireBluetoothTethered (boolean isTethered) {
Iterator<IBlueListener> listeners = _listeners.iterator();
while( listeners.hasNext() ) {
( (IBlueListener) listeners.next() ).bluetoothTethered(isTethered);;
}
}
public class connectTask extends AsyncTask<String, Void, Void>
{
@Override
protected Void doInBackground(String... params) {
SM.Debug("### blueComm ###", "recreate bluComm socket");
blueCommFunction(bluetoothProfile, bluetoothProxy);
return null;
}
}
}