2016-01-23 111 views
25

我目前正在開發一個小應用程序,以開始使用藍牙Android API可提供的服務。Android - 藍牙發現沒有找到任何設備

編輯 - >答:

看來,這個問題是由於特定的Nexus 5設備。似乎他們的藍牙接收器不能正常工作。下面的解決方案應適用於其他設備

備註:在/ lorensiuswlt/http://developer.android.com/guide/topics/connectivity/bluetooth.html 以及本教程http://www.londatiga.net/it/programming/android/how-to-programmatically-scan-or-discover-android-bluetooth-device/位於GitHub上的下面的源代碼:

  1. 我在這裏閱讀文檔AndroBluetooth

  2. 我已經完成了幾乎所有對我感興趣的功能(如檢查適配器是否存在,啓用/禁用藍牙,查詢配對設備,設置適配器可發現)。

問題:

實際上沒有裝置被發現當我啓動.onDiscovery()方法,即使器件由設置/藍牙我的Nexus 5.

發現以下是我如何處理它:

public class MainActivity extends AppCompatActivity { 
private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 

... 

protected void onCreate(Bundle savedInstanceState) { 
IntentFilter filter = new IntentFilter(); 
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); 
filter.addAction(BluetoothDevice.ACTION_FOUND); 
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); 
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); 
registerReceiver(mReceiver, filter); 
} 

過濾器是就我所能嘗試的那樣,運行良好,即ACTION_STATE_CHANGED(在藍牙啓用時)和兩個ACTION_DISCOVERY _ ***。

下面的方法,然後successfuly稱爲:

public void onDiscovery(View view) 
{ 
    mBluetoothAdapter.startDiscovery(); 
} 

然後,我有我的藍牙接收器:

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

     if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) { 
      final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); 

      if (state == BluetoothAdapter.STATE_ON) { 
       showToast("ACTION_STATE_CHANGED: STATE_ON"); 
      } 
     } 

     else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) { 
      mDeviceList = new ArrayList<>(); 
      showToast("ACTION_DISCOVERY_STARTED"); 
      mProgressDlg.show(); 
     } 

     else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action) && !bluetoothSwitchedOFF) { 
      mProgressDlg.dismiss(); 
      showToast("ACTION_DISCOVERY_FINISHED"); 

      Intent newIntent = new Intent(MainActivity.this, DeviceListActivity.class); 

      newIntent.putParcelableArrayListExtra("device.list", mDeviceList); 

      startActivity(newIntent); 
     } 

     else if (BluetoothDevice.ACTION_FOUND.equals(action)) {// When discovery finds a device 
      // Get the BluetoothDevice object from the Intent 
      BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 
      mDeviceList.add(device); 
      showToast("Device found = " + device.getName()); 
     } 
    } 
}; 

我沒有任何問題,走出logcat的,並沒有注意到我在測試過程中遇到任何麻煩。唯一的問題是在掃描結束時沒有發現任何設備,此時許多可發現的設備在周圍可用。

我試圖不要放太多的代碼,以免氾濫的話題。問我是否需要更多。

感謝您閱讀我,並提前感謝您的答案。

回答

51

你在使用哪個版本的Android?如果它是Android 6.x,我相信你需要添加ACCESS_COURSE_LOCATION權限到你的清單。例如:

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

我也有類似的問題,這個固定爲我。

UPDATE:在此添加documentation direct from Google

訪問通過藍牙和Wi-Fi掃描附近的外部裝置的硬件識別碼,您的應用程序現在必須有ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION權限

+0

這沒有奏效,我真的不明白爲什麼會這麼做,因爲這個權限是關於使用Android的網絡位置提供程序的。你確定這是固定你的問題嗎? – Amesys

+0

這也適用於我! – Xema

+0

是的。我們在Android 5上完全使用藍牙,升級到6時唯一的問題是在發現過程中找不到藍牙設備。這對我們也沒有任何意義。我們使用'startDiscovery()'方法,和你一樣。 – nverbeek

37

晚會晚了,但這可能會爲其他人派上用場。

你需要做兩件事情

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

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

到AndroidManifest.xml

  • 製作確保你在運行時請求權限以及Android 6。 0設備通過使用這樣的事情

    int MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION = 1; 
    ActivityCompat.requestPermissions(this, 
         new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 
         MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION); 
    

    之前mBluetoothAdapter.startDiscovery();

  • 如果你不這樣做第2步,你將無法得到任何硬件標識符信息的設備與Android> = 6.0

    UPDATE /編輯:
    例與Android版本檢查,並警告對話框,警告

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // Only ask for these permissions on runtime when running Android 6.0 or higher 
        switch (ContextCompat.checkSelfPermission(getBaseContext(), Manifest.permission.ACCESS_COARSE_LOCATION)) { 
         case PackageManager.PERMISSION_DENIED: 
          ((TextView) new AlertDialog.Builder(this) 
            .setTitle("Runtime Permissions up ahead") 
            .setMessage(Html.fromHtml("<p>To find nearby bluetooth devices please click \"Allow\" on the runtime permissions popup.</p>" + 
              "<p>For more info see <a href=\"http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id\">here</a>.</p>")) 
            .setNeutralButton("Okay", new DialogInterface.OnClickListener() { 
             @Override 
             public void onClick(DialogInterface dialog, int which) { 
              if (ContextCompat.checkSelfPermission(getBaseContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
               ActivityCompat.requestPermissions(DeviceListActivity.this, 
                 new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 
                 REQUEST_ACCESS_COARSE_LOCATION); 
              } 
             } 
            }) 
            .show() 
            .findViewById(android.R.id.message)) 
            .setMovementMethod(LinkMovementMethod.getInstance());  // Make the link clickable. Needs to be called after show(), in order to generate hyperlinks 
          break; 
         case PackageManager.PERMISSION_GRANTED: 
          break; 
        } 
    } 
    
    +1

    爲我工作,但然後startDiscovery()應返回false以防萬一它無法訪問。它仍然返回true,這是有點誤導... – mallaudin

    +0

    這可能是因爲它確實獲得了掃描的訪問權限,但不能檢索有關設備本身的信息。 https://developer.android.com/about/versions/marshmallow/android-6.0-changes。html#behavior-hardware-id – Nils

    +1

    我一直在撞牆的時候撞了我的頭,連續3天試圖讓它去找。然後找到這個帖子,接下來的第2步和賓果!有用。謝謝 – NoLiver92