How do I engage a Bluetooth connection with another device? - java

I'm working on a app that will connect to a OBD2 device through Bluetooth, but I haven't yet figured out how to connect to a Bluetooth device.
I followed a video tutorial, and am currently following this tutorial with hopefully better luck, but I don't really understand how to implement the code since I can't see the full code (I'm a beginner).
Any help is appreciated!
Image:
(Here's where I want to press on a device and connect to it.)
BluetoothActivity:
package com.example.asabanov.powersupplytool;
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.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Set;
import java.util.UUID;
public class BluetoothActivity extends AppCompatActivity implements OnItemClickListener {
public static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
protected static final int SUCCESS_CONNECT = 0;
protected static final int MESSAGE_READ = 1;
ArrayAdapter<String> listAdapter;
ListView listView;
BluetoothAdapter btAdapter;
Set<BluetoothDevice> devicesArray;
ArrayList<String> pairedDevices;
ArrayList<BluetoothDevice> devices;
IntentFilter filter;
BroadcastReceiver receiver;
//String tag = "debugging";
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case SUCCESS_CONNECT:
//do something
ConnectedThread connectedThread = new ConnectedThread((BluetoothSocket) msg.obj);
Toast.makeText(getApplicationContext(), "Connect", Toast.LENGTH_SHORT).show();
String s = "Successfully connected";
connectedThread.write(s.getBytes());
break;
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
String string = new String(readBuf);
Toast.makeText(getApplicationContext(), "Connect", Toast.LENGTH_SHORT).show();
break;
}
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bluetooth);
init(); //initiate Bluetooth
if (btAdapter == null) {
Toast.makeText(getApplicationContext(), "No bluetooth detected on this device", Toast.LENGTH_SHORT).show();
finish();
} else {
if (!btAdapter.isEnabled()) {
turnOnBT();
}
pairedDevices=getPairedDevices();
startDiscovery();
}
}
private void startDiscovery() {
btAdapter.cancelDiscovery();
btAdapter.startDiscovery();
}
private void turnOnBT() {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 1);
}
private ArrayList getPairedDevices() {
devicesArray = btAdapter.getBondedDevices();
if (devicesArray.size() > 0) {
//add devices in array to list array
for (BluetoothDevice device : devicesArray) {
pairedDevices.add(device.getName() + "\n" + device.getAddress());
}
}
return pairedDevices;
}
private void init() {
listView = (ListView) findViewById(R.id.listView);
listView.setOnItemClickListener(this);
listAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, 0);
listView.setAdapter(listAdapter);
btAdapter = BluetoothAdapter.getDefaultAdapter();
pairedDevices = new ArrayList<String>();
filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
devices = new ArrayList<BluetoothDevice>();
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
devices.add(device);
String s = "";
for (int a = 0; a < pairedDevices.size(); a++) {
if (device.getName().equals(pairedDevices.get(a))) {
s = "Paired";
break;
}
}
// matt-hp (paired)
listAdapter.add(device.getName() + " " + s + " " + "\n" + device.getAddress());
} else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
//run some code
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
//run some code
} else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
if (btAdapter.getState() == btAdapter.STATE_OFF) {
turnOnBT();
}
}
}
};
registerReceiver(receiver, filter);
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
registerReceiver(receiver, filter);
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(receiver, filter);
filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(receiver, filter);
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(receiver, filter);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_CANCELED) {
Toast.makeText(getApplicationContext(), "Bluetooth must be enabled to continue", Toast.LENGTH_SHORT).show();
finish();
}
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (btAdapter.isDiscovering()) {
btAdapter.cancelDiscovery();
}
if (listAdapter.getItem(position).contains("Paired")) {
BluetoothDevice selectedDevice = devices.get(position);
ConnectThread connect = new ConnectThread(selectedDevice);
connect.start();
Toast.makeText(getApplicationContext(), "Device is paired", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "Device is not paired", Toast.LENGTH_SHORT).show();
}
}
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
// 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 {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
}
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
btAdapter.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) {
}
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
*/
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
}
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 input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void 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) {
try {
// 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;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) {
}
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
}
}

Related

How to reestablish a Bluetooth connection after I leave an activity in Android Studio?

I am working on a project that can send and receive Strings to and from an Arduino to control and monitor various sensors and lights. I am running into an issue where once I leave the activity that connects to Bluetooth and then return to that same activity after visiting the home activity I am no longer able to send and receive data. The sending and receiving of strings works perfectly until I leave the activity to go to the home activity and come back.
Here is the Java code for the sensor activity:
package com.example.arduinocontrol;
import androidx.appcompat.app.AppCompatActivity;
import androidx.cardview.widget.CardView;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class uvlight extends AppCompatActivity implements OnClickListener{
private static final int REQUEST_ENABLE_BT = 1;
private CardView uvLight;
//listeners for button presses
Button on, off,clear;
//textbox below buttons
TextView t1,t2,t3;
BluetoothAdapter mBluetoothAdapter;
BluetoothDevice mDevice;
ByteArrayInputStream mSocket;
ConnectedThread mConnectedThread = null;
ConnectThread mConnectThread = null;
#Override
protected void onCreate(Bundle savedInstanceState)
{
//Instantiation
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_uvlight);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
Toast.makeText(getApplicationContext(),"BT not supported!", Toast.LENGTH_SHORT).show();
return;
}
if (!mBluetoothAdapter.isEnabled()) {
//opens a window to ask user to turn on bluetooth
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
mDevice = device;
}
}
mConnectThread = new ConnectThread(mDevice);
mConnectThread.start();
try {
setw();
} catch (Exception e) {
e.printStackTrace();
}
}
#SuppressLint("ClickableViewAccessibility")
private void setw() throws IOException {
//text for bluetooth device details
t1=(TextView)findViewById(R.id.textView3);
t2=(TextView)findViewById(R.id.response);
t2.setMovementMethod(new ScrollingMovementMethod());
String name = mDevice.getName().toString();
try {
t1.setText("Connected to: " + name);
} catch (Exception e) {
e.printStackTrace();
}
//links on and off to their element IDs
on=(Button)findViewById(R.id.uvlighton);
off=(Button)findViewById(R.id.uvlightoff);
clear=(Button)findViewById(R.id.clear);
//clears log text
clear.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
t2.setText("");
}
});
on.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//sends 'o' char to Arduino
// method to turn on uv light
if(mConnectedThread != null) {
//String sig = "o";
//mConnectedThread.write(sig.getBytes());
int sig = 112;
mConnectedThread.write(sig);
}
}
});
off.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
//method to turn off uv light
if(mConnectedThread != null) {
//String sig1 = "f";
//mConnectedThread.write(sig1.getBytes());
int sig = 113;
mConnectedThread.write(sig);
}
}
});
}
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
//HC-05 unique uuid
private final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
public ConnectThread(BluetoothDevice device) {
BluetoothSocket tmp = null;
mmDevice = device;
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
try {
//creates RFCOMM socket
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
//shows user they are connected
Toast.makeText(getApplicationContext(), "Connected to your Arduino", Toast.LENGTH_SHORT).show();
//displays bt info in text field
} catch (IOException e) {
Toast.makeText(getApplicationContext(), "Unable to connect!", Toast.LENGTH_SHORT).show();
}
mmSocket = tmp;
}
public void run() {
mBluetoothAdapter.cancelDiscovery();
//need the if for this edge case
try {
mmSocket.connect();
} catch (IOException connectException) {
try {
if (mSocket != null) {
mSocket.close();
}
} catch (IOException closeException) {
Toast.makeText(getApplicationContext(), "Unable to connect socket!", Toast.LENGTH_SHORT).show();
}
return;
}
//new connected thread obj
mConnectedThread = new ConnectedThread(mmSocket);
mConnectedThread.start();
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//Thread for bluetooth process
private class ConnectedThread extends Thread {
//copies bt socket for threading
private final BluetoothSocket mmSocket;
//copies input stream obj for threading
private final InputStream mmInStream;
//copies output stream obj for threading
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = socket.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
try {
tmpOut = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
//reads from Arduino
#Override
public void run() {
byte[] buffer = new byte[1024];
int begin = 0;
int bytes = 0;
while (true) {
try {
bytes += mmInStream.read(buffer, bytes, buffer.length - bytes);
for (int i = begin; i < bytes; i++) {
//end char for a given message from Arduino
if (buffer[i] == "#".getBytes()[0]) {
mHandler.obtainMessage(1, begin, i, buffer).sendToTarget();
begin = i + 1;
if (i == bytes - 1) {
bytes = 0;
begin = 0;
}
}
}
} catch (IOException e) {
break;
}
}
}
//writes to the output stream (in this case the Arduino)
public void write(/*byte[] bytes*/int num) {
try {
Toast.makeText(getApplicationContext(), "sending bytes", Toast.LENGTH_SHORT).show();
mmOutStream.write(num);
} catch (IOException e) {
e.printStackTrace();
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onClick(View v)
{
try
{
}
catch (Exception e)
{
//displays toast message
Toast.makeText(getApplicationContext(),e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
//Suppresses an annoying handler lear warning
#SuppressLint("HandlerLeak")
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
byte[] writeBuf = (byte[]) msg.obj;
int begin = (int)msg.arg1;
int end = (int)msg.arg2;
switch(msg.what) {
case 1:
String writeMessage = new String(writeBuf);
writeMessage = writeMessage.substring(begin, end);
//sends message to homepage to turn cardview red
//string called error contains value of writeMessage
Intent intent = new Intent("errorCode").putExtra("error", writeMessage);
LocalBroadcastManager.getInstance(uvlight.this).sendBroadcast(intent);
//write message to the scrolling textbox
t2.append(writeMessage);
break;
}
}
};
}
Here is the Java code for the home activity:
package com.example.arduinocontrol;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.cardview.widget.CardView;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
public class HomeActivity extends AppCompatActivity implements View.OnClickListener {
private CardView airPump, flowMeter, humiditySensor, levelSwitch1, levelSwitch2, lightStrip, phMeter, uvLight, waterPump, solenoidValve, nutrientPump;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
//defines cards
airPump = (CardView) findViewById(R.id.airpump);
flowMeter = (CardView) findViewById(R.id.flowmeter);
humiditySensor = (CardView) findViewById(R.id.humiditysensor);
levelSwitch1 = (CardView) findViewById(R.id.levelswitch1);
levelSwitch2 = (CardView) findViewById(R.id.levelswitch2);
lightStrip = (CardView) findViewById(R.id.lightstrip);
phMeter = (CardView) findViewById(R.id.phmeter);
uvLight = (CardView) findViewById(R.id.uvlight);
waterPump = (CardView) findViewById(R.id.waterpump);
solenoidValve = (CardView) findViewById(R.id.solenoidvalve);
nutrientPump = (CardView) findViewById(R.id.nutrientpump);
//click listeners
airPump.setOnClickListener(this);
flowMeter.setOnClickListener(this);
humiditySensor.setOnClickListener(this);
levelSwitch1.setOnClickListener(this);
levelSwitch2.setOnClickListener(this);
lightStrip.setOnClickListener(this);
phMeter.setOnClickListener(this);
uvLight.setOnClickListener(this);
waterPump.setOnClickListener(this);
solenoidValve.setOnClickListener(this);
nutrientPump.setOnClickListener(this);
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, new IntentFilter("errorCode"));
}
//turns Uvlight card red when an error is sent
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String errorMsg = intent.getStringExtra("error");
if (errorMsg.equals("-3")){
uvLight.setCardBackgroundColor(0xFFFF0000);
}
}
};
#Override
public void onBackPressed() {
moveTaskToBack(true);
}
#Override
public void onClick(View v) {
Intent i;
//on click opens the new activity
switch(v.getId()){
case R.id.airpump : i = new Intent(this,Airpump.class); startActivity(i); break;
case R.id.flowmeter : i = new Intent(this,Flowmeter.class); startActivity(i); break;
case R.id.humiditysensor : i =new Intent(this,Humiditysensor.class); startActivity(i); break;
case R.id.levelswitch1 : i = new Intent(this,Levelswitch1.class); startActivity(i); break;
case R.id.levelswitch2 : i = new Intent(this,Levelswitch2.class); startActivity(i); break;
case R.id.lightstrip : i = new Intent(this,Lightstrip.class); startActivity(i); break;
case R.id.phmeter : i = new Intent(this,Phmeter.class); startActivity(i); break;
case R.id.uvlight : i = new Intent(this,uvlight.class); startActivity(i); break;
case R.id.waterpump : i = new Intent(this,Waterpump.class); startActivity(i); break;
case R.id.solenoidvalve : i = new Intent(this,solenoidvalve.class); startActivity(i); break;
case R.id.nutrientpump : i = new Intent(this,Nutrientpump.class); startActivity(i); break;
default:break;
}
}
}
I am new to Android Studio and this is the first time I have had to make a multi-threaded application. Thank You.
you can try to extract the Bluetooth connection method into a simple profit class, similar to "local broadcast manager". When "uvlight" on destroy Bluetooth connection will continue to open. Or you can refer to GitHub's excellent open source libraries, such as: https://github.com/akexorcist/BluetoothSPPLibrary 。 I believe you can learn more in it

Android and BLE

I'm working on a project in which I want to receive the data(, separated value"only two values") from BLE server. my first question is I write the code for connection but I din't connect with it. and second how to read this comma separated value. and this comma separated value will come from arduino to BLE server and from BLE server the communication will be done between both. Code is Below.
IDs
#define SERVICE_UUID "ab0828b1-198e-4351-b779-901fa0e0371e"
#define CHARACTERISTIC_UUID_RX "4ac8a682-9736-4e5d-932b-e9b31405049c"
#define CHARACTERISTIC_UUID_TX "0972EF8C-7613-4075-AD52-756F33D4DA91"
code
package com.grng.rthr;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import com.grng.rthr.main.core.viewmodel.MainViewModel;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.Toolbar;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.grng.rthr.main.BackAwareApplication;
import com.grng.rthr.main.core.viewmodel.MainViewModel;
import com.grng.rthr.main.ui.fragment.atWork.ModeFragment;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.UUID;
public class BluetoothActivity extends AppCompatActivity {
// GUI Components
private TextView mBluetoothStatus;
private MainViewModel viewModel;
private TextView mReadBuffer;
private Button mScanBtn;
private Button mOffBtn;
private BluetoothAdapter mBTAdapter;
private Set<BluetoothDevice> mPairedDevices;
private ArrayAdapter<String> mBTArrayAdapter;
private ListView mDevicesListView;
private final String TAG = BluetoothActivity.class.getSimpleName();
private Handler mHandler; // Our main handler that will receive callback notifications
private ConnectedThread mConnectedThread; // bluetooth background worker thread to send and receive data
private BluetoothSocket mBTSocket = null; // bi-directional client-to-client data path
private static final UUID BTMODULEUUID = UUID.fromString("ab0828b1-198e-4351-b779-901fa0e0371e"); // "random" unique identifier
// #defines for identifying shared types between calling functions
private final static int REQUEST_ENABLE_BT = 1; // used to identify adding bluetooth names
private final static int MESSAGE_READ = 2; // used in bluetooth handler to identify message update
private final static int CONNECTING_STATUS = 3; // used in bluetooth handler to identify message status
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bluetooth);
// setTitle("Belt Monitoring");
setTitle("Belt Monitoring");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_back_btn);
mBluetoothStatus = (TextView)findViewById(R.id.bluetoothStatus);
mReadBuffer = (TextView) findViewById(R.id.readBuffer);
mScanBtn = (Button)findViewById(R.id.scan);
mOffBtn = (Button)findViewById(R.id.off);
mBTArrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1);
mBTAdapter = BluetoothAdapter.getDefaultAdapter(); // get a handle on the bluetooth radio
mDevicesListView = (ListView)findViewById(R.id.devicesListView);
mDevicesListView.setAdapter(mBTArrayAdapter); // assign model to view
mDevicesListView.setOnItemClickListener(mDeviceClickListener);
bluetoothOn();
// Ask for location permission if not already allowed
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
mHandler = new Handler(){
public void handleMessage(android.os.Message msg){
if(msg.what == MESSAGE_READ){
String readMessage = null;
try {
readMessage = new String((byte[]) msg.obj, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
mReadBuffer.setText(readMessage);
}
if(msg.what == CONNECTING_STATUS){
if(msg.arg1 == 1)
mBluetoothStatus.setText("Connected to Device: " + (String)(msg.obj));
else
mBluetoothStatus.setText("Connection Failed");
}
}
};
if (mBTArrayAdapter == null) {
// Device does not support Bluetooth
mBluetoothStatus.setText("Status: Bluetooth not found");
Toast.makeText(getApplicationContext(),"Bluetooth device not found!",Toast.LENGTH_SHORT).show();
}
else {
mScanBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bluetoothScan(v);
}
});
mOffBtn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
bluetoothOff(v);
}
});
}
}
private void bluetoothOn(){
if (!mBTAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
mBluetoothStatus.setText("Bluetooth enabled");
Toast.makeText(getApplicationContext(),"Bluetooth turned on",Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getApplicationContext(),"Bluetooth is already on", Toast.LENGTH_SHORT).show();
}
}
private void bluetoothScan(View view){
mBTArrayAdapter.clear();
mPairedDevices = mBTAdapter.getBondedDevices();
if(mBTAdapter.isEnabled()) {
// put it's one to the adapter
for (BluetoothDevice device : mPairedDevices)
mBTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
Toast.makeText(getApplicationContext(), "Show Paired Devices", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(getApplicationContext(), "Bluetooth not on", Toast.LENGTH_SHORT).show();
}
discovering();
}
private void discovering(){
if(mBTAdapter.isDiscovering()){
mBTAdapter.cancelDiscovery();
Toast.makeText(getApplicationContext(),"Discovery stopped",Toast.LENGTH_SHORT).show();
}
else{
if(mBTAdapter.isEnabled()) {
mBTArrayAdapter.clear(); // clear items
mBTAdapter.startDiscovery();
Toast.makeText(getApplicationContext(), "Discovery started", Toast.LENGTH_SHORT).show();
registerReceiver(blReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
}
else{
Toast.makeText(getApplicationContext(), "Bluetooth not on", Toast.LENGTH_SHORT).show();
}
}
}
// Enter here after user selects "yes" or "no" to enabling radio
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent Data){
// Check which request we're responding to
if (requestCode == REQUEST_ENABLE_BT) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
// The user picked a contact.
// The Intent's data Uri identifies which contact was selected.
mBluetoothStatus.setText("Enabled");
}
else
mBluetoothStatus.setText("Disabled");
}
}
private void bluetoothOff(View view){
mBTAdapter.disable(); // turn off
mBluetoothStatus.setText("Bluetooth disabled");
Toast.makeText(getApplicationContext(),"Bluetooth turned Off", Toast.LENGTH_SHORT).show();
}
final BroadcastReceiver blReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)){
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// add the name to the list
mBTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
mBTArrayAdapter.notifyDataSetChanged();
}
}
};
private AdapterView.OnItemClickListener mDeviceClickListener = new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {
if(!mBTAdapter.isEnabled()) {
Toast.makeText(getBaseContext(), "Bluetooth not on", Toast.LENGTH_SHORT).show();
return;
}
mBluetoothStatus.setText("Connecting...");
// Get the device MAC address, which is the last 17 chars in the View
String info = ((TextView) v).getText().toString();
final String address = info.substring(info.length() - 17);
final String name = info.substring(0,info.length() - 17);
// Spawn a new thread to avoid blocking the GUI one
new Thread()
{
public void run() {
boolean fail = false;
BluetoothDevice device = mBTAdapter.getRemoteDevice(address);
try {
mBTSocket = createBluetoothSocket(device);
} catch (IOException e) {
fail = true;
Toast.makeText(getBaseContext(), "Socket creation failed", Toast.LENGTH_SHORT).show();
}
// Establish the Bluetooth socket connection.
try {
mBTSocket.connect();
} catch (IOException e) {
try {
fail = true;
mBTSocket.close();
mHandler.obtainMessage(CONNECTING_STATUS, -1, -1)
.sendToTarget();
} catch (IOException e2) {
//insert code to deal with this
Toast.makeText(getBaseContext(), "Socket creation failed", Toast.LENGTH_SHORT).show();
}
}
if(fail == false) {
mConnectedThread = new ConnectedThread(mBTSocket);
mConnectedThread.start();
mHandler.obtainMessage(CONNECTING_STATUS, 1, -1, name)
.sendToTarget();
}
}
}.start();
}
};
private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
try {
final Method m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", UUID.class);
return (BluetoothSocket) m.invoke(device, BTMODULEUUID);
} catch (Exception e) {
Log.e(TAG, "Could not create Insecure RFComm Connection",e);
}
return device.createRfcommSocketToServiceRecord(BTMODULEUUID);
}
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 input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
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) {
try {
// Read from the InputStream
bytes = mmInStream.available();
if(bytes != 0) {
buffer = new byte[1024];
SystemClock.sleep(100); //pause and wait for rest of data. Adjust this depending on your sending speed.
bytes = mmInStream.available(); // how many bytes are ready to be read?
bytes = mmInStream.read(buffer, 0, bytes); // record how many bytes we actually read
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget(); // Send the obtained bytes to the UI activity
}
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(String input) {
byte[] bytes = input.getBytes(); //converts entered String into bytes
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
}

Making a bluetooth service that sends a signal to arduino bluetooth module

So I have been working with arduino for a while and now I've been trying to connect to the blue-tooth module with android studio. I was able to get the blue-tooth to connect but I'm having issues making the blue-tooth connection a service so that it can run even if the app is closed. Whenever I try to get the service to run on my phone, the app crashes as soon as i try to connect to blue-tooth module where as before when it was an activity, it worked perfectly. I've looked at a lot of links and guides on using services and blue-tooth but none of them do exactly what I want.
Below are some code snippets, but here is a link to the entire GitHub project
Blue-tooth activity that I got to work:
package edu.memphis.teamhack.smart_nightlight;
import android.Manifest;
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.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.UUID;
public class BluetoothActivity extends AppCompatActivity {
// GUI Components
private TextView mBluetoothStatus;
private TextView mReadBuffer;
private Button mScanBtn;
private Button mOffBtn;
private Button mListPairedDevicesBtn;
private Button mDiscoverBtn;
private BluetoothAdapter mBTAdapter;
private Set<BluetoothDevice> mPairedDevices;
private ArrayAdapter<String> mBTArrayAdapter;
private ListView mDevicesListView;
private CheckBox mLED1;
private final String TAG = MainActivity.class.getSimpleName();
private Handler mHandler; // Our main handler that will receive callback notifications
private ConnectedThread mConnectedThread; // bluetooth background worker thread to send and receive data
private BluetoothSocket mBTSocket = null; // bi-directional client-to-client data path
private static final UUID BTMODULEUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // "random" unique identifier
// #defines for identifying shared types between calling functions
private final static int REQUEST_ENABLE_BT = 1; // used to identify adding bluetooth names
private final static int MESSAGE_READ = 2; // used in bluetooth handler to identify message update
private final static int CONNECTING_STATUS = 3; // used in bluetooth handler to identify message status
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bluetooth);
mBluetoothStatus = (TextView)findViewById(R.id.bluetoothStatus);
mReadBuffer = (TextView) findViewById(R.id.readBuffer);
mScanBtn = (Button)findViewById(R.id.scan);
mOffBtn = (Button)findViewById(R.id.off);
mDiscoverBtn = (Button)findViewById(R.id.discover);
mListPairedDevicesBtn = (Button)findViewById(R.id.PairedBtn);
mLED1 = (CheckBox)findViewById(R.id.checkboxLED1);
mBTArrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1);
mBTAdapter = BluetoothAdapter.getDefaultAdapter(); // get a handle on the bluetooth radio
mDevicesListView = (ListView)findViewById(R.id.devicesListView);
mDevicesListView.setAdapter(mBTArrayAdapter); // assign model to view
mDevicesListView.setOnItemClickListener(mDeviceClickListener);
// Ask for location permission if not already allowed
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
mHandler = new Handler(){
public void handleMessage(android.os.Message msg){
if(msg.what == MESSAGE_READ){
String readMessage = null;
try {
readMessage = new String((byte[]) msg.obj, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
mReadBuffer.setText(readMessage);
}
if(msg.what == CONNECTING_STATUS){
if(msg.arg1 == 1)
mBluetoothStatus.setText("Connected to Device: " + (String)(msg.obj));
else
mBluetoothStatus.setText("Connection Failed");
}
}
};
if (mBTArrayAdapter == null) {
// Device does not support Bluetooth
mBluetoothStatus.setText("Status: Bluetooth not found");
Toast.makeText(getApplicationContext(),"Bluetooth device not found!",Toast.LENGTH_SHORT).show();
}
else {
mLED1.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
SharedPreferences settings = getSharedPreferences("MyPref",
Context.MODE_PRIVATE);
Integer myInt = settings.getInt("colorHex", 0);
if(mConnectedThread != null){ //First check to make sure thread created
mConnectedThread.write(myInt.toString());}
}
});
mScanBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bluetoothOn(v);
}
});
mOffBtn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
bluetoothOff(v);
}
});
mListPairedDevicesBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
listPairedDevices(v);
}
});
mDiscoverBtn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
discover(v);
}
});
}
}
private void bluetoothOn(View view){
if (!mBTAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
mBluetoothStatus.setText("Bluetooth enabled");
Toast.makeText(getApplicationContext(),"Bluetooth turned on",Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getApplicationContext(),"Bluetooth is already on", Toast.LENGTH_SHORT).show();
}
}
// Enter here after user selects "yes" or "no" to enabling radio
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent Data){
// Check which request we're responding to
if (requestCode == REQUEST_ENABLE_BT) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
// The user picked a contact.
// The Intent's data Uri identifies which contact was selected.
mBluetoothStatus.setText("Enabled");
}
else
mBluetoothStatus.setText("Disabled");
}
}
private void bluetoothOff(View view){
mBTAdapter.disable(); // turn off
mBluetoothStatus.setText("Bluetooth disabled");
Toast.makeText(getApplicationContext(),"Bluetooth turned Off", Toast.LENGTH_SHORT).show();
}
private void discover(View view){
// Check if the device is already discovering
if(mBTAdapter.isDiscovering()){
mBTAdapter.cancelDiscovery();
Toast.makeText(getApplicationContext(),"Discovery stopped",Toast.LENGTH_SHORT).show();
}
else{
if(mBTAdapter.isEnabled()) {
mBTArrayAdapter.clear(); // clear items
mBTAdapter.startDiscovery();
Toast.makeText(getApplicationContext(), "Discovery started", Toast.LENGTH_SHORT).show();
registerReceiver(blReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
}
else{
Toast.makeText(getApplicationContext(), "Bluetooth not on", Toast.LENGTH_SHORT).show();
}
}
}
final BroadcastReceiver blReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)){
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// add the name to the list
mBTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
mBTArrayAdapter.notifyDataSetChanged();
}
}
};
private void listPairedDevices(View view){
mPairedDevices = mBTAdapter.getBondedDevices();
if(mBTAdapter.isEnabled()) {
// put it's one to the adapter
for (BluetoothDevice device : mPairedDevices)
mBTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
Toast.makeText(getApplicationContext(), "Show Paired Devices", Toast.LENGTH_SHORT).show();
}
else
Toast.makeText(getApplicationContext(), "Bluetooth not on", Toast.LENGTH_SHORT).show();
}
private AdapterView.OnItemClickListener mDeviceClickListener = new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {
if(!mBTAdapter.isEnabled()) {
Toast.makeText(getBaseContext(), "Bluetooth not on", Toast.LENGTH_SHORT).show();
return;
}
mBluetoothStatus.setText("Connecting...");
// Get the device MAC address, which is the last 17 chars in the View
String info = ((TextView) v).getText().toString();
final String address = info.substring(info.length() - 17);
final String name = info.substring(0,info.length() - 17);
// Spawn a new thread to avoid blocking the GUI one
new Thread()
{
public void run() {
boolean fail = false;
BluetoothDevice device = mBTAdapter.getRemoteDevice(address);
try {
mBTSocket = createBluetoothSocket(device);
} catch (IOException e) {
fail = true;
Toast.makeText(getBaseContext(), "Socket creation failed", Toast.LENGTH_SHORT).show();
}
// Establish the Bluetooth socket connection.
try {
mBTSocket.connect();
} catch (IOException e) {
try {
fail = true;
mBTSocket.close();
mHandler.obtainMessage(CONNECTING_STATUS, -1, -1)
.sendToTarget();
} catch (IOException e2) {
//insert code to deal with this
Toast.makeText(getBaseContext(), "Socket creation failed", Toast.LENGTH_SHORT).show();
}
}
if(fail == false) {
mConnectedThread = new ConnectedThread(mBTSocket);
mConnectedThread.start();
mHandler.obtainMessage(CONNECTING_STATUS, 1, -1, name)
.sendToTarget();
}
}
}.start();
}
};
private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
try {
final Method m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", UUID.class);
return (BluetoothSocket) m.invoke(device, BTMODULEUUID);
} catch (Exception e) {
Log.e(TAG, "Could not create Insecure RFComm Connection",e);
}
return device.createRfcommSocketToServiceRecord(BTMODULEUUID);
}
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 input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
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) {
try {
// Read from the InputStream
bytes = mmInStream.available();
if(bytes != 0) {
buffer = new byte[1024];
SystemClock.sleep(100); //pause and wait for rest of data. Adjust this depending on your sending speed.
bytes = mmInStream.available(); // how many bytes are ready to be read?
bytes = mmInStream.read(buffer, 0, bytes); // record how many bytes we actually read
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget(); // Send the obtained bytes to the UI activity
}
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(String input) {
byte[] bytes = input.getBytes(); //converts entered String into bytes
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
Here is the Bluetooth Service I'm working on:
package edu.memphis.teamhack.smart_nightlight;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Toast;
public class BluetoothCommService extends Service {
// #defines for identifying shared types between calling functions
private final static int REQUEST_ENABLE_BT = 1; // used to identify adding bluetooth names
private BluetoothAdapter mBTAdapter;
private ArrayAdapter<String> mBTArrayAdapter;
public BluetoothCommService() {
}
public void onCreate(Bundle savedInstanceState){
//super.onCreate(savedInstanceState);
mBTAdapter = BluetoothAdapter.getDefaultAdapter(); // get a handle on the bluetooth radio
mBTArrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1);
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
void bluetoothOn(View view){
if (!mBTAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
//startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
//GUI
//mBluetoothStatus.setText("Bluetooth enabled");
// Toast.makeText(getApplicationContext(),"Bluetooth turned on",Toast.LENGTH_SHORT).show();
}
else{
//Toast.makeText(getApplicationContext(),"Bluetooth is already on", Toast.LENGTH_SHORT).show();
}
}
private void bluetoothOff(View view){
mBTAdapter.disable(); // turn off
//GUI
//mBluetoothStatus.setText("Bluetooth disabled");
//Toast.makeText(getApplicationContext(),"Bluetooth turned Off", Toast.LENGTH_SHORT).show();
}
private void discover(View view){
// Check if the device is already discovering
if(mBTAdapter.isDiscovering()){
mBTAdapter.cancelDiscovery();
Toast.makeText(getApplicationContext(),"Discovery stopped",Toast.LENGTH_SHORT).show();
}
else{
if(mBTAdapter.isEnabled()) {
mBTArrayAdapter.clear(); // clear items
mBTAdapter.startDiscovery();
Toast.makeText(getApplicationContext(), "Discovery started", Toast.LENGTH_SHORT).show();
registerReceiver(blReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
}
else{
Toast.makeText(getApplicationContext(), "Bluetooth not on", Toast.LENGTH_SHORT).show();
}
}
}
final BroadcastReceiver blReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)){
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// add the name to the list
mBTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
mBTArrayAdapter.notifyDataSetChanged();
}
}
};
}
Feel free to ask any questions.
Try this instructables, i did it by reffering to this tutorial
http://www.instructables.com/id/Android-Bluetooth-Control-LED-Part-2/
for more idea, also refer to
https://www.intorobotics.com/how-to-develop-simple-bluetooth-android-application-to-control-a-robot-remote/

My Bluetooth app crashes randomly with the error: Error receiving broadCast Intent

So i'm working on a Bluetooth app and it crashes randomly sometimes and I've yet to found a solution. Logcat complains at the line if (device.getName().equals(pairedDevices.get(a))) { but I don't understand what that has to do with the crash?
Any help is appreciated!
Logcat:
02-23 11:47:05.311 28011-28037/com.example.asabanov.powersupplytool E/Surface: getSlotFromBufferLocked: unknown buffer: 0xb91b9980
02-23 11:47:15.718 28011-28011/com.example.asabanov.powersupplytool E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.asabanov.powersupplytool, PID: 28011
java.lang.RuntimeException: Error receiving broadcast Intent { act=android.bluetooth.device.action.FOUND flg=0x10 (has extras) } in com.example.asabanov.powersupplytool.BluetoothActivity$2#4d08f04
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:934)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:168)
at android.app.ActivityThread.main(ActivityThread.java:5845)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
at com.example.asabanov.powersupplytool.BluetoothActivity$2.onReceive(BluetoothActivity.java:129)
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:915)
at android.os.Handler.handleCallback(Handler.java:739) 
at android.os.Handler.dispatchMessage(Handler.java:95) 
at android.os.Looper.loop(Looper.java:168) 
at android.app.ActivityThread.main(ActivityThread.java:5845) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687) 
BluetoothActivity:
package com.example.asabanov.powersupplytool;
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.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Set;
import java.util.UUID;
public class BluetoothActivity extends AppCompatActivity implements OnItemClickListener {
public static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
protected static final int SUCCESS_CONNECT = 0;
protected static final int MESSAGE_READ = 1;
ArrayAdapter<String> listAdapter;
ListView listView;
BluetoothAdapter btAdapter;
Set<BluetoothDevice> devicesArray;
ArrayList<String> pairedDevices;
ArrayList<BluetoothDevice> devices;
IntentFilter filter;
BroadcastReceiver receiver;
String tag = "debugging";
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case SUCCESS_CONNECT:
//do something
ConnectedThread connectedThread = new ConnectedThread((BluetoothSocket) msg.obj);
Toast.makeText(getApplicationContext(), "Connect", Toast.LENGTH_SHORT).show();
String s = "Successfully connected";
connectedThread.write(s.getBytes());
break;
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
String string = new String(readBuf);
Toast.makeText(getApplicationContext(), "Connect", Toast.LENGTH_SHORT).show();
break;
}
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bluetooth);
init(); //initiate Bluetooth
if (btAdapter == null) {
Toast.makeText(getApplicationContext(), "No bluetooth detected on this device", Toast.LENGTH_SHORT).show();
finish();
} else {
if (!btAdapter.isEnabled()) {
turnOnBT();
}
pairedDevices=getPairedDevices();
startDiscovery();
}
}
private void startDiscovery() {
btAdapter.cancelDiscovery();
btAdapter.startDiscovery();
}
private void turnOnBT() {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 1);
}
private ArrayList getPairedDevices() {
devicesArray = btAdapter.getBondedDevices();
if (devicesArray.size() > 0) {
//add devices in array to list array
for (BluetoothDevice device : devicesArray) {
pairedDevices.add(device.getName() + "\n" + device.getAddress());
}
}
return pairedDevices;
}
private void init() {
listView = (ListView) findViewById(R.id.listView);
listView.setOnItemClickListener(this);
listAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, 0);
listView.setAdapter(listAdapter);
btAdapter = BluetoothAdapter.getDefaultAdapter();
pairedDevices = new ArrayList<String>();
filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
devices = new ArrayList<BluetoothDevice>();
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
devices.add(device);
String s = "";
for (int a = 0; a < pairedDevices.size(); a++) {
if (device.getName().equals(pairedDevices.get(a))) { //log cat complains at this line
s = "Paired";
break;
}
}
// matt-hp (paired)
listAdapter.add(device.getName() + " " + s + " " + "\n" + device.getAddress());
} else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
//run some code
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
//run some code
} else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
if (btAdapter.getState() == btAdapter.STATE_OFF) {
turnOnBT();
}
}
}
};
registerReceiver(receiver, filter);
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
registerReceiver(receiver, filter);
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(receiver, filter);
filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(receiver, filter);
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(receiver, filter);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_CANCELED) {
Toast.makeText(getApplicationContext(), "Bluetooth must be enabled to continue", Toast.LENGTH_SHORT).show();
finish();
}
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (btAdapter.isDiscovering()) {
btAdapter.cancelDiscovery();
}
if (listAdapter.getItem(position).contains("Paired")) {
BluetoothDevice selectedDevice = devices.get(position);
ConnectThread connect = new ConnectThread(selectedDevice);
connect.start();
Toast.makeText(getApplicationContext(), "Device is paired", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "Device is not paired", Toast.LENGTH_SHORT).show();
}
}
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
// 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 {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
}
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
btAdapter.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) {
}
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
*/
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
}
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 input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void 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) {
try {
// 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;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) {
}
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
}
}
MainActivity:
package com.example.asabanov.powersupplytool;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(MainActivity.this, BluetoothActivity.class);
startActivity(i);
}
});
Button Y10Button = (Button) findViewById(R.id.button);
Y10Button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
Intent intent = new Intent(MainActivity.this, Y10.class);
startActivity(intent);
}
});
Button Y20Button = (Button) findViewById(R.id.button2);
Y20Button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
Intent intent = new Intent(MainActivity.this, Y20.class);
startActivity(intent);
}
});
Button SPAButton = (Button) findViewById(R.id.button3);
SPAButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
Intent intent = new Intent(MainActivity.this, SPA.class);
startActivity(intent);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_about) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
You should add some values to your pairedDevices = new ArrayList<String>(); before you try get()
BluetoothDevice object may be null. So you should check whether the object of BluetoothDevice is initialized successfully. I modified part of your code as following:
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(device != null) {
devices.add(device);
String s = "";
for (int a = 0; a < pairedDevices.size(); a++) {
if (device.getName().equals(pairedDevices.get(a))) { //log cat complains at this line
s = "Paired";
break;
}
}
// matt-hp (paired)
listAdapter.add(device.getName() + " " + s + " " + "\n" + device.getAddress());
}
In your code, device.getName() returns null, thus the exception is thrown when you call the .equals() method on a null object.
You can check the following question to find a solution to your problem -
android BluetoothDevice.getName() return null

How to pass a separate looper to a thread using HandlerThread class

I have a Handler called 'bluetoothIn' and I want to pass it to a separate looper using the HandlerThread class which will provide the looper. However I need to post the results back to the UI thread from 'handleMessage(Message msg)' since I can't modify UI elements from threads other than the main thread.
Here is my code :
package com.uniproj.senseplate;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
#SuppressWarnings("unused")
public class MainActivity extends Activity {
Button btnscan;
TextView txtArduino, txtString, txtStringLength, calorie;
Handler bluetoothIn;
final int handlerState = 0; //used to identify handler message
private BluetoothAdapter btAdapter = null;
private BluetoothSocket btSocket; //= null;
private StringBuilder recDataString = new StringBuilder();
private ConnectedThread mConnectedThread;
// SPP UUID service - this should work for most devices
private static final UUID BTMODULEUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
// String for MAC address
private static String address;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Link the buttons and textViews to respective views
btnscan = (Button) findViewById(R.id.scanBtn);
txtString = (TextView) findViewById(R.id.txtString);
txtStringLength = (TextView) findViewById(R.id.testView1);
bluetoothIn = new Handler() {
public void handleMessage(android.os.Message msg) {
if (msg.what == handlerState) {
String readMessage = (String) msg.obj;
recDataString.append(readMessage);
int endOfLineIndex = recDataString.indexOf("~");
if (endOfLineIndex > 0) {
String dataInPrint = recDataString.substring(0, endOfLineIndex);
txtString.setText("Data Received = " + dataInPrint);
int dataLength = dataInPrint.length();
txtStringLength.setText("String Length = " + String.valueOf(dataLength));
if (recDataString.charAt(0) == '#')
{
//get sensor value from string between indices 1-20
String weight = recDataString.substring(1, 20);
//update the textviews with sensor values
calorie.setText(weight + "kg");
}
recDataString.delete(0, recDataString.length());
// strIncom =" ";
dataInPrint = " ";
}
}
}
};
btAdapter = BluetoothAdapter.getDefaultAdapter(); // get Bluetooth adapter
checkBTState();
// Set up onClick listeners for button to scan for data
btnscan.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mConnectedThread.write("0");
}
});
}
private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
return device.createRfcommSocketToServiceRecord(BTMODULEUUID);
//creates secure outgoing connecetion with BT device using UUID
}
#Override
public void onResume() {
super.onResume();
//Get MAC address from DeviceListActivity via intent
Intent intent = getIntent();
//Get the MAC address from the DeviceListActivty via EXTRA
address = intent.getStringExtra(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
//create device and set the MAC address
BluetoothDevice device = btAdapter.getRemoteDevice(address);
try {
btSocket = createBluetoothSocket(device);
} catch (IOException e) {
Toast.makeText(getBaseContext(), "Socket creation failed", Toast.LENGTH_LONG).show();
}
// Establish the Bluetooth socket connection.
try
{
btSocket.connect();
} catch (IOException e) {
try
{
btSocket.close();
} catch (IOException e2)
{
//insert code to deal with this
}
}
mConnectedThread = new ConnectedThread(btSocket);
mConnectedThread.start();
//I send a character when resuming.beginning transmission to check device is connected
//If it is not an exception will be thrown in the write method and finish() will be called
mConnectedThread.write("x");
}
#Override
public void onPause()
{
super.onPause();
try
{
//Don't leave Bluetooth sockets open when leaving activity
btSocket.close();
} catch (IOException e2) {
//insert code to deal with this
}
}
//Checks that the Android device Bluetooth is available and prompts to be turned on if off
private void checkBTState() {
if(btAdapter==null) {
Toast.makeText(getBaseContext(), "Device does not support bluetooth", Toast.LENGTH_LONG).show();
} else {
if (btAdapter.isEnabled()) {
} else {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
}
}
//create new class for connect thread
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private final OutputStream mmOutStream;
//creation of the connect thread
public ConnectedThread(BluetoothSocket socket) {
btSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
//Create I/O streams for connection
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024];
int bytes;
// Keep looping to listen for received messages
while (true) {
try {
bytes = mmInStream.read(buffer);
bluetoothIn.obtainMessage(handlerState, bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
break;
}
}
}
//write method
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(getBaseContext(), "Connection Failed", Toast.LENGTH_LONG).show();
finish();
}
}
public class BluetoothInHandler extends Handler{
private Looper sLooper = null;
private Handler mWorkerThreadHandler;
final int handlerState = 0; //used to identify handler message
protected class WorkerArgs {
Handler handler;
String input;
String output;
}
public BluetoothInHandler() {
super();
synchronized (BluetoothInHandler.class) {
if (sLooper == null) {
HandlerThread thread = new HandlerThread("AsyncWorker");
thread.start();
sLooper = thread.getLooper();
}
}
mWorkerThreadHandler = new WorkerHandler(sLooper);
}
#Override
public void handleMessage(Message msg) {
if (msg.what == handlerState) {
WorkerArgs args = (WorkerArgs) msg.obj;
String readMessage = args.output;
//your job;
} else {
super.handleMessage(msg);
}
}
public void write(String input) {
WorkerArgs args = new WorkerArgs();
args.handler = this;
args.input = input;
Message message = mWorkerThreadHandler.obtainMessage(handlerState);
message.obj = args;
mWorkerThreadHandler.sendMessage(message);
}
protected class WorkerHandler extends Handler {
public WorkerHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
if (msg.what == handlerState) {
WorkerArgs args = (WorkerArgs) msg.obj;
//the code here run in a thread, not in the ui thread
//do your job like:
byte[] bytes = mmInStream.read(buffer);
args.output = new String(bytes);
Message message = args.handler.obtainMessage(handlerState);
message.obj = args;
message.sendToTarget();
}
}
}
}
}//ConnectedThread End
}
runOnUi might be a good choice for this
runOnUiThread(new Runnable() {
#Override
public void run() {
// Do whatever you need to do on the UI here
}
});
Sorry, I made a mistake. I think the error is causing by the code bluetoothIn.obtainMessage(handlerState, bytes, -1, buffer).sendToTarget();
change to
bluetoothIn.obtainMessage(handlerState, bytes, -1, new String(buffer)).sendToTarget();
Remove the code I wrote. It is no use.

Categories