Android Broadcast Receiver bluetooth events catching

Я пытаюсь поймать изменения состояния bluetooth с помощью широковещательного приемника.

Мой манифест:

<uses-permission android:name="android.permission.BLUETOOTH" />
<application>
     <activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <receiver android:name=".BluetoothBroadcastReceiver"
              android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
            <action android:name="android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED" />
            <action android:name="android.bluetooth.device.action.ACL_CONNECTED" />
            <action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
        </intent-filter>
    </receiver>
</application>

Метод приемника onReceive:

public void onReceive(Context context, Intent intent) {

    String action = intent.getAction();
    Log.d("BroadcastActions", "Action "+action+"received");
    int state;
    BluetoothDevice bluetoothDevice;

    switch(action)
    {
        case BluetoothAdapter.ACTION_STATE_CHANGED:
            state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
            if (state == BluetoothAdapter.STATE_OFF)
            {
                Toast.makeText(context, "Bluetooth is off", Toast.LENGTH_SHORT).show();
                Log.d("BroadcastActions", "Bluetooth is off");
            }
            else if (state == BluetoothAdapter.STATE_TURNING_OFF)
            {
                Toast.makeText(context, "Bluetooth is turning off", Toast.LENGTH_SHORT).show();
                Log.d("BroadcastActions", "Bluetooth is turning off");
            }
            else if(state == BluetoothAdapter.STATE_ON)
            {
                Log.d("BroadcastActions", "Bluetooth is on");
            }
            break;

        case BluetoothDevice.ACTION_ACL_CONNECTED:
            bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            Toast.makeText(context, "Connected to "+bluetoothDevice.getName(),
                    Toast.LENGTH_SHORT).show();
            Log.d("BroadcastActions", "Connected to "+bluetoothDevice.getName());
            break;

        case BluetoothDevice.ACTION_ACL_DISCONNECTED:
            bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            Toast.makeText(context, "Disconnected from "+bluetoothDevice.getName(),
                    Toast.LENGTH_SHORT).show();
            break;
    }
}

Я запускаю приложение, а затем минимизирую его, нажав кнопку "Домой". Перейдите в настройки и включите bluetooth, но ничего не происходит. Хотя я ожидаю сообщения тоста и логарифма. Что здесь не так?

Ответы

Ответ 1

Чтобы улавливать изменения состояния Bluetooth (STATE_OFF, STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF), сделайте это в своей деятельности:

Сначала добавьте разрешение Bluetooth в файл AndroidManifest:

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

Создайте BroadcastReceiver в своей деятельности или службе:

    private final BroadcastReceiver mBroadcastReceiver1 = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();

        if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
            final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
            switch(state) {
                case BluetoothAdapter.STATE_OFF:
                    ..
                    break;
                case BluetoothAdapter.STATE_TURNING_OFF:
                    ..
                    break;
                case BluetoothAdapter.STATE_ON:
                    ..
                    break;
                case BluetoothAdapter.STATE_TURNING_ON:
                    ..
                    break;
            }

        }
    }
};

Создайте IntentFilter и зарегистрируйте его с помощью BroadcastReceiver для Activity/Service в вашем методе onCreate():

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

    IntentFilter filter1 = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
    registerReceiver(mBroadcastReceiver1, filter1);

    ...
}

Отменить регистрацию BroadcastReceiver в методе onDestroy():

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

    unregisterReceiver(mBroadcastReceiver1);
}

Чтобы уловить изменения в обнаружении устройства (SCAN_MODE_NONE, SCAN_MODE_CONNECTABLE, SCAN_MODE_CONNECTABLE_DISCOVERABLE), создайте еще один BroadcastReceiver и зарегистрируйте/отмените регистрацию в своей Деятельности, как я упоминал выше. Только различие между этими вещами BroadcastReceiver в первую использует BluetoothAdapter.EXTRA_STATE, а другое использует BluetoothAdapter.EXTRA_SCAN_MODE. Вот пример кода для BroadcastReceiver для обнаружения изменений в видимости:

Создайте фильтр и зарегистрируйте его в методе onCreate():

IntentFilter filter2 = new IntentFilter();
filter2.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter2.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
filter2.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
registerReceiver(mBroadcastReceiver2, filter2);

Создайте BroadcastReciver в Activity/Service, чтобы уловить изменения в видимости:

    private final BroadcastReceiver mBroadcastReceiver2 = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();

        if(action.equals(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED)) {

            int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.ERROR);

            switch(mode){
                case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
                    ..
                    break;
                case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
                    ..
                    break;
                case BluetoothAdapter.SCAN_MODE_NONE:
                    ..
                    break;
            }
        }
    }
};

И, наконец, отмените регистрацию в onDestroy():

unregisterReceiver(mBroadcastReceiver2);

Обратите внимание, что вам не нужно добавлять какие-либо <intent-filter> или <receiver> в ваш файл AndroidManifest, за исключением того, что вам нужно, конечно, добавить разрешение Bluetooth.

Если вы хотите поймать (ACTION_ACL_CONNECTED, ACTION_ACL_DISCONNECTED, ACTION_ACL_DISCONNECT_REQUESTED), теперь вам нужно добавить <intent-filter> в ваш файл AndroidManifest:

<intent-filter>
    <action android:name="android.bluetooth.device.action.ACL_CONNECTED" />
    <action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
</intent-filter>

Создайте фильтр и зарегистрируйте его в методе onCreate():

IntentFilter filter3 = new IntentFilter();
filter3.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter3.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
registerReceiver(mBroadcastReceiver3, filter3);

Затем создайте BroadcastReceiver в своей деятельности/службе:

    private final BroadcastReceiver mBroadcastReceiver3 = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();

        switch (action){
            case BluetoothDevice.ACTION_ACL_CONNECTED:
                ..
                break;
            case BluetoothDevice.ACTION_ACL_DISCONNECTED:
                ..
                break;
        }
    }
};

И, наконец, отмените регистрацию:

unregisterReceiver(mBroadcastReceiver3);

Если вы хотите больше узнать о константах состояния, это из документации:

public static final String EXTRA_STATE:

Используется как дополнительное поле в ACTION_STATE_CHANGED для запроса текущее состояние мощности. Возможные значения: STATE_OFF, STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF

public static final String EXTRA_SCAN_MODE:

Используется как int дополнительное поле в ACTION_SCAN_MODE_CHANGED намерениях запросить текущий режим сканирования. Возможные значения: SCAN_MODE_NONE, SCAN_MODE_CONNECTABLE, SCAN_MODE_CONNECTABLE_DISCOVERABLE

Ответ 2

Ваша основная проблема;) Вы не можете использовать "переключатель" для сравнения строк.

По крайней мере, до версии VERSION_INT 18 (включительно). Версия 19 началась с Java 7.