Android 12 以上版本中的蓝牙发现问题

问题描述 投票:0回答:1

我正在编写一个非常简单的测试 Android 应用程序,它可以发现蓝牙设备并将其显示在屏幕上。此应用程序在 Android 9 上正常运行,但在 Android 12 上无法正常运行。 我在请求权限时没有遇到任何问题,并且它可以正确检测到它们。事实上,它成功运行了 bluetoothAdapter.startDiscovery(),但 BroadcastReceiver 没有向我显示任何设备。 我一直无法找到原因,也不知道可能是什么问题。请任何人帮助我,或者有人知道在高于 Android 12 的版本中执行此功能的代码示例吗?

这是执行blueetoothAdapter.startDiscovery()方法后的Android Logcat

2023-06-22 13:33:16.317 10495-10495 蓝牙适配器 com.example.discoverydevicestest 我开始Discovery 2023-06-22 13:33:16.322 10495-10495 DiscoveryTest com.example.discoverydevicestest E 发现设备启动 2023-06-22 13:33:16.327 10495-10495 Toast com.example.discoverydevicestest V 显示:来电者 = com.example.discoverydevicestest.DiscoveryAndroid12.startDiscovery:199 2023-06-22 13:33:16.327 10495-10495 Toast com.example.discoverydevicestest V 显示:focusDisplayId = 0,isFocusInDesktop = false mCustomDisplayId=-1 isDexDualMode=false 2023-06-22 13:33:16.327 10495-10495 Toast com.example.discoverydevicestest V 显示:isActivityContext = true

我的代码

public class DiscoveryAndroid12 extends AppCompatActivity {

    private static final String TAG = "DiscoveryTest";
    private static final int REQUEST_ENABLE_BLUETOOTH = 1;
    private static final int REQUEST_PERMISSION_LOCATION = 2;
    private static final int REQUEST_BLUETOOTH_SCAN_PERMISSION = 3;
    private static final int REQUEST_BLUETOOTH_CONNECT_PERMISSION = 4;
    private static final int REQUEST_BLUETOOTH_A12_PERMISSIONS = 5;

    private BluetoothAdapter bluetoothAdapter;
    private ArrayAdapter<String> deviceListAdapter;
    private List<BluetoothDevice> discoveredDevices;

    private Button discoverButton;
    private ListView deviceListView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        discoverButton = findViewById(R.id.discoverButton);
        deviceListView = findViewById(R.id.deviceListView);

        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        discoveredDevices = new ArrayList<>();
        deviceListAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);
        deviceListView.setAdapter(deviceListAdapter);

        discoverButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                discoverDevices();
            }
        });

        deviceListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                connectToDevice(position);
            }
        });

        // Check if the device has bluetooth
        if (bluetoothAdapter == null) {
            Toast.makeText(this, "Bluetooth is not supported on this device", Toast.LENGTH_SHORT).show();
            finish();
        }

        // Register for broadcasts when a device is discovered.
        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        registerReceiver(receiver, filter);

    }

    // Create a BroadcastReceiver for ACTION_FOUND.
    private final BroadcastReceiver receiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                Log.e(TAG, "Device detected!");
                // Discovery has found a device. Get the BluetoothDevice
                // object and its info from the Intent.
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
                    // TODO: Consider calling
                    //    ActivityCompat#requestPermissions
                }
                String deviceName = device.getName();
                String deviceHardwareAddress = device.getAddress(); // MAC address
                Log.e(TAG, "Device found: " + deviceName + ": " + deviceHardwareAddress);

                discoveredDevices.add(device);
                String show = (deviceName != null) ? deviceName + ": " + deviceHardwareAddress : "Unknown name: " + deviceHardwareAddress;
                deviceListAdapter.add(show);

            }
        }
    };

    private void discoverDevices() {
        Log.e(TAG, "Starting process to search devices...");
        boolean isGranted = true;

        //Check permissions
        if (Build.VERSION.SDK_INT >= 31) {
            isGranted = checkBTScanAndConnectPermissions();
        } else {
            isGranted = checkLocationPermission();
        }

        if (isGranted) { //If permissions are granted
            // Check if bluetooth is enabled
            if (!bluetoothAdapter.isEnabled()) {
                Log.e(TAG, "BT disabled, requesting user to enable it");
                Intent enableBluetoothIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBluetoothIntent, REQUEST_ENABLE_BLUETOOTH);
            } else {
                Log.e(TAG, "BT enabled, starting dicovery");
                startDiscovery();
            }
        }

    }

    private boolean checkLocationPermission() {

        Log.e(TAG, "Checking LOCATION permissions...");
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSION_LOCATION);
            return false;
        } else {
            Log.e(TAG, "Location permission granted");
            return true;
        }
    }

    private boolean checkScanPermission() {

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN)
                != PackageManager.PERMISSION_GRANTED) {
            Log.e(TAG, "BLUETOOTH_SCAN permission is not granted, requesting it...");
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_SCAN}, REQUEST_BLUETOOTH_SCAN_PERMISSION);
            return false;
        } else {
            Log.e(TAG, "BLUETOOTH_SCAN  permission granted");
            return true;
        }
    }



    @RequiresApi(api = Build.VERSION_CODES.S)
    private boolean checkBTScanAndConnectPermissions() {

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT}, REQUEST_BLUETOOTH_A12_PERMISSIONS);
            return false;
        } else {
            Log.e(TAG, "BLUETOOTH SCAN and CONNECT permissions granted");
            return true;
        }
    }

    private void startDiscovery() {
        boolean isGranted = true;
        deviceListAdapter.clear();
        discoveredDevices.clear();
        // Starting BT devices discovery
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
            if (Build.VERSION.SDK_INT >= 31) {
                isGranted = checkScanPermission();
            }
        }

        if (isGranted) {
            Log.e(TAG, "BT scan permissions already granted");
            bluetoothAdapter.startDiscovery();
            Log.e(TAG, "Discovery devices start");
            Toast.makeText(this, "Discovering devices...", Toast.LENGTH_SHORT).show();
        }

    }

    private void connectToDevice(int position) {
        BluetoothDevice device = discoveredDevices.get(position);

        // Actions to connect to BT device

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
        }

        Toast.makeText(this, "Connecting to device: " + device.getName(), Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_ENABLE_BLUETOOTH) {
            if (resultCode == RESULT_OK) {
                startDiscovery();
                Toast.makeText(this, "Bluetooth enabled", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, "Bluetooth activation was canceled", Toast.LENGTH_SHORT).show();
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {


        if (requestCode == REQUEST_PERMISSION_LOCATION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                discoverDevices();
            } else {
                Toast.makeText(this, "Location permission denied", Toast.LENGTH_SHORT).show();
            }
        }

        if (requestCode == REQUEST_BLUETOOTH_SCAN_PERMISSION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                startDiscovery();
                Toast.makeText(this, "Scan permission granted", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, "Scan permission denied", Toast.LENGTH_SHORT).show();
            }
        }

        if (requestCode == REQUEST_BLUETOOTH_A12_PERMISSIONS) {
            boolean isgranted = true;
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Log.d(TAG, "Scan permission granted");
                Toast.makeText(this, "Scan permission granted", Toast.LENGTH_SHORT).show();
            } else {
                Log.d(TAG, "Scan permission denied");
                Toast.makeText(this, "Scan permission denied", Toast.LENGTH_SHORT).show();
                isgranted = false;
            }

            if (grantResults.length > 0 && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
                Log.d(TAG, "Connect permission granted");
                Toast.makeText(this, "Connect permission granted", Toast.LENGTH_SHORT).show();
            } else {
                Log.d(TAG, "Connect permission denied");
                Toast.makeText(this, "Connect permission denied", Toast.LENGTH_SHORT).show();
                isgranted = false;
            }

            if (isgranted){
                discoverDevices();
            }
        }


        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions

        }
        bluetoothAdapter.cancelDiscovery();
    }
}

AndroidManifest.xml 文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <!-- Request legacy Bluetooth permissions on older devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30"/>

    <!-- Needed only if your app looks for Bluetooth devices.
     You must add an attribute to this permission, or declare the
     ACCESS_FINE_LOCATION permission, depending on the results when you
     check location usage in your app. -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

    <!-- Needed only if your app makes the device discoverable to Bluetooth
         devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

    <!-- Needed only if your app communicates with already-paired Bluetooth
         devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

    <!-- Needed only if your app uses Bluetooth scan results to derive physical location. -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />


    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.DiscoveryDevicesTest"
        tools:targetApi="31">
        <activity
            android:name=".DiscoveryAndroid12"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.bluetooth.device.action.FOUND" />
            </intent-filter>

        </activity>
    </application>

</manifest>

在 Android 12 中使用 BroadcastReceiver 时有什么需要注意的事项吗?

预先感谢您的贡献!

android bluetooth broadcastreceiver android-permissions bluetoothadapter
1个回答
0
投票

我正在开发 MAUI,并面临可用设备列表显示为空的问题。

这拯救了我的一天,非常感谢。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.