I’m writing an app and it has a part which, on button click, scans for Bluetooth devices and shows them in a ListView. It works fine, but i need it to show only devices starting with a word in the name, for example: "MyArduino/123", so I need it to look for the "MyArduino/" part in device names and only show those that have it.
XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="com.test.app.MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/title"
android:textSize="20sp"
android:textAlignment="center"
android:text="@string/title"
android:gravity="center_horizontal" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:text="@string/bt_menu"
android:background="@color/button"
android:onClick="showBt"
android:id="@+id/to_bt_menu"
android:layout_margin="10sp"
tools:ignore="UsingOnClickInXml" />
<Button
android:id="@+id/to_vars_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:layout_marginLeft="10sp"
android:layout_marginStart="10sp"
android:layout_toEndOf="@id/to_bt_menu"
android:layout_toRightOf="@id/to_bt_menu"
android:onClick="showVars"
android:text="@string/vars_menu"
android:background="@color/button"
android:layout_margin="10sp"
tools:ignore="UsingOnClickInXml" />
<TextView
android:id="@+id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/to_bt_menu"
android:visibility="gone"
android:ellipsize="end"
android:maxLines="1"
android:text="@string/status"
android:textStyle="bold" />
<TextView
android:id="@+id/bluetooth_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/to_bt_menu"
android:visibility="gone"
android:layout_toEndOf="@id/status"
android:layout_toRightOf="@id/status"
android:layout_marginLeft="20sp"
android:layout_marginStart="20sp"
android:ellipsize="end"
android:maxLines="1"
android:text="@string/bluetooth_status" />
<Button
android:id="@+id/scan"
android:layout_width="150sp"
android:layout_height="wrap_content"
android:layout_below="@id/bluetooth_status"
android:layout_margin="10sp"
android:visibility="gone"
android:text="@string/bluetooth_on"
android:background="@color/button" />
<Button
android:id="@+id/off"
android:layout_width="150sp"
android:layout_height="wrap_content"
android:layout_below="@id/bluetooth_status"
android:layout_margin="10sp"
android:visibility="gone"
android:layout_toRightOf="@id/scan"
android:layout_toEndOf="@id/scan"
android:background="@color/button"
android:text="@string/bluetooth_off" />
<Button
android:id="@+id/paired_btn"
android:layout_width="150sp"
android:layout_height="wrap_content"
android:layout_below="@id/off"
android:layout_margin="10sp"
android:visibility="gone"
android:text="@string/show_paired_devices"
android:background="@color/button" />
<Button
android:id="@+id/discover"
android:layout_width="150sp"
android:layout_height="wrap_content"
android:layout_below="@id/off"
android:layout_margin="10sp"
android:visibility="gone"
android:layout_toEndOf="@+id/paired_btn"
android:layout_toRightOf="@id/paired_btn"
android:text="@string/discover_new_devices"
android:background="@color/button" />
<ListView
android:id="@+id/devices_list_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/discover"
android:visibility="gone"
android:choiceMode="singleChoice" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20sp"
android:onClick="reqVars"
android:text="@string/req_btn"
android:layout_below="@id/user_edit"
android:visibility="gone"
android:id="@+id/req_btn"
android:layout_margin="10sp"
android:background="@color/button" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/to_vars_menu"
android:layout_margin="10sp"
android:visibility="gone"
android:id="@+id/user_edit"
android:hint="@string/hint_edit"
tools:ignore="TextFields"/>
<Button
android:id="@+id/send_edit_btn"
android:layout_margin="10sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/user_edit"
android:visibility="gone"
android:layout_marginStart="20sp"
android:layout_marginLeft="20sp"
android:layout_marginTop="20sp"
android:layout_toEndOf="@+id/req_btn"
android:layout_toRightOf="@+id/req_btn"
android:onClick="editVar"
android:text="@string/send_edit_btn"
android:background="@color/button" />
<ListView
android:layout_below="@id/req_btn"
android:visibility="gone"
android:id="@+id/vars"
android:choiceMode="singleChoice"
android:listSelector="@color/list"
android:layout_width="300sp"
android:layout_height="wrap_content" />
</RelativeLayout>
MainActivity:
package com.test.app;
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.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
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.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
private final String TAG = MainActivity.class.getSimpleName();
private static final UUID BT_MODULE_UUID = 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
public 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
// GUI Components
private TextView mBluetoothStatus;
private Button mScanBtn;
private Button mOffBtn;
private Button mListPairedDevicesBtn;
private Button mDiscoverBtn;
private ListView mDevicesListView;
private TextView mStatus;
private EditText mUserEdit;
private Button mReqBtn;
private Button mSendEdit;
private ListView mVars;
private String mSelecVar;
private String mMessage;
private BluetoothAdapter mBTAdapter;
private Set<BluetoothDevice> mPairedDevices;
private ArrayList<BluetoothDevice> mBTDevices;
private ArrayAdapter<String> mBTArrayAdapter;
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
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Objects.requireNonNull(getSupportActionBar()).hide();
} else {
getSupportActionBar().hide();
}
setContentView(R.layout.activity_main);
mBluetoothStatus = (TextView)findViewById(R.id.bluetooth_status);
mScanBtn = (Button)findViewById(R.id.scan);
mOffBtn = (Button)findViewById(R.id.off);
mDiscoverBtn = (Button)findViewById(R.id.discover);
mListPairedDevicesBtn = (Button)findViewById(R.id.paired_btn);
mStatus = (TextView)findViewById(R.id.status);
mUserEdit = (EditText)findViewById(R.id.user_edit);
mReqBtn = (Button)findViewById(R.id.req_btn);
mSendEdit = (Button)findViewById(R.id.send_edit_btn);
mVars = (ListView)findViewById(R.id.vars);
mBTArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);
mBTDevices = new ArrayList<>();
mBTAdapter = BluetoothAdapter.getDefaultAdapter(); // get a handle on the bluetooth radio
mDevicesListView = (ListView)findViewById(R.id.devices_list_view);
assert mDevicesListView != null;
mDevicesListView.setAdapter(mBTArrayAdapter); // assign model to view
mDevicesListView.setOnItemClickListener(mDeviceClickListener);
mVars.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mSelecVar = mVars.getItemAtPosition(position).toString().split(",")[0];
}
});
// 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(Looper.getMainLooper()){
@Override
public void handleMessage(Message msg){
if(msg.what == MESSAGE_READ){
String readMessage = null;
try {
readMessage = new String((byte[]) msg.obj, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
mMessage = readMessage;
if (mMessage != null) {
for (int i = 0; i < mMessage.length(); i++) {
if (mMessage.toCharArray()[i] == ';') {
getVars(mMessage);
break;
}
}
}
}
if(msg.what == CONNECTING_STATUS){
if(msg.arg1 == 1) {
mBluetoothStatus.setText("Connected to Device: " + msg.obj);
mConnectedThread.write("list");
} 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) {
bluetoothOn();
}
});
mOffBtn.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
bluetoothOff();
}
});
mListPairedDevicesBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v){
listPairedDevices();
}
});
mDiscoverBtn.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
discover();
}
});
}
}
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();
}
}
// 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(){
mBTAdapter.disable(); // turn off
mBluetoothStatus.setText("Bluetooth disabled");
Toast.makeText(getApplicationContext(),"Bluetooth turned Off", Toast.LENGTH_SHORT).show();
}
private void discover(){
// 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
mBTDevices.add(device);
mBTArrayAdapter.add(device.getName() + "n" + device.getAddress());
mBTArrayAdapter.notifyDataSetChanged();
}
if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)){
BluetoothDevice mDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (mDevice.getBondState() == BluetoothDevice.BOND_BONDED){
Log.d(TAG, "BroadcastReceiver: BOND_BONDED");
}
if (mDevice.getBondState() == BluetoothDevice.BOND_BONDING){
Log.d(TAG, "BroadcastReceiver: BOND_BONDING");
}
if (mDevice.getBondState() == BluetoothDevice.BOND_NONE){
Log.d(TAG, "BroadcastReceiver: BOND_NONE");
}
}
}
};
private void listPairedDevices(){
mBTArrayAdapter.clear();
mPairedDevices = mBTAdapter.getBondedDevices();
if(mBTAdapter.isEnabled()) {
// put it's one to the adapter
for (BluetoothDevice device : mPairedDevices)
if (device.getName().equals("MyArduino/")){
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() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
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) view).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()
{
@Override
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) {
mConnectedThread = new ConnectedThread(mBTSocket, mHandler);
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, BT_MODULE_UUID);
} catch (Exception e) {
Log.e(TAG, "Could not create Insecure RFComm Connection",e);
}
return device.createRfcommSocketToServiceRecord(BT_MODULE_UUID);
}
public void showBt(View view) {
mBluetoothStatus.setVisibility(View.VISIBLE);
mScanBtn.setVisibility(View.VISIBLE);
mOffBtn.setVisibility(View.VISIBLE);
mDiscoverBtn.setVisibility(View.VISIBLE);
mListPairedDevicesBtn.setVisibility(View.VISIBLE);
mDevicesListView.setVisibility(View.VISIBLE);
mStatus.setVisibility(View.VISIBLE);
mVars.setVisibility(View.GONE);
mUserEdit.setVisibility(View.GONE);
mSendEdit.setVisibility(View.GONE);
mReqBtn.setVisibility(View.GONE);
}
public void showVars(View view) {
mBluetoothStatus.setVisibility(View.GONE);
mScanBtn.setVisibility(View.GONE);
mOffBtn.setVisibility(View.GONE);
mDiscoverBtn.setVisibility(View.GONE);
mListPairedDevicesBtn.setVisibility(View.GONE);
mDevicesListView.setVisibility(View.GONE);
mStatus.setVisibility(View.GONE);
mVars.setVisibility(View.VISIBLE);
mUserEdit.setVisibility(View.VISIBLE);
mSendEdit.setVisibility(View.VISIBLE);
mReqBtn.setVisibility(View.VISIBLE);
}
public void reqVars(View view) {
if (mConnectedThread != null){
mConnectedThread.write("list");
}
}
public void getVars(String string) {
String[] str = string.split(";");
List<String> al;
al = Arrays.asList(str);
ArrayAdapter<String> mVarsArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, al);
mVars.setAdapter(mVarsArrayAdapter);
}
public void editVar(View view) {
if (mConnectedThread != null) {
mConnectedThread.write("edit " + mSelecVar + " " + mUserEdit.getText());
mUserEdit.setText("");
SystemClock.sleep(2000);
mConnectedThread.write("list");
}
}
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
mBTAdapter.cancelDiscovery();
Log.d(TAG, "onItemClick: You clicked on a device.");
String deviceName = mBTDevices.get(i).getName();
String deviceAddress = mBTDevices.get(i).getAddress();
Log.d(TAG, "onItemClick: deviceName = " + deviceName);
Log.d(TAG, "onItemClick: deviceAddress = " + deviceAddress);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2){
Log.d(TAG, "Trying to pair with " + deviceName);
mBTDevices.get(i).createBond();
}
}
}
ConnectedThread:
package com.test.app;
import android.bluetooth.BluetoothSocket;
import android.os.Handler;
import android.os.SystemClock;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private final Handler mHandler;
public ConnectedThread(BluetoothSocket socket, Handler handler) {
mmSocket = socket;
mHandler = handler;
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;
}
@Override
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(MainActivity.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) { }
}
}
Right now, the ListView shows all the devices that the Bluetooth founds, and sometimes, even shows them 2 or 3 times in the same list. As you can see in the MainActivity, i tried to make some sort of a filter in line 272 but it just does not work. Thanks
2
Answers
So, after hours of trial and error, the problem was solved.
I've noticed this line in the errors on crash:
It means that the function was looking for "MyArduino/" in a null object. So i modified this:
To this:
And the problem was solved. It just showed the devices with "MyAdruino/" names and only once. Hope this will help anyone that gets the same problem
You trying to get device name equals to "MyArduino/" but what you need is actually device name how start with "MyArduino/":
just replace this line in listPairedDevices() on MainActivity:
from : (equals)
to : (startsWith)
editting the answer
//before adding the device:
}