【问题标题】:Android's bluetooth BluetoothDevice.ACTION_FOUND is not being triggered?Android的蓝牙BluetoothDevice.ACTION_FOUND没有被触发?
【发布时间】:2019-05-03 02:39:17
【问题描述】:

我正在尝试通过我的应用管理多个蓝牙事件,这样用户就无需离开应用并尝试通过 Android 设置搜索/配对蓝牙设备。

我能够枚举以前配对的设备并开始发现,但是我找不到附近的设备。

背景信息:

设备 = 三星 Galaxy S6

操作系统 = Android 6.0.1,内核 3.4.0-750027

通过 Android 自己的内置发现功能可以看到蓝牙设备

这是我的相关代码:

package experiment.xyz.abc;

import android.app.ListActivity;
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.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 *      
 * This activity is responsible for bluetooth device discovery, pairing, and selection.
 * 1) user can search for nearby devices
 * 2) pair with device
 * 3) unpair a device
 * 4) select a bt device( upon successful selection the activity navigates away).
 */
public class BluetDeviceListActivity extends ListActivity
{
 public static String BLUETOOTH_DEVICE_ADDRESS= "BLUETOOTH_DEVICE_ADDRESS";

    List<BluetoothDevice> bluetList;
    BluetoothDeviceListAdapter newBluetoothDeviceListAdapter = null;
    private  Set<BluetoothDevice> pairedDevices;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.bluet_list_view);

        //instantiate adapter
        newBluetoothDeviceListAdapter = new BluetoothDeviceListAdapter(this);


        //populate bluet list
        populatePairedBluetoothDevices();

        //set the ListActivity's adapter with our custom adapter
        setListAdapter(newBluetoothDeviceListAdapter);
        //on item click get the associated item based index & use Intent to send BluetoothDevice
        getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                BluetoothDevice bluetoothDevice= newBluetoothDeviceListAdapter.getListOfBluetoothDevices().get(position);

                if (bluetoothDevice!=null) {
                    Intent returnIntent = new Intent();
                    returnIntent.putExtra(BLUETOOTH_DEVICE_ADDRESS, bluetoothDevice.getAddress());
                    setResult(RESULT_OK, returnIntent);
                }

                finish();

                if (mReceiver!=null)
                {

                    try {
                        unregisterReceiver(mReceiver);
                    }
                    catch (IllegalArgumentException exc)
                    {
                        exc.printStackTrace();
                    }
                }
            }
        });

        //cancel activity dialog
        Button cancelButton = (Button) findViewById(R.id.cancelBluetoothDialogButton);
        cancelButton.setOnClickListener( new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                finish();

                if (mReceiver!=null)
                {

                    try {
                        unregisterReceiver(mReceiver);
                    }
                    catch (IllegalArgumentException exc)
                    {
                        exc.printStackTrace();
                    }
                }
            }
        });

        //search for bluetooth devices
        Button searchAndPairButton = (Button) findViewById(R.id.searchPairButton);
        searchAndPairButton.setOnClickListener( new View.OnClickListener() {

            @Override
            public void onClick(View v) {


                //update textview
                populateDiscoveredBluetoothDevices();
            }
        });


        //pair or unpair selected device
        Button pairOrUnpairButton = (Button) findViewById(R.id.pairUnpairDialogButton);
        pairOrUnpairButton.setOnClickListener( new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                //TODO:

            }
        });



    }//end onCreate


    //discover nearby devices & add to list
    private void populateDiscoveredBluetoothDevices()
   {
       StreamApiUtility.getBluetoothAdapter();


       //is bluet enabled
       BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
       if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {

           //if already discovering cancel
           if(mBluetoothAdapter.isDiscovering()){
               mBluetoothAdapter.cancelDiscovery();
           }

           //start a new discovery
           mBluetoothAdapter.startDiscovery();


           }//end there are paired devices
           else
           {
               Log.i("EEGdataCapture", "No paired devices, select Search & Pair.");
               TextView textView  =(TextView) findViewById(R.id.textViewBluetoothListInstruction);
               textView.setText("No paired devices, select Search & Pair.");

           }

       }


    //query already paired & add to list
    private void populatePairedBluetoothDevices()
    {
        StreamApiUtility.getBluetoothAdapter();

        //is bluet enabled
        BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {

            //if already discovering cancel
            if(mBluetoothAdapter.isDiscovering()){
                mBluetoothAdapter.cancelDiscovery();
            }

            //start a new discovery
            mBluetoothAdapter.startDiscovery();

            //iterate paired/bonded devices and if there are any add them to the custom adapter
            pairedDevices = mBluetoothAdapter.getBondedDevices();
            if (pairedDevices.size() > 0) {
                BluetoothDevice bluetoothDevice;
                Iterator<BluetoothDevice> it = pairedDevices.iterator();
                while (it.hasNext()) {
                    bluetoothDevice = (BluetoothDevice) it.next();
                    //add to adapter
                    newBluetoothDeviceListAdapter.addDevice(bluetoothDevice);
                    newBluetoothDeviceListAdapter.notifyDataSetChanged();
                    Log.i("EEGdataCapture", "paired device, name: " + bluetoothDevice.getName() + ", address: " + bluetoothDevice.getAddress());
                }


            }//end there are paired devices
            else
            {
                Log.i("EEGdataCapture", "No paired devices, select Search & Pair.");
                TextView textView  =(TextView) findViewById(R.id.textViewBluetoothListInstruction);
                textView.setText("No paired devices, select Search & Pair.");

            }

        }
    }



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

            if (BluetoothDevice.ACTION_FOUND.equals(action)) {

                device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);


                Log.i("EEGdataCapture", "BluetoothDevice.ACTION_FOUND");

                Log.i("EEGdataCapture", device.getName() + "\n" + device.getAddress());

                //update list

                newBluetoothDeviceListAdapter.addDevice(device);
                newBluetoothDeviceListAdapter.notifyDataSetChanged();


            }
            else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {

                Log.i("EEGdataCapture", "BluetoothDevice.ACTION_BOND_STATE_CHANGED");

                final int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
                final int prevState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, BluetoothDevice.ERROR);

                if (state == BluetoothDevice.BOND_BONDED && prevState == BluetoothDevice.BOND_BONDING) {

                    Toast.makeText(MyApp.getAppContext(), "Paired", Toast.LENGTH_SHORT).show();
                } else if (state == BluetoothDevice.BOND_NONE && prevState == BluetoothDevice.BOND_BONDED) {
                    Toast.makeText(MyApp.getAppContext(), "Unpaired", Toast.LENGTH_SHORT).show();
                }


            }
            else if (BluetoothDevice.ACTION_UUID.equals(action)) {

                Log.i("EEGdataCapture", "BluetoothDevice.ACTION_UUID");



            }

            else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {

                Log.i("EEGdataCapture", "BluetoothAdapter.ACTION_DISCOVERY_STARTED, Discovery Started...");


            }

            else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                Log.i("EEGdataCapture", "BluetoothAdapter.ACTION_DISCOVERY_FINISHED, Discovery finished.");


        }
            else
            {
                Log.i("EEGdataCapture", "BluetoothAdapter, ACTIOM is not supported, action ="+action);
            }


        }};



    private void pairDevice(BluetoothDevice device) {
        try {
            Method method = device.getClass().getMethod("createBond", (Class[]) null);
            method.invoke(device, (Object[]) null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void unpairDevice(BluetoothDevice device) {
        try {
            Method method = device.getClass().getMethod("removeBond", (Class[]) null);
            method.invoke(device, (Object[]) null);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    @Override
    protected void onPause() {
        super.onPause();

        if ( StreamApiUtility.getBluetoothAdapter()!=null) {
            StreamApiUtility.getBluetoothAdapter().cancelDiscovery();
        }
        if (mReceiver!=null)
        {

            try {
                unregisterReceiver(mReceiver);
            }
            catch (IllegalArgumentException exc)
            {
                exc.printStackTrace();
            }
        }
    }

    @Override
    protected void onResume()
     {
         super.onResume();
         //filter to capture bluet events
         IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
         filter.addAction(BluetoothDevice.ACTION_UUID);
         filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
         filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);

         //register listener for bluet events before starting discovery again
         registerReceiver(mReceiver, filter);

     }


    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (mReceiver!=null)
        {

            try {
                unregisterReceiver(mReceiver);
            }
            catch (IllegalArgumentException exc)
            {
                exc.printStackTrace();
            }
        }
    }
}

更新清单:

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

尽管正在调用 ACTION_DISCOVERY_STARTED 或 ACTION_DISCOVERY_FINISHED,但未触发/调用 BroadcastReciever 的 BluetoothDevice.ACTION_FOUND。

请帮忙???

谢谢

【问题讨论】:

  • 您有机会在 Android 6.0 以下测试您的应用吗?

标签: android bluetooth


【解决方案1】:

您的代码似乎没问题。我猜你有BLUETOOTH 权限(否则你不会收到ACTION_DISCOVERY_STARTED)但是你也有ACCESS_COARSE_LOCATION 权限吗?

You need it to receive ACTION_FOUND

ACTION_FOUND
广播操作:发现远程设备。
需要BLUETOOTHACCESS_COARSE_LOCATION 才能接收。

【讨论】:

  • 我通过在清单中添加 ACCESS_COARSE_LOCATION 尝试了这种方法,但是,仍然没有发现设备???我在原始帖子中添加了我的权限。
  • 从Android 6(API 23)开始,还需要询问用户,ACCESS_COARSE_LOCATION是一个危险的权限。另一方面,BLUETOOTH 是普通权限,是自动授予的。
  • 如果将目标级别设置为 22 会发生什么?
【解决方案2】:

您需要执行实时权限检查,以确保在发现任何设备之前启用粗略定位。 为此,您应该在 build.gradle 文件中定位/最低 SDK 23+。

if (mActivityContext.checkSelfPermission("android.permission.ACCESS_COARSE_LOCATION") == PackageManager.PERMISSION_GRANTED) {
        final BluetoothManager bluetoothManager =
                (BluetoothManager) mActivityContext.getSystemService(Context.BLUETOOTH_SERVICE);
        if (bluetoothManager != null) mBleAdapter = bluetoothManager.getAdapter();

在此处注册 Intent 过滤器

        mBleAdapter.startDiscovery();
    } else {
        mInterface.requestPermission(Manifest.permission.ACCESS_COARSE_LOCATION, mCoarsePermissionTag);
    }

mInterface 是我返回 MainActivity 的接口

【讨论】:

    猜你喜欢
    • 2015-08-18
    • 2018-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-17
    • 1970-01-01
    • 2011-07-14
    相关资源
    最近更新 更多