【问题标题】:Bluetooth on Android: StartDiscovery not working. Cannot scan devicesAndroid 上的蓝牙:StartDiscovery 不起作用。无法扫描设备
【发布时间】:2013-04-17 13:22:30
【问题描述】:

我是 android 新手,我正在制作一个具有蓝牙功能的应用程序。我可以设置蓝牙适配器,获取我自己的设备信息,但我无法使用 startdiscovery 来发现蓝牙设备。当我开始扫描时,它什么也不做。

我正在使用 onclicklistner 开始扫描:

  bt.setOnClickListener(new OnClickListener() {
           @Override
           public void onClick(View v) {
               if (!(bluetooth.isEnabled())) {
                   status = "Bluetooth is not Enabled.";
                   Toast.makeText(AddUser.this, status, Toast.LENGTH_LONG).show();
                   Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, 1);

                }
                else
                {

                    scand();
                }

           }

这是我在“public void onCreate”函数之后放置的 onActivityResult 函数:

 protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    System.out.println(resultCode);
    if (resultCode ==  RESULT_CANCELED) {
        status="Error Enabling bluetooth";
        Toast.makeText(AddUser.this, status, Toast.LENGTH_LONG).show();
    } else {

            scand();
    }



}

这是我的 scand 函数,我在其中调用了 startdiscovery:

    private void scand()
{



   bluetooth.startDiscovery(); 
   Log.d("itmes", ""+items.size());
   item1 = new String[items.size()];
   item1 = items.toArray(item1);
   AlertDialog.Builder builder = new AlertDialog.Builder(this);
   builder.setTitle("Choose a device");
   builder.setItems(item1, new DialogInterface.OnClickListener() {

       public void onClick(DialogInterface dialog, int item) {
            Toast.makeText(getApplicationContext(), item1[item], Toast.LENGTH_SHORT).show();

       }

    });

    AlertDialog alert = builder.create();

    alert.show();

}

这是广播接收器:

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

            if (BluetoothDevice.ACTION_FOUND.equals(action)) 
            {
                   Log.e("br", "--- device found ---");
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

               items.add(device.getName());
            }
          }
        };

在上面的广播接收器代码中,我试图将找到的设备名称放在字符串 ArrayList "items" 中。

我在 oncreate 函数中注册广播接收器,如下所示:

filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
   registerReceiver(mReceiver, filter);

我在 androidmanifest 文件中设置了蓝牙权限。在上面的 scand 函数中,它应该显示已发现设备的列表,但它显示的是一个只有标题的空对话框。请告诉我如何正确使用 startdiscovery 和 broadcastreceiver 在 alertdialog 中显示结果。

【问题讨论】:

  • 您尝试扫描的蓝牙设备是否处于发现模式?
  • 是的,它们是可发现的。
  • startdiscovery和broadcastreceiver的使用方法正确吗?
  • 你的广播接收器在你的活动中吗?
  • 是的,在activity类里面,在oncreate函数之后

标签: android bluetooth


【解决方案1】:

如果您的应用面向 Android 11(API 级别 30)或更低版本,请在 Android 开发人员中使用 ACCESS_FINE_LOCATION,这是必要的

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

如果您的应用针对 API 级别 23 或更低,则必须在运行时检查权限和请求权限

if(checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        discovery()
    } else {
        requestLocationPermissions()
    }

private fun discovery() {
    if (bluetoothAdapter == null) {
        //bluetooth can't work

    } else {
        if (bluetoothAdapter.isEnabled) {
            bluetoothAdapter.startDiscovery()
        } else {
            startBluetooth()
        }
    }
}

private fun startBluetooth() {
    val bluetoothIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
    startActivityForResult(bluetoothIntent, REQUET_ENABLE_BT)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    when(requestCode) {
        REQUET_ENABLE_BT -> {
            if (resultCode == RESULT_OK) {
                discovery()
            } else {
                Toast.makeText(baseContext, "bluetooth open failed", Toast.LENGTH_SHORT).show()
            }
        }
        else -> {
            super.onActivityResult(requestCode, resultCode, data)
        }
    }
}

【讨论】:

    【解决方案2】:
      discovery() {
         IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
         this.registerReceiver(mReceiver, filter);
         // Register for broadcasts when discovery has finished
         filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
         this.registerReceiver(mReceiver, filter);
            
         // If we're already discovering, stop it
         if (mBluetoothAdapter.isDiscovering()) {
             mBluetoothAdapter.cancelDiscovery();
         }
         // Request discover from BluetoothAdapter
         mBluetoothAdapter.startDiscovery();
      }
    

    广播接收器:

      private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
      @Override
      public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            // When discovery finds a device
            try {
                Broadcast=true;
                if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                    // Get the BluetoothDevice object from the Intent
                    BluetoothDevice device = intent
                            .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
    
                    // If it's already paired, skip it, because it's been listed
                    // already
                    if (device.getBondState() !=BluetoothDevice.BOND_BONDED)    {
                        
                        near_device.add(device.getAddress());
                    
                    // When discovery is finished, change the Activity title
                } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED
                        .equals(action)) {
                    scanResult();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    };
    
     scanresult()
        {
    
                mBluetoothAdapter.cancelDiscovery();
                receiverCheck = false;
                // Unregister broadcast listeners
                Home.this.unregisterReceiver(mReceiver);
              // near device arraylist contain all device mac address
        }
    

    【讨论】:

      【解决方案3】:

      检查你有

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

      在您的清单中。

      https://developer.android.com/reference/android/bluetooth/BluetoothDevice#ACTION_FOUND

      【讨论】:

      • 哇.. 出乎意料的成功。谢谢
      • 如果您是目标 9+,请检查您是否拥有 Manifest.permission.ACCESS_FINE_LOCATION
      【解决方案4】:

      好吧,在我看来,当您将数组 item1 设置为要在 AlertDialog 中显示的内容时,您是在告诉 Dialog 在那个时刻显示数组中的项目(一个空数组),所以您不会看到元素。

      我不确定您是否可以在这样做之后更新 item1 数组的内容并期望刷新 AlertDialog。我不认为这是这样工作的(但我从来没有尝试过,无论如何)。

      我使用 ListView 和 Adapter 在我的应用程序中做了类似的事情,因此当您通过适配器添加项目时,ListView 会刷新(无论如何您都必须使用 adapter.notifyDataSetChanged()):

      protected ArrayList<BluetoothDevice> foundDevices 
                            = new ArrayList<BluetoothDevice>();
      private ListView foundDevicesListView;
      private ArrayAdapter<BluetoothDevice> adapter;
      
      foundDevicesListView = (ListView) findViewById(R.id.foundDevicesListView);
      
      adapter = new ArrayAdapter<BluetoothDevice>(this,
                  android.R.layout.simple_list_item_1, foundDevices);
      foundDevicesListView.setAdapter(adapter);
      //
      //  Initialization, etc ....
      
      
          BroadcastReceiver mReceiver = new BroadcastReceiver() {
              public void onReceive(Context context, Intent intent) {
                  String action = intent.getAction();
      
                  // When discovery finds a new device
                  if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                      // Get the BluetoothDevice object from the Intent
                      BluetoothDevice device= intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE));
                      if (!foundDevices.contains(device)) {
                          foundDevices.add(device);
                          adapter.notifyDataSetChanged();
                      }
                  }
      
                  // When discovery cycle finished
                  if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                      if(foundDevices==null || foundDevices.isEmpty()){
                          // Show not devices found message
                      }
                  }
              } 
      

      【讨论】:

        【解决方案5】:

        startDiscovery() 是异步的,您不会在调用后立即收到结果。移动代码以显示对话框到一个函数,比如说 public void showScanResult() 并在你的 onReceive 中调用它。

        【讨论】:

        • 这可能不起作用,因为我不确定您是否可以显示该对话框。但是尝试一下,我们就从那里开始。
        • 是的,我在 startdiscovery 调用之后使用了 while(bluetooth.isdiscovering){}。它会等到发现完成,这是正确的做法吗?它现在正在工作。感谢您的回复。 :)
        • 你不应该这样做,因为如果发现时间超过 5 秒,你可能会得到 ANR。先试试我的方法,然后我们就从那里开始。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-03
        相关资源
        最近更新 更多