使用 android 应用程序扫描范围内的蓝牙设备

Scan for Bluetooth devices in range using android application

我正在开发一个 android 应用程序来在我单击按钮时发现我周围的蓝牙设备。下面我已经提到了它是如何工作的。

MainActivity.java

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Set;

public class MainActivity extends AppCompatActivity {
  private String LOG_TAG; // Just for logging purposes. Could be anything. Set to app_name
  private int REQUEST_ENABLE_BT = 99; // Any positive integer should work.
  private BluetoothAdapter mBluetoothAdapter;

  @Override
  protected void onCreate(Bundle savedInstanceState)
  {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Button scanBt = (Button) findViewById(R.id.button_scanBT);

    LOG_TAG = getResources().getString(R.string.app_name);
    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

    scanBt.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v)
    {
        scanForBluetoothDevices();
        Log.d("TAG","testing");
    }
    });

  private void scanForBluetoothDevices()
  {
    // Start this on a new activity without passing any data to it
    Intent intent = new Intent(this, FoundBTDevices.class);
    startActivity(intent);
  }

}

FoundBTDevices.java

 import android.app.ListActivity;
 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.Build;
 import android.os.Bundle;
 import android.util.Log;

 import androidx.annotation.RequiresApi;
 import java.util.ArrayList;

public class FoundBTDevices extends ListActivity{

private ArrayList<BluetoothObject> arrayOfFoundBTDevices;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

    if (!havePermissions()) {
        Log.d("TAG", "Requesting permissions needed for this app.");
        requestPermissions();
    }

IntentFilter bluetoothFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, bluetoothFilter);
final BluetoothAdapter mBluetoothAdapter = 
BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.startDiscovery();


}


    // Create a BroadcastReceiver for ACTION_FOUND
    private final BroadcastReceiver mReceiver = new BroadcastReceiver()
    {

        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
        @Override
        public void onReceive(Context context, Intent intent)
        {
            arrayOfFoundBTDevices = new ArrayList<BluetoothObject>();

            // start looking for bluetooth devices
            mBluetoothAdapter.startDiscovery();

            Log.d("TAG","This is onReceive()");
            String action = intent.getAction();
            // When discovery finds a device
            if (BluetoothDevice.ACTION_FOUND.equals(intent.getAction()))
            {
                // Get the bluetoothDevice object from the Intent
                BluetoothDevice device = 
   intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                // Get the "RSSI" to get the signal strength as 
   integer,
                // but should be displayed in "dBm" units
                int rssi = 
   intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE);

                // Create the device object and add it to the 
   arrayList of devices
                BluetoothObject bluetoothObject = new 
   BluetoothObject();
                bluetoothObject.setBluetooth_name(device.getName());

   bluetoothObject.setBluetooth_address(device.getAddress());

   bluetoothObject.setBluetooth_state(device.getBondState());
                bluetoothObject.setBluetooth_type(device.getType());    
  // requires API 18 or higher
                bluetoothObject.setBluetooth_uuids(device.getUuids());
                bluetoothObject.setBluetooth_rssi(rssi);

                arrayOfFoundBTDevices.add(bluetoothObject);

                // 1. Pass context and data to the custom adapter
                FoundBTDevicesAdapter adapter = new 
FoundBTDevicesAdapter(getApplicationContext(), arrayOfFoundBTDevices);

                // 2. setListAdapter
                setListAdapter(adapter);
            }
        }
    };


  private boolean havePermissions() {
    return ContextCompat.checkSelfPermission(this, 
  Manifest.permission.ACCESS_FINE_LOCATION)
            == PackageManager.PERMISSION_GRANTED;
  }
  private void requestPermissions() {
    ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 
  PERMISSIONS_REQUEST_CODE);
    Log.d("TAG", "requestPermissions");
  }

 @Override
  protected void onPause() {
    super.onPause();
    mBluetoothAdapter.cancelDiscovery();
  }
  }

FoundBTDevicesAdapter.java

 import android.content.Context;
 import android.os.ParcelUuid;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 import android.widget.TextView;

 import java.util.ArrayList;
 import java.util.UUID;

 public class FoundBTDevicesAdapter extends ArrayAdapter<BluetoothObject>
 {
  private Context context;
  private ArrayList<BluetoothObject> arrayFoundDevices;

  public FoundBTDevicesAdapter(Context context, ArrayList<BluetoothObject> arrayOfAlreadyPairedDevices)
{
    super(context, R.layout.row_bt_scan_new_devices, arrayOfAlreadyPairedDevices);

    this.context = context;
    this.arrayFoundDevices = arrayOfAlreadyPairedDevices;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    BluetoothObject bluetoothObject = arrayFoundDevices.get(position);

    // 1. Create Inflater
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    // 2. Get rowView from inflater
    View rowView = inflater.inflate(R.layout.row_bt_scan_new_devices, parent, false);

    // 3. Get the widgets from the rowView
    TextView bt_name = (TextView) rowView.findViewById(R.id.textview_bt_scan_name);
    TextView bt_address = (TextView) rowView.findViewById(R.id.textview_bt_scan_address);
    TextView bt_bondState = (TextView) rowView.findViewById(R.id.textview_bt_scan_state);
    TextView bt_type = (TextView) rowView.findViewById(R.id.textview_bt_scan_type);
    TextView bt_uuid = (TextView) rowView.findViewById(R.id.textview_bt_scan_uuid);
    TextView bt_signal_strength = (TextView) rowView.findViewById(R.id.textview_bt_scan_signal_strength);

    // 4. Set the text for each widget
    bt_name.setText(bluetoothObject.getBluetooth_name());
    bt_address.setText("address: " + bluetoothObject.getBluetooth_address());
    bt_bondState.setText("state: " + bluetoothObject.getBluetooth_state());
    bt_type.setText("type: " + bluetoothObject.getBluetooth_type());
    bt_signal_strength.setText("RSSI: " + bluetoothObject.getBluetooth_rssi() + "dbm");

    ParcelUuid uuid[] = bluetoothObject.getBluetooth_uuids();
    if (uuid != null)
        bt_uuid.setText("uuid" + uuid[0]);


    // 5. return rowView
    return rowView;

}//end getView()

}

AndroidManifest.xml

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

据我了解BroadcastReceiver不火。 Logcat 未显示任何错误消息,应用程序未显示任何蓝牙设备。我在这里做错了什么

我的 Android Studio 版本是 3.6.1。我的 minSdkVersion 是 18 而 compileSdkVersion 是 29.

您尚未请求执行扫描所需的位置或蓝牙权限。参见 https://developer.android.com/training/permissions/requesting#perm-check. Weirdly, it isn't mentioned on https://developer.android.com/guide/topics/connectivity/bluetooth

特别是,您需要检查 ACCESS_FINE_LOCATION 运行时权限,如果未被授予,您需要请求权限。

好吧,您不必两次调用 mBluetoothAdapter.startDiscovery();。需要一次。并确保您的清单中有 LocationBluetooth 权限。并确保您的设备可以被其他设备发现

好吧,我正在放置一些代码。希望对你有帮助

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {

            //if you have found the devices
            if (BluetoothDevice.ACTION_FOUND.equals(intent.getAction())) {

                // Now that you have found the device. Get the Bluetooth Device
                // object and its info from the Intent.

                BluetoothDevice deviceInfo = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                String deviceName = deviceInfo.getName();

              //Make sure you update your arraylist/recyclerlist adapter from here. As it 
              //invokes for every found device once.

            }
        }
    };

下面是如何调用它

IntentFilter bluetoothFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        context.registerReceiver(mReceiver, bluetoothFilter);
        final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        mBluetoothAdapter.startDiscovery();