526 lines
16 KiB
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;
|
|
}
|
|
}
|
|
}
|