AndroidStudio Kotlin подключиться к bluetooth - PullRequest
0 голосов
/ 27 мая 2020

Я добавил <uses-permission android:name="android.permission.BLUETOOTH" /> в свой манифест, но ошибка

Отсутствует разрешение, требуемое BluetoothAdapter.isEnabled: android .permission.BLUETOOTH. все еще там.

Кроме того, в ContextCompat.checkSelfPermission(...) какой первый параметр CONTEXT? В документации https://developer.android.com/training/permissions/requesting не сказано.

И правильно ли, что мне нужно отключать и повторно подключать bluetooth всякий раз, когда приложение не используется?

class MainActivity : AppCompatActivity() {

    var bt: BluetoothAdapter? = null
    var bts: BluetoothSocket? = null
    val REQUEST_BLUETOOTH_PERMISSION: Int = 1
    val REQUEST_BLUETOOTH_ENABLE: Int = 2

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE))
        {
            Toast.makeText(
                getApplicationContext(),
                "Device does not support Bluetooth therefore this application cannot run.",
                Toast.LENGTH_SHORT
            ).show();
            return;
        }

        bt = BluetoothAdapter.getDefaultAdapter()
        if (bt == null) {
            // This device does not have Bluetooth.
            Toast.makeText(
                getApplicationContext(),
                "Device does not have a Bluetooth adapter therefore this application cannot run.",
                Toast.LENGTH_SHORT
            ).show();
            return;
        }

        bluetoothConnect();
    }

    fun bluetoothConnect() {
        if (ContextCompat.checkSelfPermission(
                CONTEXT, // What is this? It's not explained at https://developer.android.com/training/permissions/requesting
                Manifest.permission.BLUETOOTH
            ) == PackageManager.PERMISSION_GRANTED
        ) {

            if (bt.isEnabled == false) { // Error: Missing permission required by BluetoothAdapter.isEnabled: android.permission.BLUETOOTH.
                val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
                startActivityForResult(enableBtIntent, REQUEST_BLUETOOTH_ENABLE)
            } else {
                val pairedDevices: Set<BluetoothDevice>? = bt.bondedDevices
                pairedDevices?.forEach { device ->
                    val deviceName = device.name
                    val deviceHardwareAddress = device.address // MAC address
                }
            }
        }
        else {
            // Request permission. That will call back to onActivityResult which in the case of success will call this method again.
            // Ask for permission.
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.BLUETOOTH),
                REQUEST_BLUETOOTH_PERMISSION
            )
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (requestCode == REQUEST_BLUETOOTH_PERMISSION) {
            if (resultCode == RESULT_OK) {
                bluetoothConnect();
            } else {
                Toast.makeText(
                    getApplicationContext(),
                    "This application cannot run because it does not have Bluetooth permission.",
                    Toast.LENGTH_SHORT
                ).show();
                // Do we need to quit? How?
            }
        }
        else if( requestCode == REQUEST_BLUETOOTH_ENABLE)
        {
            if(resultCode == RESULT_OK)
            {
                // try again
                bluetoothConnect();
            }
            else {
                Toast.makeText(
                    getApplicationContext(),
                    "This application cannot run because Bluetooth is not enabled and could not be enabled.",
                    Toast.LENGTH_SHORT
                ).show();
                // Do we need to quit? How?
            }
        }
    }


    override fun onPause() {
        super.onPause()
        // Release Bluetooth
    }

    override fun onResume() {
        super.onResume()
        // Connect Bluetooth
    }

    override fun onStop() {
        super.onStop()
        // Release Bluetooth
    }

    override fun onStart() {
        super.onStart()
        // Connect Bluetooth
    }

}

Изменить:

  • добавлена ​​дополнительная проверка BT в код,
  • добавлен манифест
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.rwb.btconnectortest">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/btconnectortestTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Ответы [ 2 ]

1 голос
/ 27 мая 2020

Просто потому, что комментарии для этого не годятся, позвольте мне дать вам список вещей, которые вам следует сделать, прежде чем вы сможете действовать с помощью Bluetooth. (извиняюсь, это Java, потому что это то, что у меня есть прямо сейчас, но очень легко перевести на Kotlin, если необходимо)

Я делаю это для BT LE (с низким энергопотреблением), что является предпочтительным путь по .. очевидным причинам.

  1. Вы добавляли разрешения в манифест? Вам нужно что-то вроде
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
<uses-permission android:name="android.permission.BLUETOOTH"/>
Убедитесь, что Bluetooth существует и включен ...
// Does BLE exist?
if(getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){
    final BluetoothManager manager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);

Теперь, когда у вас есть менеджер, вам нужно получить BluetoothAdapter:

    BluetoothAdapter bluetoothAdapter = manager.getAdapter();

Все это нормально в onCreate, но имейте в виду, что вы должны проверять, включен ли BT каждый раз, когда пользователь возобновляет активность (поскольку это могло быть выключено / отключено / отозвано / и т.д. c).

Вероятно в onResume:

// obviously, you need to check that Bt adapter isn't null and all that, 
// otherwise you ought to go back and "construct" it again, check permissions, etc.
adapter = getBTAdapter(); // do all the checks in there...
boolean bluetoothEnabled = adapter != null && adapter.isEnabled();

Если радиомодуль BT выключен (пользователь отключил его), вы можете включить его программно, , если у вас есть соответствующее разрешение (что я думаю, это администратор BT или аналогичный, вам придется поискать этого, потому что это было давно).

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> Я думаю, что это было.

Поскольку BT - это радио, которому требуется питание, потребуется некоторое время (секунды), чтобы включиться и стать доступным. Для этого вам нужно «слушать» с помощью еще одного широковещательного приемника ...

Другими словами, действие вызовет намерение (startActivityForResult(...)), сообщающее Android включить BT, вы подпишетесь на это трансляция для прослушивания обратного вызова. Как только android проинформирует вас о том, что BT включен, вы можете go вернуться к шагу 1 и начать проверять, включен ли он, у вас есть разрешение и т. c.

Обратный вызов - если я не забыл слишком много ... выглядело как

        public void onReceive(Context context, Intent intent) {

Там вы должны проверить различные BluetoothAdapter состояния ... среди них:

BluetoothAdapter.ACTION_STATE_CHANGED

Это сигнализирует, что состояние изменилось, но другое вложенное состояние, если необходимо для определения до какого состояния ...

final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE);
switch (state) {
   case BluetoothAdapter.STATE_OFF:
   case BluetoothAdapter.STATE_TURNING_OFF:
   case BluetoothAdapter.STATE_TURNING_ON:
   case BluetoothAdapter.STATE_ON:
}

Это все те, которые вам небезразличны (отметьте перечисление BluetoothAdapter для получения дополнительной информации).

В ON вы знаете, что BT включен ... так что ...

Теперь вы можете сообщить адаптеру, что хотите scan. ..

adapter.startLeScan(callback);

(не забудьте позвонить stopLeScan(callback), когда закончите).

При обнаружении каждого устройства будет вызываться callback с информацией, необходимой для попытки подключения и сопряжения (при необходимости).

Сигнатура обратного вызова (LeScanCallback) выглядит примерно так:

    public void onScan(final BluetoothDevice device, int rssi, byte[] record);

(я печатаю по памяти, так что это может быть другое имя, но вы уловили идею)

Это, насколько я помню, старый API.

API 21 имеет ScanSettings.Builder(), где вы можете указать, как вы хотите сканировать, но по сути это аналогичный метод. Запустите сканирование, передайте обратный вызов и дождитесь появления результатов.

У вас также есть разные режимы:

  • SCAN_MODE_BALANCED: баланс эффективности батареи и скорости сканирования

  • SCAN_MODE_LOW_LATENCY: предпочитать скорость сканирования батарея

  • SCAN_MODE_LOW_POWER: эффективность батареи предпочтительнее скорости сканирования

  • SCAN_MODE_OPPORTUNISTI C: не помню :) Я думаю это было использовать результаты других сканеров «вокруг» вас. Никогда не использовал его.

После того, как вы определили устройство, которое искали, BluetoothDevice имеет все необходимое, чтобы сообщить BT о «подключении» к нему.

    public void onScanResult(int callbackType, ScanResult scanResult) {

^ это подпись «нового» сканера.

Из этого ScanResult вы можете сделать:

  int rssi = result.getRssi();
  BluetoothDevice device = result.getDevice();

  String advertiseName = device.getName();
  String macAddress = device.getAddress();    

Если сканирование завершится неудачно по какой-либо причине, вы получите обратный вызов на onScanFailed(int errorCode). И снова, есть разные «причины» (проверьте errorCode), почему сканирование не удалось.

Помните, я могу смешивать API 18 или API 21 здесь, но концепция очень похожа в обоих .

После того, как вы наконец получили адрес MA C устройства ... вы можете попросить адаптер попытаться подключиться к нему:

BluetoothDevice device = adapter.getRemoteDevice(macAddress);
device.connectGatt(context, false, anotherCallback);

Обратный вызов имеет BluetoothGattCallback, и опять же, среди них есть несколько методов onConnectionStateChange...

На этом этапе вам следует больше узнать о том, как работает Bluetooth (и как он работает на Android) потому что существуют различные режимы (Gatt - односторонний) работы с BT. Невозможно знать каждый и как / что вы хотите делать после подключения.

Практическое правило будет: убедитесь, что вы готовы к повторному соединению или повторному запросу разрешений, потому что в конечном итоге это выбор пользователя: отключить, выключить, уйти, отозвать разрешение и т. д. c. в в любой точке при этом.

Удачи!

0 голосов
/ 27 мая 2020

Я перезапустил AndroidStudio, и теперь ошибка исчезла. Что за фигня полный sh.

а вот макет сломан ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...