2017-01-07 65 views
0

我製作了一個應用程序,即發現附近的藍牙設備等。我可以獲得藍牙適配器,打開關閉程序,獲得配對設備,發現程序。 Everthing很好,但發現過程不正常。Android藍牙發現API不適用於Android 6.0

我在5種不同的真實設備上測試了我的應用程序。目前我意識到我在Android版本上遇到問題,但我不確定。

我的應用程序的發現過程工作,

  • 華爲P7 - 安卓版本:4.4.2
  • 索尼XPERIA Z^- 的Android版本:5.1.1
  • 三星Galaxy J3 - 安卓版本:5.1.1

我的應用程序的發現過程是不工作的,

  • 三星Galaxy S7 - 安卓版本:6.0.1
  • 三星Galaxy J7 - 安卓版本:6.0.1

MainActivity.java

package com.sphinxlike.bluetoothexample; 

import android.bluetooth.BluetoothAdapter; 
import android.bluetooth.BluetoothDevice; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.os.Handler; 
import android.os.Parcelable; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.ArrayAdapter; 
import android.widget.Button; 
import android.widget.ListView; 
import android.widget.TextView; 
import android.widget.Toast; 

import java.util.ArrayList; 
import java.util.Iterator; 
import java.util.Set; 

import static java.lang.System.out; 


public class MainActivity extends AppCompatActivity implements View.OnClickListener{ 

    /* DECLERATIONS */ 
    // Button 
    Button openBtn = null;          // Open button 
    Button closeBtn = null;          // Close button 
    Button listBtn = null;          // Paired devices list button 
    Button searchBtn = null;         // Discovery new devices button 

    // Bluetooth 
    private BluetoothAdapter mBluetoothAdapter = null;   // Local bluetooth adapter variable 
    private static final int REQUEST_ENABLE_BT = 1;    // Bluetooth open intent variable 
    String mDeviceName = null; 
    String mDeviceAddress = null; 
    public static String EXTRA_ADDRESS = "device_address"; 

    // XML 
    TextView tvDeviceName = null;        // To show local bluetooth device's name 
    TextView tvBluetoothState = null;       // To show bluetooth state 
    ListView lvDeviceList = null;        // To list paired devices or discovered devices 

    // Set, List, Array Adapter 
    private Set<BluetoothDevice> mPairedDevicesSet = null;  // Paired devices Set 
    private Set<BluetoothDevice> mNewDevicesSet = null;   // New devices Set 
    ArrayAdapter mPairedDevicesAdapter = null;     // Paired devices array adapter 
    ArrayAdapter mNewDevicesAdapter = null;      // New devices array adapter 
    ArrayList bluetoothDeviceList = null;      // Listing bluetooth devices 
    private ArrayList<BluetoothDevice> btDeviceList = new ArrayList<BluetoothDevice>(); 

    // Bluetooth State Updater 
    private Handler mHandler;         // Loop in UI 

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

     // Initializes UI elements 
     tvDeviceName = (TextView)findViewById(R.id.deviceName); 
     tvBluetoothState = (TextView)findViewById(R.id.bluetoothState); 
     openBtn = (Button)findViewById(R.id.openBluetooth); 
     closeBtn = (Button)findViewById(R.id.closeBluetooth); 
     listBtn = (Button)findViewById(R.id.listBluetooth); 
     searchBtn = (Button)findViewById(R.id.searchBluetooth); 
     lvDeviceList = (ListView)findViewById(R.id.deviceList); 

     // Bluetooth adapter 
     mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 

     // Button checks 
     openBtn.setOnClickListener((View.OnClickListener) this); 
     closeBtn.setOnClickListener((View.OnClickListener) this); 
     listBtn.setOnClickListener((View.OnClickListener) this); 
     searchBtn.setOnClickListener((View.OnClickListener) this); 

     // To update bluetooth state text view 
     tvBluetoothState.setText(String.valueOf(mBluetoothAdapter.getState())); 


     // If the phone does not support bluetooth adapter 
     if (mBluetoothAdapter == null) { 
      tvBluetoothState.setText("Your phone has not Bluetooth Adapter"); 
      openBtn.setEnabled(false); 
      closeBtn.setEnabled(false); 
      listBtn.setEnabled(false); 
      searchBtn.setEnabled(false); 
     } 

     // Updater loop 
     mHandler = new Handler(); 
     mHandler.post(mUpdate); 
    } 

    // Updater Loop 
    private Runnable mUpdate = new Runnable() { 
     public void run() { 
      getBluetoothState(); 
      mHandler.postDelayed(this, 500); 
     } 
    }; 

    // Button onClick method 
    public void onClick(View v) { 
     switch (v.getId()) { 
      case R.id.openBluetooth: 
       if (!mBluetoothAdapter.isEnabled()) { 
        Intent bluetoothAcIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 
        startActivityForResult(bluetoothAcIntent, REQUEST_ENABLE_BT); 
       } else { 
        Toast.makeText(getApplicationContext(), "Bluetooth is already open", Toast.LENGTH_SHORT).show(); 
       } 
       break; 
      case R.id.closeBluetooth: 
       if (mBluetoothAdapter.isEnabled()) { 
        mBluetoothAdapter.disable(); 
       } else { 
        Toast.makeText(getApplicationContext(), "Bluetooth is already close", Toast.LENGTH_SHORT).show(); 
       } 
       break; 
      case R.id.listBluetooth: 
       pairedDevicesList(); 
       break; 
      case R.id.searchBluetooth: 
       IntentFilter filter = new IntentFilter(); 

       filter.addAction(BluetoothDevice.ACTION_FOUND); 
       filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); 
       filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); 

       registerReceiver(mBroadcastReceiver, filter); 
       mBluetoothAdapter.startDiscovery(); 

       break; 
     } 
    }; 

    @Override 
    public void onDestroy() { 
     unregisterReceiver(mBroadcastReceiver); 

     super.onDestroy(); 
    } 

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 
     public void onReceive(Context context, Intent intent) { 
      String action = intent.getAction(); 
      // Whenever a remote Bluetooth device is found 
      if (BluetoothDevice.ACTION_FOUND.equals(action)) { 
       // Get the BluetoothDevice object from the Intent 
       BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 
       Toast.makeText(getApplicationContext(), device.getName() + ":" + device.getAddress(), Toast.LENGTH_LONG).show(); 
//    lvDeviceList.setAdapter(mPairedDevicesAdapter);  // Set list view elements with adapter elements 
      } 
     } 
    }; 

    // Show bluetooth state on UI 
    public void getBluetoothState() { 
     tvDeviceName.setText("Device Name: " + mBluetoothAdapter.getName()); 
     switch(mBluetoothAdapter.getState()) {        // Set bluetooth state text view 
      case 10: // STATE_OFF 
       tvBluetoothState.setText("Bluetooth is closed"); 
       bluetoothDeviceList = new ArrayList();    // Initialize global array list variable that is declared 
       mPairedDevicesAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, bluetoothDeviceList);  // Get array list and use in array adapter 
       lvDeviceList.setAdapter(mPairedDevicesAdapter);  // Set list view elements with adapter elements 
       break; 
      case 11: // STATE_TURNING_ON 
       tvBluetoothState.setText("Bluetooth is opening"); 
       break; 
      case 12: // STATE_ON 
       tvBluetoothState.setText("Bluetooth is opened"); 
       break; 
      case 13: // STATE_TURNING_OFF 
       tvBluetoothState.setText("Bluetooth is closing"); 
       break; 
     } 

     // If bluetooth adapter -> Set buttons 
     if (mBluetoothAdapter.isEnabled()) { 
      // Enable listing button 
      listBtn.setEnabled(true); 
      searchBtn.setEnabled(true); 
     } else { 
      // Disable listing button 
      listBtn.setEnabled(false); 
      searchBtn.setEnabled(false); 
     } 
    } 

    // Get paired device list and adapt to list view 
    public void pairedDevicesList() 
    { 
     if (!mBluetoothAdapter.isEnabled()) { 
      Toast.makeText(getApplicationContext(), "Open the Bluetooth", Toast.LENGTH_SHORT).show(); 
     } else { 
      mPairedDevicesSet = mBluetoothAdapter.getBondedDevices();  // Get paired devices 
      bluetoothDeviceList = new ArrayList();      // Initialize global array list variable that is declared 

      if (mPairedDevicesSet.size()>0) { 
       for (BluetoothDevice bt : mPairedDevicesSet) {    // for-each loop 
        mDeviceName = bt.getName(); 
        mDeviceAddress = bt.getAddress(); 
        bluetoothDeviceList.add(mDeviceName + "\n" + mDeviceAddress);    // get the device name and add to array list object 
       } 
      } else if (mPairedDevicesSet.size()<=0){ 
       Toast.makeText(getApplicationContext(), "No paired devices", Toast.LENGTH_SHORT).show(); 
      } 
      mPairedDevicesAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1, bluetoothDeviceList);  // Get array list and use in array adapter 
      lvDeviceList.setAdapter(mPairedDevicesAdapter);  // Set list view elements with adapter elements 
     } 
    } 

} 

activity_main。 xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:id="@+id/activity_main" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:paddingBottom="@dimen/activity_vertical_margin" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    tools:context="com.sphinxlike.bluetoothexample.MainActivity" 
    android:orientation="vertical"> 

    <TextView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:hint="Device Name" 
     android:id="@+id/deviceName"/> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:orientation="horizontal" 
     android:layout_marginTop="20dp"> 

     <Button 
      android:layout_width="0dp" 
      android:layout_weight="1" 
      android:layout_height="wrap_content" 
      android:id="@+id/openBluetooth" 
      android:text="B. Open" 
      android:textAllCaps="false" 
      android:layout_gravity="center" 
      android:gravity="center"/> 
     <Button 
      android:layout_width="0dp" 
      android:layout_weight="1" 
      android:layout_height="wrap_content" 
      android:id="@+id/closeBluetooth" 
      android:text="B. Close" 
      android:textAllCaps="false" 
      android:layout_gravity="center" 
      android:gravity="center"/> 
     <Button 
      android:layout_width="0dp" 
      android:layout_weight="1" 
      android:layout_height="wrap_content" 
      android:id="@+id/listBluetooth" 
      android:text="List Paired" 
      android:textAllCaps="false" 
      android:layout_gravity="center" 
      android:gravity="center"/> 
     <Button 
      android:layout_width="0dp" 
      android:layout_weight="1" 
      android:layout_height="wrap_content" 
      android:id="@+id/searchBluetooth" 
      android:text="Search" 
      android:textAllCaps="false" 
      android:layout_gravity="center" 
      android:gravity="center"/> 
    </LinearLayout> 

    <TextView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_marginTop="20dp" 
     android:hint="Bluetooth State" 
     android:id="@+id/bluetoothState" 
     android:layout_gravity="center" 
     android:gravity="center"/> 

    <ListView 
     android:layout_width="wrap_content" 
     android:layout_height="match_parent" 
     android:id="@+id/deviceList"> 

    </ListView> 
</LinearLayout> 

回答

0

首先,感謝@Tomasz Czura。我解決了多個運行時權限請求的問題。 Android Developer 6.0 Changes頁說:

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

所以,我添加權限到AndroidManifest.xml中:

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

然後我重新安排這樣我的活動:

public class MainActivity extends AppCompatActivity { 
... 
    int ACTION_REQUEST_MULTIPLE_PERMISSION = 1; // Any number 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     ... 

     int pCheck = this.checkSelfPermission("Manifest.permission.ACCESS_FINE_LOCATION"); 
     pCheck += this.checkSelfPermission("Manifest.permission.ACCESS_COARSE_LOCATION"); 
     pCheck += this.checkSelfPermission("Manifest.permission.BLUETOOTH_ADMIN"); 
     pCheck += this.checkSelfPermission("Manifest.permission.BLUETOOTH"); 
     if (pCheck != 0) { 
      this.requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, 
      Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.BLUETOOTH}, ACTION_REQUEST_MULTIPLE_PERMISSION); 
     } 
    } 
} 

它工作。

0

你必須在運行時的Android 6.0索要Blueottoth權限 - ActivityCompat.requestPermissions(..)

+0

但我可以打開關閉藍牙,獲得藍牙適配器並獲得配對設備。他們不需要運行時權限?發現api是否需要運行時權限? – sphinxlike

+0

嘗試請求位置權限'android.permission.ACCESS_COARSE_LOCATION' –

+0

它沒有工作 – sphinxlike