代码之家  ›  专栏  ›  技术社区  ›  sphinxlike

Android蓝牙发现API在Android 6.0上不工作

  •  1
  • sphinxlike  · 技术社区  · 8 年前

    我制作了一个应用程序,可以发现附近的蓝牙设备等。我可以获得蓝牙适配器,打开和关闭进程,获得配对设备,发现进程。一切都很好,但发现过程没有正常工作。

    我在5台不同的真实设备上测试了我的应用程序。当时我意识到我在Android版本上有问题,但我不确定。

    我的应用程序的发现过程正在进行,

    • 华为P7-安卓版本:4.4.2
    • 索尼Xperia Z-Android版本:5.1.1
    • 三星Galaxy J3-Android版本:5.1.1

    我的应用程序的发现过程不工作,

    • 三星Galaxy S7-Android版本: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>
    
    2 回复  |  直到 8 年前
        1
  •  2
  •   sphinxlike    8 年前

    首先,感谢@Tomasz Czura。我解决了多个运行时权限请求的问题。 Android Developer 6.0 Changes 佩奇说:

    要通过蓝牙和Wi-Fi扫描访问附近外部设备的硬件标识符,您的应用程序现在必须具有access_FINE_LOCATION或access_COARSE_locations权限:

    因此,我向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);
            }
        }
    }
    

    它起作用了。

        2
  •  0
  •   Faysal Ahmed    6 年前

    在Android 6.0中,您必须在运行时请求蓝牙权限-

    ActivityCompat.requestPermissions(..)