I have an app that runs 3 threads at the same time. One thread is for stablishing a bluetooth connection between the phone and another bluetooth device (Arduino). Thread 2 plays audio incoming from another phone via bluetooh. Thread 3 records and sends audio to the other phone via bluetooth.
The audio communication works with lots of glitches if phone is trying to stablish a connection with the Arduino (when thread 1 is running bluetoothsocket.connect();). However, when phone does not try to stablish a connection with the Arduino or the connection is already stablished and thread 1 is done, then the communication is good.
Here is the code for thread 1 - arduino (this code is with a class)
public class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
// As mmSocket is final, we use a temporary socket variable
BluetoothSocket tmp = null;
mmDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(UUID);
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
// Cancel discovery because it will slow down the connection
mBluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
} catch (IOException closeException) { }
// Send the name of the disconnected device back to the UI Activity
sendDeviceConnectionToActivity(deviceMAC, false);
Log.d("Bluetoot connected -->", "NNNNNNNN" + connectException);
return;
}
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(mmSocket, mmDevice);
// mConnectedThread = new ConnectedThread(mmSocket);
// mConnectedThread.start();
Log.d("Bluetoot connected -->", mmDevice.getName());
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
the code for audio in thread 2 and 3 (this code is with a another class)
public void audioCreate() {
// Audio track object
track = new AudioTrack(AudioManager.STREAM_VOICE_CALL,
16000, AudioFormat.CHANNEL_OUT_MONO,
encoding, minSize, AudioTrack.MODE_STREAM);
// Audio record object
recorder = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, 16000,
AudioFormat.CHANNEL_IN_MONO, encoding,
bufferSize);
}
public void initiateBluetoothConexion(BluetoothDevice deviceSelected) {
// Toast.makeText(getApplicationContext(), "Service On", Toast.LENGTH_SHORT).show();
deviceMAC = deviceSelected.getAddress();
mBluetoothAdapter.cancelDiscovery();
// Cancel any thread attempting to make a connection
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
mConnectThread = new ConnectThread(deviceSelected);
mConnectThread.setPriority(10);
mConnectThread.start();
}
public class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
// As mmSocket is final, we use a temporary socket variable
BluetoothSocket tmp = null;
mmDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(UUID);
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_AUDIO);
// Cancel discovery because it will slow down the connection
mBluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
} catch (IOException closeException) { }
// Send the name of the disconnected device back to the UI Activity
sendDeviceConnectionToActivity(deviceMAC, false);
return;
}
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(mmSocket, mmDevice);
// mConnectedThread = new ConnectedThread(mmSocket);
// mConnectedThread.start();
Log.d("Bluetoot connected -->", mmDevice.getName());
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
private void manageConnectedSocket(BluetoothSocket mmSocket, BluetoothDevice mmDevice) {
// Cancel the thread that completed the connection
// if (mConnectThread != null) {
// mConnectThread.cancel();
// mConnectThread = null;
// }
// Cancel any thread currently running a connection
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(mmSocket);
mConnectedThread.setPriority(10);
mConnectedThread.start();
// Send the name of the connected device back to the UI Activity
Log.d(TAG, "Connected to " + mmDevice.getName());
sendDeviceConnectionToActivity(mmDevice.getAddress(), true);
// setState(STATE_CONNECTED);
}
public class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private byte buffer[] = null;
private byte playBuffer[] = null;
private boolean intercomm = false;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams; using temp objects because
// member streams are final.
try {
tmpIn = socket.getInputStream();
} catch (IOException e) {
Log.e(TAG, "Error occurred when creating input stream", e);
}
try {
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "Error occurred when creating output stream", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
intercomm = true;
}
public void run() {
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);
playBuffer = new byte[minSize];
// Playback received audio
track.play();
startRecording();
// receive recording until an exception occurs.
while (intercomm) {
try {
if (mmInStream.available() == 0) {
//Do nothing
} else {
mmInStream.read(playBuffer);
track.write(playBuffer, 0, playBuffer.length);
}
} catch (IOException e) {
Log.d("AUDIO", "Error when receiving recording");
sendDeviceConnectionToActivity(deviceMAC, false);
break;
}
}
}
// Record Audio
public void startRecording() {
Log.d("AUDIO", "Assigning recorder");
buffer = new byte[bufferSize];
// Start Recording
recorder.startRecording();
Log.d("startRecording", "passed");
// Start a thread
recordingThread = new Thread(new Runnable() {
#Override
public void run() {
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);
Log.d("startRecording", "sendRecording");
sendRecording();
}
}, "AudioRecorder Thread");
recordingThread.setPriority(10);
recordingThread.start();
}
// Method for sending Audio
public void sendRecording() {
// Infinite loop until microphone button is released
while (intercomm) {
try {
recorder.read(buffer, 0, bufferSize);
mmOutStream.write(buffer);
} catch (IOException e) {
Log.d("AUDIO", "Error when sending recording");
sendErrorsToActivity("Error sending audio");
}
}
}
// Call this method from the main activity to shut down the connection.
public void cancel() {
intercomm = false;
stopPlaying();
stopRecording();
destroyProcesses();
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close the connect socket", e);
}
}
// Stop playing and free up resources
public void stopPlaying() {
if (track != null) {
track.stop();
track.flush();
}
}
// Stop Recording and free up resources
public void stopRecording() {
if (recorder != null) {
recorder.stop();
}
}
public void destroyProcesses() {
//Release resources for audio objects
track.release();
recorder.release();
}
}
I tested the code in an octacore android oreo. However, when I did it in an phone sdk 23, it was worst.
Your AudioTrack is starving because it is not receiving data quickly enough from the arduino. This is most likely due to increased network contention during the BT connection process.
You appear to be configuring your AudioTrack with the smallest possible play-buffer. On most devices, this is only a few ms of audio, so if the AudioTrack isn't fed more data every few ms, it will starve, and you will hear a glitch.
One solution is to increase the AudioTrack's buffer size (perhaps to around 8000 samples or more).
In addition, you have not checked the return value from mmInStream.read(), which means you may be trying to "play" a playBuffer that is only partially filled.
Altering the thread priorities, as you are, is unlikely to make a qualitative difference.
Related
I'm working with Bluetooth in android.My main goal is to transmit large video file via Bluetooth.
I'm following Bluetooth chat sample for connectivity.
Actually i convert video into byte array and then in onRecieve method convert back to File.
when converting back to file some exception occurs.
I increased the buffer size in connected Thread.
To convert recieved byte[] into Hashmap<String, Byte[]>
private Object convertFromBytes(byte[] bytes) {
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
Object out = null;
ObjectInput in = null;
try {
in = new ObjectInputStream(bis);
out = in.readObject();
Log.d("bytetodata out", "");
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
Log.d("bytetodata out", e.getLocalizedMessage());
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException ex) {
Log.e(TAG, ex.getLocalizedMessage());
// ignore close exception
}
}
Log.d("bytetodata out", "");
return out;
}
Exception occurs at
in = new ObjectInputStream(bis);
Bluetooth Reciever code
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
onRecieve(readBuf);
private void onRecieve(byte[] readBuf) {
HashMap<String, byte[]> receivedMap = (HashMap<String, byte[]>) convertFromBytes(readBuf);
//Log.d("recieveMAP Size" , String.valueOf(receivedMap.size()));
if (receivedMap != null && receivedMap.size() == 2) {
byte[] filebyte = receivedMap.get("file");
byte[] objectbyte = receivedMap.get("object");
if (filebyte != null) {
File file = new File("storage/emulated/0/Download/name.mp4");
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
Log.e("Mainactivity", e.getLocalizedMessage());
}
if (file.exists()) {
try {
FileUtils.writeByteArrayToFile(file, filebyte);
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, e.getLocalizedMessage());
}
} else {
//System.out.println("file created: " + file);
Toast.makeText(context, "File is Empty", Toast.LENGTH_LONG).show();
}
} else {
Log.e(TAG, "selected video path = null!");
}
//System.out.println("file created: " + file);
//Toast.makeText(context, "File Created", Toast.LENGTH_LONG).show();
// Video video = (Video) convertFromBytes(objectbyte);
}
}
Bluetooth Connectivity code
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[ 4096 * 16 ];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(BTListFragment.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
connectionLost();
break;
}
}
}
/**
* Write to the connected OutStream.
*
* #param buffer The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(BTListFragment.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
}
BlutoothConnectivityService.java
package com.example.accessagriculture.Utils;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import com.example.accessagriculture.Views.Fragments.BTListFragment;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
/**
* This class does all the work for setting up and managing Bluetooth
* connections with other devices. It has a thread that listens for
* incoming connections, a thread for connecting with a device, and a
* thread for performing data transmissions when connected.
*/
public class BTConnectService {
// Name for the SDP record when creating server socket
private static final String NAME = "BluetoothChat";
// Unique UUID for this application
private static final UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
// Member fields
private final BluetoothAdapter mAdapter;
private final Handler mHandler;
private AcceptThread mAcceptThread;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
private int mState;
// Constants that indicate the current connection state
public static final int STATE_NONE = 0; // we're doing nothing
public static final int STATE_LISTEN = 1; // now listening for incoming connections
public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
public static final int STATE_CONNECTED = 3; // now connected to a remote device
/**
* Constructor. Prepares a new BluetoothChat session.
* #param handler A Handler to send messages back to the UI Activity
*/
public BTConnectService(Handler handler) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
mHandler = handler;
}
/**
* Set the current state of the chat connection
*
* #param state An integer defining the current connection state
*/
private synchronized void setState(int state) {
mState = state;
// Give the new state to the Handler so the UI Activity can update
mHandler.obtainMessage(BTListFragment.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}
/**
* Return the current connection state.
*/
public synchronized int getState() {
return mState;
}
/**
* Start the chat service. Specifically start AcceptThread to begin a
* session in listening (server) mode. Called by the Activity onResume()
*/
public synchronized void start() {
// Cancel any thread attempting to make a connection
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
// Cancel any thread currently running a connection
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
// Start the thread to listen on a BluetoothServerSocket
if (mAcceptThread == null) {
mAcceptThread = new AcceptThread();
mAcceptThread.start();
}
setState(STATE_LISTEN);
}
/**
* Start the ConnectThread to initiate a connection to a remote device.
*
* #param device The BluetoothDevice to connect
*/
public synchronized void connect(BluetoothDevice device) {
// Cancel any thread attempting to make a connection
if (mState == STATE_CONNECTING) {
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
}
// Cancel any thread currently running a connection
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
// Start the thread to connect with the given device
mConnectThread = new ConnectThread(device);
mConnectThread.start();
setState(STATE_CONNECTING);
}
/**
* Start the ConnectedThread to begin managing a Bluetooth connection
*
* #param socket The BluetoothSocket on which the connection was made
* #param device The BluetoothDevice that has been connected
*/
public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
// Cancel the thread that completed the connection
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
// Cancel any thread currently running a connection
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
// Cancel the accept thread because we only want to connect to one device
if (mAcceptThread != null) {
mAcceptThread.cancel();
mAcceptThread = null;
}
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(socket);
mConnectedThread.start();
// Send the name of the connected device back to the UI Activity
Message msg = mHandler.obtainMessage(BTListFragment.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(BTListFragment.DEVICE_NAME, device.getName());
msg.setData(bundle);
mHandler.sendMessage(msg);
setState(STATE_CONNECTED);
}
/**
* Stop all threads
*/
public synchronized void stop() {
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
if (mAcceptThread != null) {
mAcceptThread.cancel();
mAcceptThread = null;
}
setState(STATE_NONE);
}
/**
* Write to the ConnectedThread in an unsynchronized manner
*
* #param out The bytes to write
* #see ConnectedThread#write(byte[])
*/
public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != STATE_CONNECTED) return;
r = mConnectedThread;
}
// Perform the write unsynchronized
r.write(out);
}
/**
* Indicate that the connection attempt failed and notify the UI Activity.
*/
private void connectionFailed() {
setState(STATE_LISTEN);
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(BTListFragment.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(BTListFragment.TOAST, "Unable to connect device");
msg.setData(bundle);
mHandler.sendMessage(msg);
}
/**
* Indicate that the connection was lost and notify the UI Activity.
*/
private void connectionLost() {
//setState(STATE_LISTEN);
// Send a failure message back to the Activity
/*Message msg = mHandler.obtainMessage(BTListFragment.MESSAGE_TOAST);
//Bundle bundle = new Bundle();
// bundle.putString(BTListFragment.TOAST, "Device connection was lost");
msg.setData(bundle);
mHandler.sendMessage(msg);*/
}
/**
* This thread runs while listening for incoming connections. It behaves
* like a server-side client. It runs until a connection is accepted
* (or until cancelled).
*/
private class AcceptThread extends Thread {
// The local server socket
private final BluetoothServerSocket mmServerSocket;
public AcceptThread() {
BluetoothServerSocket tmp = null;
// Create a new listening server socket
try {
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
} catch (IOException e) {
}
mmServerSocket = tmp;
}
public void run() {
setName("AcceptThread");
BluetoothSocket socket = null;
// Listen to the server socket if we're not connected
while (mState != STATE_CONNECTED) {
try {
// This is a blocking call and will only return on a
// successful connection or an exception
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
synchronized (BTConnectService.this) {
switch (mState) {
case STATE_LISTEN:
case STATE_CONNECTING:
// Situation normal. Start the connected thread.
connected(socket, socket.getRemoteDevice());
break;
case STATE_NONE:
case STATE_CONNECTED:
// Either not ready or already connected. Terminate new socket.
try {
socket.close();
} catch (IOException e) {
}
break;
}
}
}
}
}
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) {
}
}
}
/**
* This thread runs while attempting to make an outgoing connection
* with a device. It runs straight through; the connection either
* succeeds or fails.
*/
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
}
mmSocket = tmp;
}
public void run() {
setName("ConnectThread");
// Always cancel discovery because it will slow down a connection
mAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mmSocket.connect();
} catch (IOException e) {
connectionFailed();
// Close the socket
try {
mmSocket.close();
} catch (IOException e2) {
}
// Start the service over to restart listening mode
BTConnectService.this.start();
return;
}
// Reset the ConnectThread because we're done
synchronized (BTConnectService.this) {
mConnectThread = null;
}
// Start the connected thread
connected(mmSocket, mmDevice);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
}
/**
* This thread runs during a connection with a remote device.
* It handles all incoming and outgoing transmissions.
*/
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(BTListFragment.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
connectionLost();
break;
}
}
}
/**
* Write to the connected OutStream.
*
* #param buffer The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(BTListFragment.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
}
}
The coding frame with ObjectOutputStream. On the sender site
HashMap<String, Object> hm = new HashMap<>();
...
ByteArrayOutputStream bao = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bao);
oos.writeObject(hm);
Socket.getOutputStream().write(bao.toByteArray()); // send the
...
on the receiver site
private Object convertFromBytes(byte[] bytes) {
... // your codes
}
I'm sorry. I missed to read that you send the bytes in chunks. But, normally the sending takes over the sending package (chunked or not) and the receiving task is responsible for the assembling the chunks. Since you work explicitly with ChunkOutputStream and ChunkInputStream
I have a 2 fragment and i have to call bluetooth connection class in the both of them. 1.st fragment connected devices and second i try to send message but i cant because this error.
This error very tired to me because i can not find any solutions.What is the reason of the this problem. Please help me how can i fix it ?
D/BluetoothConnectionServ2: write: Write Called.
write: Writing to outputstream: g yh6gg6
E/BluetoothConnectionServ2: write: Error writing to output stream. socket closed
That because of the :
(But i can not solve now)
(I am waiting your help)
I have to connect device on the other Fragment. Because my Connection not live. So if i call the this line again on the fragment:
mBluetoothService.startClient(device,MY_UUID_INSECURE);
So if i called this way. Mybluetooth Connection class close other connection and close socket so i have a error. So i have to keep connection.
But now how can i find solution ?
BluetoothConnection Service:
public class BluetoothConnectionService2 {
private static final String TAG = "BluetoothConnectionServ";
private static final String appName = "MYAPP";
private static final UUID MY_UUID_INSECURE =
UUID.fromString("90fe5f0d-823c-4215-b5ff-e96ad59d62cc");
private final BluetoothAdapter mBluetoothAdapter;
Context mContext;
private AcceptThread mInsecureAcceptThread;
private ConnectThread mConnectThread;
private BluetoothDevice mmDevice;
private UUID deviceUUID;
ProgressDialog mProgressDialog;
private ConnectedThread mConnectedThread;
public BluetoothConnectionService2(Context context) {
mContext = context;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
start();
}
/**
* This thread runs while listening for incoming connections. It behaves
* like a server-side client. It runs until a connection is accepted
* (or until cancelled).
*/
private class AcceptThread extends Thread {
// The local server socket
private final BluetoothServerSocket mmServerSocket;
public AcceptThread(){
BluetoothServerSocket tmp = null;
// Create a new listening server socket
try{
tmp = mBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(appName,MY_UUID_INSECURE);
Log.d(TAG, "AcceptThread: Setting up Server using: " + MY_UUID_INSECURE);
}catch (IOException e){
Log.e(TAG, "AcceptThread: IOException: " + e.getMessage() );
}
mmServerSocket = tmp;
}
public void run(){
Log.d(TAG, "run: AcceptThread Running.");
BluetoothSocket socket = null;
try{
// This is a blocking call and will only return on a
// successful connection or an exception
Log.d(TAG, "run: RFCOM server socket start.....");
socket = mmServerSocket.accept();
Log.d(TAG, "run: RFCOM server socket accepted connection.");
}catch (IOException e){
Log.e(TAG, "AcceptThread: IOException: " + e.getMessage() );
}
//talk about this is in the 3rd
if(socket != null){
connected(socket,mmDevice);
}
Log.i(TAG, "END mAcceptThread ");
}
public void cancel() {
Log.d(TAG, "cancel: Canceling AcceptThread.");
try {
mmServerSocket.close();
} catch (IOException e) {
Log.e(TAG, "cancel: Close of AcceptThread ServerSocket failed. " + e.getMessage() );
}
}
}
/**
* This thread runs while attempting to make an outgoing connection
* with a device. It runs straight through; the connection either
* succeeds or fails.
*/
private class ConnectThread extends Thread {
private BluetoothSocket mmSocket;
public ConnectThread(BluetoothDevice device, UUID uuid) {
Log.d(TAG, "ConnectThread: started.");
mmDevice = device;
deviceUUID = uuid;
}
public void run(){
mBluetoothAdapter.cancelDiscovery();
BluetoothSocket tmp = null;
Log.i(TAG, "RUN mConnectThread ");
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
Log.d(TAG, "ConnectThread: Trying to create InsecureRfcommSocket using UUID: "
+MY_UUID_INSECURE );
tmp = mmDevice.createRfcommSocketToServiceRecord(deviceUUID);
} catch (IOException e) {
Log.e(TAG, "ConnectThread: Could not create InsecureRfcommSocket " + e.getMessage());
}
mmSocket = tmp;
// Always cancel discovery because it will slow down a connection
mBluetoothAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
mmSocket.connect();
Thread.sleep(3000);
Log.d(TAG, "run: ConnectThread connected.");
} catch (IOException e) {
// Close the socket
try {
mmSocket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
Log.d(TAG, "run: ConnectThread: Could not connect to UUID: " + MY_UUID_INSECURE );
} catch (InterruptedException e) {
e.printStackTrace();
}
connected(mmSocket,mmDevice);
}
public void cancel() {
try {
Log.d(TAG, "cancel: Closing Client Socket.");
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "cancel: close() of mmSocket in Connectthread failed. " + e.getMessage());
}
}
}
/**
* Start the chat service. Specifically start AcceptThread to begin a
* session in listening (server) mode. Called by the Activity onResume()
*/
public synchronized void start() {
Log.d(TAG, "start");
// Cancel any thread attempting to make a connection
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mInsecureAcceptThread == null) {
mInsecureAcceptThread = new AcceptThread();
mInsecureAcceptThread.start();
}
}
/**
AcceptThread starts and sits waiting for a connection.
Then ConnectThread starts and attempts to make a connection with the other devices AcceptThread.
**/
public synchronized void startClient(BluetoothDevice device,UUID uuid){
Log.d(TAG, "startClient: Started.");
//initprogress dialog
mProgressDialog = ProgressDialog.show(mContext,"Connecting Bluetooth"
,"Please Wait...",true);
mConnectThread = new ConnectThread(device, uuid);
mConnectThread.start();
}
/**
Finally the ConnectedThread which is responsible for maintaining the BTConnection, Sending the data, and
receiving incoming data through input/output streams respectively.
**/
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
Log.d(TAG, "ConnectedThread: Starting.");
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
//dismiss the progressdialog when connection is established
try{
mProgressDialog.dismiss();
}catch (NullPointerException e){
e.printStackTrace();
}
try {
tmpIn = mmSocket.getInputStream();
tmpOut = mmSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run(){
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
}
//Call this from the main activity to send data to the remote device
public void write(byte[] bytes) {
String text = new String(bytes, Charset.defaultCharset());
Log.d(TAG, "write: Writing to outputstream: " + text);
try {
mmOutStream.write(bytes);
Thread.sleep(3000);
mmOutStream.flush();
} catch (IOException e) {
Log.e(TAG, "write: Error writing to output stream. " + e.getMessage() );
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
private void connected(BluetoothSocket mmSocket, BluetoothDevice mmDevice) {
Log.d(TAG, "connected: Starting.");
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(mmSocket);
mConnectedThread.start();
}
/**
* Write to the ConnectedThread in an unsynchronized manner
*
* #param out The bytes to write
* #see ConnectedThread#write(byte[])
*/
public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
if(mConnectedThread==null){
}
// Synchronize a copy of the ConnectedThread
Log.d(TAG, "write: Write Called.");
//perform the write
mConnectedThread.write(out);
}
}
You should keep live your connection this is true.But if fragments will close same time connection will stop.You should not close first fragment maybe you can make invisible first fragment.
My Application contains 3 Activities -
MainActivity.java
Write.java
BluetoothConnectionService.java
BluetoothConnectionService.java
public class BluetoothConnectionService {
private static final String TAG = "BluetoothConnectionServ";
private static final String appName = "MYAPP";
private static final UUID MY_UUID_INSECURE =
UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");
private final BluetoothAdapter mBluetoothAdapter;
Context mContext;
private AcceptThread mInsecureAcceptThread;
private ConnectThread mConnectThread;
private BluetoothDevice mmDevice;
private UUID deviceUUID;
ProgressDialog mProgressDialog;
private ConnectedThread mConnectedThread;
public BluetoothConnectionService(Context context) {
mContext = context;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//start();
}
/**
* This thread runs while listening for incoming connections. It behaves
* like a server-side client. It runs until a connection is accepted
* (or until cancelled).
*/
private class AcceptThread extends Thread {
// The local server socket
private final BluetoothServerSocket mmServerSocket;
public AcceptThread(){
BluetoothServerSocket tmp = null;
// Create a new listening server socket
try{
tmp = mBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(appName, MY_UUID_INSECURE);
Log.d(TAG, "AcceptThread: Setting up Server using: " + MY_UUID_INSECURE);
}catch (IOException e){
Log.e(TAG, "AcceptThread: IOException: " + e.getMessage() );
}
mmServerSocket = tmp;
}
public void run(){
Log.d(TAG, "run: AcceptThread Running.");
BluetoothSocket socket = null;
try{
// This is a blocking call and will only return on a
// successful connection or an exception
Log.d(TAG, "run: RFCOM server socket start.....");
socket = mmServerSocket.accept();
Log.d(TAG, "run: RFCOM server socket accepted connection.");
}catch (IOException e){
Log.e(TAG, "AcceptThread: IOException: " + e.getMessage() );
}
if(socket != null){
connected(socket,mmDevice);
}
Log.i(TAG, "END mAcceptThread ");
}
public void cancel() {
Log.d(TAG, "cancel: Canceling AcceptThread.");
try {
mmServerSocket.close();
} catch (IOException e) {
Log.e(TAG, "cancel: Close of AcceptThread ServerSocket failed. " + e.getMessage() );
}
}
}
/**
* This thread runs while attempting to make an outgoing connection
* with a device. It runs straight through; the connection either
* succeeds or fails.
*/
private class ConnectThread extends Thread {
private BluetoothSocket mmSocket;
public ConnectThread(BluetoothDevice device, UUID uuid) {
Log.d(TAG, "ConnectThread: started.");
mmDevice = device;
deviceUUID = uuid;
}
public void run(){
BluetoothSocket tmp = null;
Log.i(TAG, "RUN mConnectThread ");
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
Log.d(TAG, "ConnectThread: Trying to create InsecureRfcommSocket using UUID: "
+MY_UUID_INSECURE );
tmp = mmDevice.createRfcommSocketToServiceRecord(deviceUUID);
} catch (IOException e) {
Log.e(TAG, "ConnectThread: Could not create InsecureRfcommSocket " + e.getMessage());
}
mmSocket = tmp;
// Always cancel discovery because it will slow down a connection
mBluetoothAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mmSocket.connect();
Log.d(TAG, "run: ConnectThread connected.");
//mProgressDialog.cancel();
//Toast.makeText(mContext,"Connected", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
// Close the socket
try {
mmSocket.close();
Log.d(TAG, "run: Closed Socket.");
} catch (IOException e1) {
Log.e(TAG, "mConnectThread: run: Unable to close connection in socket " + e1.getMessage());
}
Log.d(TAG, "run: ConnectThread: Could not connect to UUID: " + MY_UUID_INSECURE );
}
connected(mmSocket,mmDevice);
}
public void cancel() {
try {
Log.d(TAG, "cancel: Closing Client Socket.");
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "cancel: close() of mmSocket in Connectthread failed. " + e.getMessage());
}
}
}
private void connected(BluetoothSocket mmSocket, BluetoothDevice mmDevice) {
Log.d(TAG, "connected: Starting.");
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(mmSocket);
mConnectedThread.start();
//start new activity
Intent intent = new Intent(mContext, Write.class);
mContext.startActivity(intent);
}
/**
Finally the ConnectedThread which is responsible for maintaining the BTConnection, Sending the data, and
receiving incoming data through input/output streams respectively.
**/
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
Log.d(TAG, "ConnectedThread: Starting.");
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
//dismiss the progress dialog when connection is established
try{
mProgressDialog.dismiss();
}catch (NullPointerException e){
e.printStackTrace();
}
try {
tmpIn = mmSocket.getInputStream();
tmpOut = mmSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run(){
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
// Read from the InputStream
try {
bytes = mmInStream.read(buffer);
String incomingMessage = new String(buffer, 0, bytes);
Log.d(TAG, "InputStream: " + incomingMessage);
Intent incomingMessageIntent = new Intent("incomingMessage");
incomingMessageIntent.putExtra("theMessage", incomingMessage);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(incomingMessageIntent);
Log.d(TAG, "broadcast sent");
} catch (IOException e) {
Log.e(TAG, "write: Error reading Input Stream. " + e.getMessage() );
break;
}
}
}
//Call this from the main activity to send data to the remote device
/*public void write(byte[] bytes) {
String text = new String(bytes, Charset.defaultCharset());
Log.d(TAG, "write: Writing to outputstream: " + text);
try {
mmOutStream.write(bytes);
} catch (IOException e) {
Log.e(TAG, "write: Error writing to output stream. " + e.getMessage() );
}
}*/
public void write(String input) {
byte[] msgBuffer = input.getBytes(); //converts entered String into bytes
try {
mmOutStream.write(msgBuffer); //write bytes over BT connection via outstream
} catch (IOException e) {
//if you cannot write, close the application
Toast.makeText(mContext, "Connection Failure", Toast.LENGTH_LONG).show();
}
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
public void start() {
Log.d(TAG, "start");
// Cancel any thread attempting to make a connection
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mInsecureAcceptThread == null) {
mInsecureAcceptThread = new AcceptThread();
mInsecureAcceptThread.start();
}
}
public void startClient(BluetoothDevice device,UUID uuid){
Log.d(TAG, "startClient: Started.");
//init progress dialog
mProgressDialog = ProgressDialog.show(mContext,"Connecting Bluetooth"
,"Please Wait...",true);
mConnectThread = new ConnectThread(device, uuid);
mConnectThread.start();
}
/**
* Write to the ConnectedThread in an unsynchronized manner
*
*/
public void write() {
// Create temporary object
//ConnectedThread r;
// Synchronize a copy of the ConnectedThread
Log.d(TAG, "write: Write Called.");
//perform the write
mConnectedThread.write("1");
}
}
PROBLEM:-
From the MainActivity, I created a BluetoothConnectionService object
BluetoothConnectionService mBluetoothConnection = new BluetoothConnectionService(MainActivity.this);
Then, I called startClient(device,uuid) method on mBluetoothConnection object
mBluetoothConnection.startClient(device,uuid);
Now, after successful connection is made, I can send out data to other devices by calling write() from the MainActivity
mBluetoothConnection.write();
But I don't want to send out data from MainActivity instead I want to use Write activity to send data out. How can I do that?
The Code you are using is provided by google Bluetooth chat application and they write using this:
In your Activity
private void sendMessage(String message) {
// Check that we're actually connected before trying anything
if (bluetoothConnectionService.getState() != BluetoothConnectionService.STATE_CONNECTED) {
Toast.makeText(MainActivity.this, R.string.not_connected, Toast.LENGTH_SHORT).show();
return;
}
// Check that there's actually something to send
if (message.length() > 0) {
// Get the message bytes and tell the BluetoothConnectionService to write
byte[] send = message.getBytes();
bluetoothConnectionService.write(send);
// Reset out string buffer to zero and clear the edit text field
mOutStringBuffer.setLength(0);
}
}
In the service add these two methods
/**
* Write to the ConnectedThread in an unsynchronized manner
*
* #param out The bytes to write
* #see ConnectedThread#write(byte[])
*/
public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != STATE_CONNECTED) return;
r = mConnectedThread;
}
// Perform the write unsynchronized
r.write(out);
}
/**
* Write to the connected OutStream.
*
* #param buffer The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
I have problem with connecting blutooth RfComm. I was able to connect to bluetooth and communicate but sometimes it doesn't connect. I am using standard uuid-00001101-0000-1000-8000-00805F9B34FB
please help me out :)
private class ConnectThread extends Thread {
private BluetoothSocket mmSocket;
private BluetoothDevice mmDevice;
private ConnectThread(BluetoothDevice device) {
Log.d(TAG, "in ConnectThread");
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
Log.d(TAG, "createRfcommSocketToServiceRecord for " + mmDevice.getName());
// MY_UUID is the app's UUID string, also used by the server code
tmp = mmDevice.createRfcommSocketToServiceRecord(MY_UUID);
//tmp = mmDevice.createInsecureRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
e.printStackTrace();
}
mmSocket = tmp;
}
public void run() {
Log.d(TAG, "in ConnectThread : run");
// Cancel discovery because it will slow down the connection
bluetoothAdapter.cancelDiscovery();
try {
Log.d(TAG, "Try to Connect Socket");
// Connect the device through the socket. This will block
mmSocket.connect();
} catch (IOException connectException) {
try {
Log.i(TAG, "Trying fallback...");
mmSocket = (BluetoothSocket) mmDevice.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(mmDevice, 1);
mmSocket.connect();
} catch (Exception e2) {
Log.e(TAG, "Couldn't establish Bluetooth connection!");
try {
mmSocket.close();
} catch (IOException e3) {
Log.e(TAG, "unable to close() socket during connection failure", e3);
}
return;
}
// Do work to manage the connection (in a separate thread)
mHandler.obtainMessage(SUCCESS_CONNECT, mmSocket).sendToTarget();
}
}
// Will cancel an in-progress connection, and close the socket
private void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private class ConnectedThread extends Thread implements Runnable {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
Log.d(TAG, "in ConnectedThread");
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
Log.d(TAG, "in ConnectedThread : run");
byte[] buffer; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
//Log.d(TAG,"in ConnectedThread : run -- while");
try {
try {
sleep(25);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Read from the InputStream
buffer = new byte[1024];
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI activity
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
break;
}
}
}
01-18 09:19:09.661 15692-16231/iconcreator.pidroid I/Main Activity :: Trying fallback...
01-18 09:19:09.661 2809-2873/? E/bt_btif_sock_rfcomm: find_rfc_slot_by_id unable to find RFCOMM slot id: 14
01-18 09:19:09.662 15692-16231/iconcreator.pidroid W/BluetoothAdapter: getBluetoothService() called with no BluetoothManagerCallback
01-18 09:19:09.743 16236-16236/? D/NetworkSecurityConfig: No Network Security Config specified, using platform default
01-18 09:19:09.846 2809-2859/? W/bt_rfcomm: port_rfc_closed RFCOMM connection in state 1 closed: Closed (res: 19)
01-18 09:19:09.846 15692-16231/iconcreator.pidroid E/Main Activity :: Couldn't establish Bluetooth connection!
01-18 09:19:09.847 2809-2873/? E/bt_btif_sock_rfcomm: find_rfc_slot_by_id unable to find RFCOMM slot id: 15
I am working with the Bluetooth chat example and I am trying to send "dummy" data in specific intervals from a thread that's active when the Bluetooth device is connected. Is it a good idea to start/stop another service to call a method in the original service every so often? How would I implement this?
private class ConnectedThread extends Thread {
static private final String TAG = "PhoneInfoConnectedThread";
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket, String socketType) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
Log.d(TAG, "In and out streams created");
} catch (IOException e) {
Log.e(TAG, "temp sockets not created " + e.getMessage());
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
// this is where we will spend out time when connected to the accessory.
public void run() {
// Keep listening to the InputStream while connected
while (true) {
// do whatever
}
}
// Write to the connected OutStream.
public void write(byte[] buffer) {
if (mmOutStream == null) {
Log.e(TAG, "ConnectedThread.write: no OutStream");
return;
}
try {
Log.d(TAG, "ConnectedThread.write: writing " + buffer.length
+ " bytes");
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
// mHandler.obtainMessage(PhoneInfoActivity.MESSAGE_WRITE, -1,
// -1, buffer).sendToTarget();
Log.d(TAG, "ConnectedThread.write: sent to calling activity");
} catch (IOException e) {
Log.e(TAG, "Exception during write" + e.getMessage());
}
}
public void cancel() {
try {
Log.d(TAG, "ConnectedThread.cancel: closing socket");
if (mmSocket != null)
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "ConnectedThread.cancel: socket.close() failed"
+ e.getMessage());
}
}
}
May this example help you.
MyTimerTask myTask = new MyTimerTask();
Timer myTimer = new Timer();
myTimer.schedule(myTask, 2000, 1000);
class MyTimerTask extends TimerTask {
public void run() {
Log.v("TAG","Message");
}
}
for more information see this