android 4.4 蓝牙开发总结(电视盒子)

提取Android盒子(CM201-1 YS)dtb文件 最近从某鱼上掏了一个CM201-1 YS的盒子,动手倒腾倒腾,准备安装Armbian,用来做矿机,但该型号的盒子ophub上面没有完全适配的镜像,故而想尝试下,看能否整个适配镜像出来。 阅读详情

6.0的蓝牙已经开发完毕,因为可以得到系统6.0的jar包,so也就开发的快些,更好些。4.4因为代码部分在setting模块里,部分在系统中,so不方便打成jar包。所以就通过广播接受改变状态之类的。也算鼓捣出来一款。

4.4蓝牙效果

开发的思路:

1.开关蓝牙

2.扫描到蓝牙列表和得到配对列表

 

 

下面关于连接蓝牙:

A2dp:这个是蓝牙音频传输协议

AVRCP:输入设备控制协议

首先要弄清当前蓝牙的功能属于那种协议,具体代码判断协议的方法不清楚。(本项目用不到)

3.连接蓝牙

 

4.断开蓝牙与取消配对

 

1.开关蓝牙

   /**
     * 打开蓝牙or关闭蓝牙
     * @param flag true:open
     */
    public void openOrCloseBluetooth(boolean flag) {
        if (flag) {
            mBluetoothAdapter.enable();
        } else {
            mBluetoothAdapter.disable();
        }
    }

2.扫描到蓝牙列表和得到配对列表

扫描蓝牙

//开始扫描
    public void startScan() {
        if (mBluetoothAdapter != null) {
            // scanResultList.clear();
            if (mBluetoothAdapter.isDiscovering()) {
                Log.d(TAG, "startScan: cancelDiscovery");
                mBluetoothAdapter.cancelDiscovery();
            }
            mBluetoothAdapter.startDiscovery();
            Log.d(TAG, "startScan: 开始扫描周围蓝牙");
        } else {
            Log.d(TAG, "startScan: 扫描周围蓝牙异常");
        }
    }

扫描之后如何获取扫描结果主要通过广播获取

  private void registerBluetoothBroadcastReceiver(Context context) {
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//蓝牙状态改变的广播
        filter.addAction(BluetoothDevice.ACTION_FOUND);//找到设备的广播
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索完成的广播
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//开始扫描的广播
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//状态改变
        filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
        if (mReceiver == null) {
            mReceiver = new BluetoothBroadCasteReceiver();
        }
        Log.d(TAG, "registerBluetoothBroadcastReceiver: 注册蓝牙广播" + mBluetoothAdapter.isEnabled());
        context.registerReceiver(mReceiver, filter);
    }

接受器中主要处理这三个状态

                case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
                    Log.d(TAG, "onReceive: 开始扫描。");
                    break;
                case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
                    Log.d(TAG, "onReceive: 扫描结束。");
                    if (callBack != null) {
                        //callBack.scan_result(scanResultList,            getHasConnectBlueDevices());
                        callBack.scanEnd();
                    }
                    break;
                case BluetoothDevice.ACTION_CLASS_CHANGED:
                    Log.d(TAG, "onReceive: 一个已经改变的远程设备的蓝牙类。");
                    break;
                case BluetoothDevice.ACTION_FOUND:
                    device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    BluetoothDeviceBean bluetoothDeviceBean = new BluetoothDeviceBean(device, Bluetooth_State.State_BOND_NONE);
                    if (device != null) {
                        //发现的设备统一给一个未配对的状态
                        if (callBack != null) {
                            callBack.foundDevice(bluetoothDeviceBean, getHasConnectBlueDevices());
                        }
                        Log.d(TAG, "onReceive: 远程设备发现。" + device.getName() + "??" + device.getAddress() + "???" + device.getBondState());
                    }
                    break;

tips:

1.扫描蓝牙的时候,扫描结束的广播等待时间较长,为了页面体验就在发现设备的广播中,做数据的收集,但注意的是同一个设备会多次被发现,所以数据要做一些扁平化处理

2.扫描的结果也包含了已经配对的,so数据应该做一些处理

获得已经配对的列表

 /**
     * 获得已经配对的蓝牙列表
     * @return
     */
    public Set<BluetoothDeviceBean> getHasConnectBlueDevices() {
        Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices();
        Set<BluetoothDeviceBean> bluetoothDeviceBeans = new LinkedHashSet<>();
        if (bondedDevices != null) {
            for (BluetoothDevice de :
                    bondedDevices) {
                bluetoothDeviceBeans.add(new BluetoothDeviceBean(de, Bluetooth_State.State_BOND_BONDED));
            }
            Log.e(TAG, "getHasConnectBlueDevices: 已经配对的蓝牙设备" + bluetoothDeviceBeans.toString());
            return bluetoothDeviceBeans;
        } else {
            Log.e(TAG, "没有已经配对的蓝牙设备");
            return bluetoothDeviceBeans;
        }
    }

tips:已经配对的列表中及时当前的设备没有连接也会显示。

3.连接蓝牙

连接蓝牙主要分为两部分,一部分是配对,配对完成后再连接

配对:

 /**
     * 蓝牙配对
     * @param btClass
     * @param btDevice
     */
    public void createBond(Class btClass, BluetoothDevice btDevice) {
        Method createBondMethod = null;
        try {
            createBondMethod = btClass.getMethod("createBond");
            Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            Log.d(TAG, "createBond: XXXX");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            Log.d(TAG, "createBond: XXXX1");
        } catch (InvocationTargetException e) {
            Log.d(TAG, "createBond: XXXX2");
            e.printStackTrace();
        }
    }

在广播中得到配对的状态:

               case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
                    int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
                    switch (state) {
                        case BluetoothDevice.BOND_NONE:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "BOND_NONE 删除配对" + device.getName());
                            if (callBack != null) {
                                callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.State_BOND_NONE));
                            }
                            break;
                        case BluetoothDevice.BOND_BONDING:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "BOND_BONDING 正在配对" + device.getName());
                            if (callBack != null) {
                                callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.State_BOND_BONDING));
                            }
                            break;
                        case BluetoothDevice.BOND_BONDED:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "BOND_BONDED 配对成功" + device.getName());
                            if (callBack != null) {
                                callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.State_BOND_BONDED));
                            }
                            //连接操作
                            conectBluetoothDevice(device);
                            break;
                    }
                    break;

收到配对成功的广播进行连接:

A2dp连接:

 //连接蓝牙
    public void conectBluetoothDevice(BluetoothDevice device) {
        if (mA2dpService != null) {
            try {
                Log.d(TAG, "createBond: 配对成功开始连接");
                mA2dpService.connect(device);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

输入控制设备的连接:

 /**
     * 
     * @param device
     * @param isConnect true:连接 false:断开
     */
    private void connectOrDisConnectHidBT(BluetoothDevice device, boolean isConnect) {
        if (mHidService != null) {
            //连接
            try {
                String flag = "";
                if (isConnect) {
                    flag = "connect";
                } else {
                    flag = "disconnect";
                }
                if (mHidService.getProfile() == getInputDeviceHiddenConstant()) {
                    if (device != null) {
                        //得到BluetoothInputDevice然后反射connect连接设备
                        Method method = mHidService.getProxy().getClass().getMethod(flag,
                                new Class[]{BluetoothDevice.class});
                        method.invoke(mHidService.getProxy(), device);
                    }
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                // e.printStackTrace();
            }
        }
    }
 /**
     * 获取BluetoothProfile中hid的profile,"INPUT_DEVICE"类型隐藏,需反射获取
     * @return
     */
    @SuppressLint("NewApi")
    public static int getInputDeviceHiddenConstant() {
        Class<BluetoothProfile> clazz = BluetoothProfile.class;
        for (Field f : clazz.getFields()) {
            int mod = f.getModifiers();
            if (Modifier.isStatic(mod) && Modifier.isPublic(mod)
                    && Modifier.isFinal(mod)) {
                try {
                    if (f.getName().equals("INPUT_DEVICE")) {
                        return f.getInt(null);
                    }
                } catch (Exception e) {
                }
            }
        }
        return -1;
    }

tips:连接蓝牙的时候,需要开启一个服务,通过广播接受来判定是否连接成功

A2dp的服务:

    private void initA2dpService() {
        Intent i = new Intent(IBluetoothA2dp.class.getName());
        context.bindService(i, mConnection, Context.BIND_AUTO_CREATE);
    }

    IBluetoothA2dp mA2dpService;
    public ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            try {
                mA2dpService = IBluetoothA2dp.Stub.asInterface(service);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub

        }

    };
               case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
                    switch (intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, -1)) {
                        case BluetoothA2dp.STATE_CONNECTING:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "BluetoothA2dp.STATE_CONNECTING: " + device.getName() + " connecting");
                            if (callBack != null) {
                                callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.STATE_CONNECTING));
                            }
                            break;
                        case BluetoothA2dp.STATE_CONNECTED:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            if (device != null) {
                                if (callBack != null) {
                                    callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.STATE_CONNECTED));
                                }
                                Log.d(TAG, "BluetoothA2dp.STATE_CONNECTED: " + device.getName() + " 连接成功");
                            }
                            break;
                        case BluetoothA2dp.STATE_DISCONNECTING:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "BluetoothA2dp.STATE_DISCONNECTING: " + device.getName() + " connecting");
                            break;
                        case BluetoothA2dp.STATE_DISCONNECTED:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            if (callBack != null) {
                                callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.STATE_DISCONNECTED));
                            }
                            Log.d(TAG, "BluetoothA2dp.STATE_DISCONNECTED: " + device.getName() + " disconnected");
                            break;
                    }
                    break;

输入控制设备:

 //判断连接hid设备的服务是否连上
    private BTHidServiceBean mHidService = null;
    /**
     * 查看BluetoothInputDevice源码,connect(BluetoothDevice device)该方法可以连接HID设备,但是查看BluetoothInputDevice这个类
     * 是隐藏类,无法直接使用,必须先通过BluetoothProfile.ServiceListener回调得到BluetoothInputDevice,然后再反射connect方法连接
     */
    private BluetoothProfile.ServiceListener connect = new BluetoothProfile.ServiceListener() {
        @Override
        public void onServiceConnected(int profile, BluetoothProfile proxy) {
            //BluetoothProfile proxy这个已经是BluetoothInputDevice类型了
            mHidService = new BTHidServiceBean(profile, proxy);
        }

        @Override
        public void onServiceDisconnected(int profile) {

        }
    };
 /**
     * 注册输入设备的服务
     */
    private void initHidService() {
        mBluetoothAdapter.getProfileProxy(context, connect, getInputDeviceHiddenConstant());
    }

监听连接的广播:

 private void registerBluetoothBroadcastReceiver(Context context) {
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//蓝牙状态改变的广播
        filter.addAction(BluetoothDevice.ACTION_FOUND);//找到设备的广播
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索完成的广播
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//开始扫描的广播
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//状态改变
        filter.addAction("android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED");
        if (mReceiver == null) {
            mReceiver = new BluetoothBroadCasteReceiver();
        }
        Log.d(TAG, "registerBluetoothBroadcastReceiver: 注册蓝牙广播" + mBluetoothAdapter.isEnabled());
        context.registerReceiver(mReceiver, filter);
    }
 case "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED":
                    switch (intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0)) {
                        case BluetoothProfile.STATE_CONNECTING:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "BluetoothProfile.STATE_CONNECTING: " + device.getName() + " connecting");
                            if (callBack != null) {
                                callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.STATE_CONNECTING));
                            }
                            break;
                        case BluetoothProfile.STATE_CONNECTED:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            if (device != null) {
                                if (callBack != null) {
                                    callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.STATE_CONNECTED));
                                }
                                Log.d(TAG, "BluetoothProfile.STATE_CONNECTED: " + device.getName() + " connecting");
                            }
                            break;
                        case BluetoothProfile.STATE_DISCONNECTING:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "BluetoothProfile.STATE_DISCONNECTING: " + device.getName() + " connecting");
                            break;
                        case BluetoothProfile.STATE_DISCONNECTED:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            if (callBack != null) {
                                callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.STATE_DISCONNECTED));
                            }
                            Log.d(TAG, "BluetoothProfile.STATE_DISCONNECTED: " + device.getName() + " disconnected");
                            break;
                    }
                    break;

 

附上如何判定蓝牙是否连接成功:

A2dp:

 /**
     * 判断蓝牙是否已经
     * @param device
     * @return
     */
    public boolean isHasConnected(BluetoothDevice device) {
        try {
            if (mA2dpService.getConnectionState(device) == BluetoothA2dp.STATE_CONNECTED) {
                Log.e(TAG, "isHasConnected: XXX1::" + device.getName() + "???" + mA2dpService.getConnectionState(device));
                return true;
            } else {
                Log.e(TAG, "isHasConnected: XXX2::" + device.getName() + "???" + mA2dpService.getConnectionState(device));
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return false;
    }

输入设备:

//判断蓝牙是否已经
    public boolean isHasConnected(BluetoothDevice device) {
        if (mHidService != null) {
            BluetoothProfile proxy = mHidService.getProxy();
            int connectionState = proxy.getConnectionState(device);
            if (connectionState == BluetoothProfile.STATE_CONNECTED) {
                return true;
            }
        }
        return false;
    }

4.断开蓝牙与取消配对

断开蓝牙不等于取消配对

A2dp

   /**
     * 断开蓝牙连接
     * @param device
     */
    public void disConectBluetoothDevice(BluetoothDevice device) {
        if (isHasConnected(device) && mA2dpService != null) {
            try {
                mA2dpService.disconnect(device);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

取消配对一定包含断开蓝牙

 /**
     * 清除配对历史
     * @param device
     */
    public void unpairDevice(BluetoothDevice device) {
        try {
            Method m = device.getClass()
                    .getMethod("removeBond", (Class[]) null);
            m.invoke(device, (Object[]) null);
        } catch (Exception e) {
            Log.d(TAG, "清除配对异常" + e.getMessage());
        }
    }

 

 /**
     * @param currentDevice
     * @param isUnpairDevice 是否取消配对
     */
    public void disconnect(BluetoothDevice currentDevice, boolean isUnpairDevice) {
        Set<BluetoothDeviceBean> hasConnectBlueDevices = helper.getHasConnectBlueDevices();

        if (hasConnectBlueDevices != null) {
            for (BluetoothDeviceBean di :
                    hasConnectBlueDevices) {
                if (di.getDevice().getAddress().equals(currentDevice.getAddress())) {
                    helper.disConectBluetoothDevice(di.getDevice());
                    if (isUnpairDevice) {
                        helper.unpairDevice(di.getDevice());
                    }
                    break;
                }
            }
        }
    }

输入设备:

配对方法是固定的,断开连接上面已经总结

附件1:4.4蓝牙A2dp工具类:

package com.ygjy.setting4_0.bluetooth.uitls;

import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.IBluetoothA2dp;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

import com.ygjy.setting4_0.bluetooth.bean.BluetoothDeviceBean;
import com.ygjy.setting4_0.bluetooth.bean.Bluetooth_State;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * @创建人:hcy
 * @创建时间:2018/11/9
 * @作用描述:Function
 **/
public class BlueToothHelper {
    private static final String TAG = "BlueToothHelper>>>";
    private BluetoothManager mBluetoothManager;
    private BluetoothAdapter mBluetoothAdapter;
    //private Set<BluetoothDeviceBean> scanResultList;
    private Context context;

    public BlueToothHelper(Context context) {
        //获得蓝牙管理对象
        this.context = context;

        mBluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
        //获得蓝牙适配器
        mBluetoothAdapter = mBluetoothManager.getAdapter();
        //scanResultList = new LinkedHashSet<>();
        if (hasBluetooth()) {
            initA2dpService();
            registerBluetoothBroadcastReceiver(context);
        } else {
            Toast.makeText(context, "当前设备不支持蓝牙", Toast.LENGTH_SHORT).show();
        }
    }


    /**
     * 设备是否支持蓝牙
     *
     * @return true:支持 false:不支持
     */
    public boolean hasBluetooth() {
        if (mBluetoothAdapter != null) {
            Log.d(TAG, "该设备支持蓝牙:本机的蓝牙名称" + mBluetoothAdapter.getName());
            return true;
        } else {
            Log.d(TAG, "该设备不支持蓝牙");
        }
        return false;
    }


    private BroadcastReceiver mReceiver;

    /**
     * 注册广播可以获取扫描结果和配对的状态
     * @param context
     */
    private void registerBluetoothBroadcastReceiver(Context context) {
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//蓝牙状态改变的广播
        filter.addAction(BluetoothDevice.ACTION_FOUND);//找到设备的广播
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索完成的广播
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//开始扫描的广播
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//状态改变
        filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
        if (mReceiver == null) {
            mReceiver = new BluetoothBroadCasteReceiver();
        }
        Log.d(TAG, "registerBluetoothBroadcastReceiver: 注册蓝牙广播" + mBluetoothAdapter.isEnabled());
        context.registerReceiver(mReceiver, filter);
    }

    public void unregisterBluetoothBroadCastReceiver(Context context) {

        if (mBluetoothAdapter != null) {
            mBluetoothAdapter.cancelDiscovery();
        }
        if (mA2dpService != null) {
            context.unbindService(mConnection);
        }
        if (mReceiver != null) {
            context.unregisterReceiver(mReceiver);
        }
    }


    //开始扫描
    public void startScan() {
        if (mBluetoothAdapter != null) {
            // scanResultList.clear();
            if (mBluetoothAdapter.isDiscovering()) {
                Log.d(TAG, "startScan: cancelDiscovery");
                mBluetoothAdapter.cancelDiscovery();
            }
            mBluetoothAdapter.startDiscovery();
            Log.d(TAG, "startScan: 开始扫描周围蓝牙");
        } else {
            Log.d(TAG, "startScan: 扫描周围蓝牙异常");
        }
    }

    //判断蓝牙是否已经开启
    public boolean isEnabled() {
        boolean bluetooth_state = mBluetoothAdapter.isEnabled();
        Log.d(TAG, "isEnabled: 蓝牙当前是否开启::" + bluetooth_state);
        return bluetooth_state;
    }

    /**
     * 打开蓝牙or关闭蓝牙
     * @param flag true:open
     */
    public void openOrCloseBluetooth(boolean flag) {
        if (flag) {
            mBluetoothAdapter.enable();
        } else {
            mBluetoothAdapter.disable();
        }
    }


    //蓝牙的广播
    public class BluetoothBroadCasteReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            BluetoothDevice device = null;
            switch (action) {
                case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
                    Log.d(TAG, "onReceive: 开始扫描。");
                    break;
                case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
                    Log.d(TAG, "onReceive: 扫描结束。");
                    if (callBack != null) {
                        //callBack.scan_result(scanResultList, getHasConnectBlueDevices());
                        callBack.scanEnd();
                    }
                    break;
                case BluetoothDevice.ACTION_CLASS_CHANGED:
                    Log.d(TAG, "onReceive: 一个已经改变的远程设备的蓝牙类。");
                    break;
                case BluetoothDevice.ACTION_FOUND:
                    device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    BluetoothDeviceBean bluetoothDeviceBean = new BluetoothDeviceBean(device, Bluetooth_State.State_BOND_NONE);
                    if (device != null) {
                        //发现的设备统一给一个未配对的状态
                        if (callBack != null) {
                            callBack.foundDevice(bluetoothDeviceBean, getHasConnectBlueDevices());
                        }
                        Log.d(TAG, "onReceive: 远程设备发现。" + device.getName() + "??" + device.getAddress() + "???" + device.getBondState());
                    }
                    break;
                case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
                    int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
                    switch (state) {
                        case BluetoothDevice.BOND_NONE:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "BOND_NONE 删除配对" + device.getName());
                            if (callBack != null) {
                                callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.State_BOND_NONE));
                            }
                            break;
                        case BluetoothDevice.BOND_BONDING:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "BOND_BONDING 正在配对" + device.getName());
                            if (callBack != null) {
                                callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.State_BOND_BONDING));
                            }
                            break;
                        case BluetoothDevice.BOND_BONDED:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "BOND_BONDED 配对成功" + device.getName());
                            if (callBack != null) {
                                callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.State_BOND_BONDED));
                            }
                            //连接操作
                            conectBluetoothDevice(device);
                            break;
                    }
                    break;

                case BluetoothAdapter.ACTION_STATE_CHANGED:
                    int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
                    switch (blueState) {
                        case BluetoothAdapter.STATE_TURNING_ON:
                            break;
                        case BluetoothAdapter.STATE_ON:
                            Log.d(TAG, "onReceives: 蓝牙已经打开");
                            if (callBack != null) {
                                callBack.bluetooth_openOrClose(true);
                            }


                            break;
                        case BluetoothAdapter.STATE_TURNING_OFF:
                            break;
                        case BluetoothAdapter.STATE_OFF:
                            Log.d(TAG, "onReceives: 蓝牙已经关闭");
                            if (callBack != null) {
                                callBack.bluetooth_openOrClose(false);
                            }
                            break;
                    }
                    break;
                case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
                    switch (intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, -1)) {
                        case BluetoothA2dp.STATE_CONNECTING:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "BluetoothA2dp.STATE_CONNECTING: " + device.getName() + " connecting");
                            if (callBack != null) {
                                callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.STATE_CONNECTING));
                            }
                            break;
                        case BluetoothA2dp.STATE_CONNECTED:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            if (device != null) {
                                if (callBack != null) {
                                    callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.STATE_CONNECTED));
                                }
                                Log.d(TAG, "BluetoothA2dp.STATE_CONNECTED: " + device.getName() + " 连接成功");
                            }
                            break;
                        case BluetoothA2dp.STATE_DISCONNECTING:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "BluetoothA2dp.STATE_DISCONNECTING: " + device.getName() + " connecting");
                            break;
                        case BluetoothA2dp.STATE_DISCONNECTED:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            if (callBack != null) {
                                callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.STATE_DISCONNECTED));
                            }
                            Log.d(TAG, "BluetoothA2dp.STATE_DISCONNECTED: " + device.getName() + " disconnected");
                            break;
                    }
                    break;
            }
        }
    }

    //连接蓝牙
    public void conectBluetoothDevice(BluetoothDevice device) {
        if (mA2dpService != null) {
            try {
                Log.d(TAG, "createBond: 配对成功开始连接");
                mA2dpService.connect(device);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 断开蓝牙连接
     * @param device
     */
    public void disConectBluetoothDevice(BluetoothDevice device) {
        if (isHasConnected(device) && mA2dpService != null) {
            try {
                mA2dpService.disconnect(device);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }


    public interface BuletoothCallBack {
        void foundDevice(BluetoothDeviceBean deviceBean, Set<BluetoothDeviceBean> hasBoundSet);

        void scan_result(Set<BluetoothDeviceBean> list, Set<BluetoothDeviceBean> hasBoundSet);

        void scanEnd();

        void bluetooth_openOrClose(boolean b);

        void update_state(BluetoothDeviceBean deviceBean);
    }


    private BuletoothCallBack callBack;

    public void setCallBack(BuletoothCallBack callBack) {
        this.callBack = callBack;
    }


    public boolean isConnectedAddress(BluetoothDevice _b) {
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        Class<BluetoothAdapter> bluetoothAdapterClass = BluetoothAdapter.class;//得到BluetoothAdapter的Class对象
        try {//得到蓝牙状态的方法
            Method method = bluetoothAdapterClass.getDeclaredMethod("getConnectionState", (Class[]) null);
            //打开权限
            method.setAccessible(true);
            int state = (int) method.invoke(bluetoothAdapter, (Object[]) null);
            if (state == BluetoothAdapter.STATE_CONNECTED) {
                Log.i(TAG, "BluetoothAdapter.STATE_CONNECTED");
                Set<BluetoothDevice> devices = bluetoothAdapter.getBondedDevices();
                Log.i(TAG, "devices:" + devices.size());
                for (BluetoothDevice device : devices) {
                    Method isConnectedMethod = BluetoothDevice.class.getDeclaredMethod("isConnected", (Class[]) null);
                    method.setAccessible(true);
                    boolean isConnected = (boolean) isConnectedMethod.invoke(device, (Object[]) null);
                    if (isConnected) {
                        Log.i(TAG, "connected:" + device.getAddress());
                        if (getAddress(_b).equals(device.getAddress())) {
                            return true;
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public String getAddress(BluetoothDevice device) {
        return device.getAddress();
    }


    /**
     * 获得已经配对的蓝牙列表
     * @return
     */
    public Set<BluetoothDeviceBean> getHasConnectBlueDevices() {
        Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices();
        Set<BluetoothDeviceBean> bluetoothDeviceBeans = new LinkedHashSet<>();
        if (bondedDevices != null) {
            for (BluetoothDevice de :
                    bondedDevices) {
                bluetoothDeviceBeans.add(new BluetoothDeviceBean(de, Bluetooth_State.State_BOND_BONDED));
            }
            Log.e(TAG, "getHasConnectBlueDevices: 已经配对的蓝牙设备" + bluetoothDeviceBeans.toString());
            return bluetoothDeviceBeans;
        } else {
            Log.e(TAG, "没有已经配对的蓝牙设备");
            return bluetoothDeviceBeans;
        }
    }

    /**
     * 清除配对历史
     * @param device
     */
    public void unpairDevice(BluetoothDevice device) {
        try {
            Method m = device.getClass()
                    .getMethod("removeBond", (Class[]) null);
            m.invoke(device, (Object[]) null);
        } catch (Exception e) {
            Log.d(TAG, "清除配对异常" + e.getMessage());
        }
    }

    /**
     * 蓝牙配对
     * @param btClass
     * @param btDevice
     */
    public void createBond(Class btClass, BluetoothDevice btDevice) {
        Method createBondMethod = null;
        try {
            createBondMethod = btClass.getMethod("createBond");
            Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            Log.d(TAG, "createBond: XXXX");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            Log.d(TAG, "createBond: XXXX1");
        } catch (InvocationTargetException e) {
            Log.d(TAG, "createBond: XXXX2");
            e.printStackTrace();
        }
    }


    private void initA2dpService() {
        Intent i = new Intent(IBluetoothA2dp.class.getName());
        context.bindService(i, mConnection, Context.BIND_AUTO_CREATE);
    }

    IBluetoothA2dp mA2dpService;
    public ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            try {
                mA2dpService = IBluetoothA2dp.Stub.asInterface(service);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub

        }

    };

    public Intent getExplicitIntent(Context context, Intent implicitIntent) {
        // Retrieve all services that can match the given intent
        PackageManager pm = context.getPackageManager();
        List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
        // Make sure only one match was found
        if (resolveInfo == null || resolveInfo.size() != 1) {
            return null;
        }
        // Get component info and create ComponentName
        ResolveInfo serviceInfo = resolveInfo.get(0);
        String packageName = serviceInfo.serviceInfo.packageName;
        String className = serviceInfo.serviceInfo.name;
        ComponentName component = new ComponentName(packageName, className);
        // Create a new intent. Use the old one for extras and such reuse
        Intent explicitIntent = new Intent(implicitIntent);
        // Set the component to be explicit
        explicitIntent.setComponent(component);
        return explicitIntent;
    }


    /**
     * 判断蓝牙是否已经
     * @param device
     * @return
     */
    public boolean isHasConnected(BluetoothDevice device) {
        try {
            if (mA2dpService.getConnectionState(device) == BluetoothA2dp.STATE_CONNECTED) {
                Log.e(TAG, "isHasConnected: XXX1::" + device.getName() + "???" + mA2dpService.getConnectionState(device));
                return true;
            } else {
                Log.e(TAG, "isHasConnected: XXX2::" + device.getName() + "???" + mA2dpService.getConnectionState(device));
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return false;
    }
}

附件2:蓝牙输入控制设备的工具类:

package com.ygjy.setting4_0.bluetooth.uitls;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
import android.widget.Toast;

import com.ygjy.setting4_0.bluetooth.bean.BTHidServiceBean;
import com.ygjy.setting4_0.bluetooth.bean.BluetoothDeviceBean;
import com.ygjy.setting4_0.bluetooth.bean.Bluetooth_State;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * @创建人:hcy
 * @创建时间:2018/11/9
 * @作用描述:Function
 **/
public class BlueToothHelper {
    private static final String TAG = "BlueToothHelper>>>";
    private BluetoothManager mBluetoothManager;
    private BluetoothAdapter mBluetoothAdapter;
    //private Set<BluetoothDeviceBean> scanResultList;
    private Context context;
    BluetoothDevice device = null;

    public BlueToothHelper(Context context) {
        //获得蓝牙管理对象
        this.context = context;
        mBluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
        //获得蓝牙适配器
        mBluetoothAdapter = mBluetoothManager.getAdapter();
        //scanResultList = new LinkedHashSet<>();
        if (hasBluetooth()) {
            initHidService();
            registerBluetoothBroadcastReceiver(context);
        } else {
            Toast.makeText(context, "当前设备不支持蓝牙", Toast.LENGTH_SHORT).show();
        }
    }


    /**
     * 设备是否支持蓝牙
     *
     * @return true:支持 false:不支持
     */
    public boolean hasBluetooth() {
        if (mBluetoothAdapter != null) {
            Log.d(TAG, "该设备支持蓝牙:本机的蓝牙名称" + mBluetoothAdapter.getName());
            return true;
        } else {
            Log.d(TAG, "该设备不支持蓝牙");
        }
        return false;
    }


    private BroadcastReceiver mReceiver;

    private void registerBluetoothBroadcastReceiver(Context context) {
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//蓝牙状态改变的广播
        filter.addAction(BluetoothDevice.ACTION_FOUND);//找到设备的广播
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索完成的广播
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//开始扫描的广播
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//状态改变
        filter.addAction("android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED");
        if (mReceiver == null) {
            mReceiver = new BluetoothBroadCasteReceiver();
        }
        Log.d(TAG, "registerBluetoothBroadcastReceiver: 注册蓝牙广播" + mBluetoothAdapter.isEnabled());
        context.registerReceiver(mReceiver, filter);
    }

    public void unregisterBluetoothBroadCastReceiver(Context context) {

        if (mBluetoothAdapter != null) {
            mBluetoothAdapter.cancelDiscovery();
        }
//        if (mA2dpService != null) {
//            context.unbindService(mConnection);
//        }
        if (mReceiver != null) {
            context.unregisterReceiver(mReceiver);
        }
    }


    //开始扫描
    public void startScan() {
        if (mBluetoothAdapter != null) {
            // scanResultList.clear();
            if (mBluetoothAdapter.isDiscovering()) {
                Log.d(TAG, "startScan: cancelDiscovery");
                mBluetoothAdapter.cancelDiscovery();
            }
            mBluetoothAdapter.startDiscovery();
            Log.d(TAG, "startScan: 开始扫描周围蓝牙");
        } else {
            Log.d(TAG, "startScan: 扫描周围蓝牙异常");
        }
    }

    //判断蓝牙是否已经开启
    public boolean isEnabled() {
        boolean bluetooth_state = mBluetoothAdapter.isEnabled();
        Log.d(TAG, "isEnabled: 蓝牙当前是否开启::" + bluetooth_state);
        return bluetooth_state;
    }

    public void openOrCloseBluetooth(boolean flag) {
        if (flag) {
            mBluetoothAdapter.enable();
        } else {
            mBluetoothAdapter.disable();
        }
    }


    //蓝牙的广播
    public class BluetoothBroadCasteReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            switch (action) {
                case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
                    Log.d(TAG, "onReceive: 开始扫描。");
                    break;
                case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:

                    if (callBack != null) {
                        //callBack.scan_result(scanResultList, getHasConnectBlueDevices());
                        callBack.scanEnd();
                    }
                    break;
                case BluetoothDevice.ACTION_CLASS_CHANGED:
                    Log.d(TAG, "onReceive: 一个已经改变的远程设备的蓝牙类。");
                    break;
                case BluetoothDevice.ACTION_FOUND:
                    device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    BluetoothDeviceBean bluetoothDeviceBean = new BluetoothDeviceBean(device, Bluetooth_State.State_BOND_NONE);
                    if (device != null) {
                        //发现的设备统一给一个未配对的状态
                        if (callBack != null) {
                            callBack.foundDevice(bluetoothDeviceBean, getHasConnectBlueDevices());
                        }
                        Log.d(TAG, "onReceive: 远程设备发现。" + device.getName() + "??" + device.getAddress() + "???" + device.getBondState());
                    }
                    break;
                case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
                    int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
                    switch (state) {
                        case BluetoothDevice.BOND_NONE:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "BOND_NONE 删除配对" + device.getName());
                            if (callBack != null) {
                                callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.State_BOND_NONE));
                            }
                            break;
                        case BluetoothDevice.BOND_BONDING:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "BOND_BONDING 正在配对" + device.getName());

                            if (callBack != null) {
                                callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.State_BOND_BONDING));
                            }


                            break;
                        case BluetoothDevice.BOND_BONDED:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "BOND_BONDED 配对成功" + device.getName());
                            if (callBack != null) {
                                callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.State_BOND_BONDED));
                            }
                            conectBluetoothDevice(device);
                            break;
                    }
                    break;

                case BluetoothAdapter.ACTION_STATE_CHANGED:
                    int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
                    switch (blueState) {
                        case BluetoothAdapter.STATE_TURNING_ON:
                            break;
                        case BluetoothAdapter.STATE_ON:
                            Log.d(TAG, "onReceives: 蓝牙已经打开");
                            if (callBack != null) {
                                callBack.bluetooth_openOrClose(true);
                            }


                            break;
                        case BluetoothAdapter.STATE_TURNING_OFF:
                            break;
                        case BluetoothAdapter.STATE_OFF:
                            Log.d(TAG, "onReceives: 蓝牙已经关闭");
                            if (callBack != null) {
                                callBack.bluetooth_openOrClose(false);
                            }
                            break;
                    }
                    break;
                case "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED":
                    switch (intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0)) {
                        case BluetoothProfile.STATE_CONNECTING:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "BluetoothProfile.STATE_CONNECTING: " + device.getName() + " connecting");
                            if (callBack != null) {
                                callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.STATE_CONNECTING));
                            }
                            break;
                        case BluetoothProfile.STATE_CONNECTED:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            if (device != null) {
                                if (callBack != null) {
                                    callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.STATE_CONNECTED));
                                }
                                Log.d(TAG, "BluetoothProfile.STATE_CONNECTED: " + device.getName() + " connecting");
                            }
                            break;
                        case BluetoothProfile.STATE_DISCONNECTING:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            Log.d(TAG, "BluetoothProfile.STATE_DISCONNECTING: " + device.getName() + " connecting");
                            break;
                        case BluetoothProfile.STATE_DISCONNECTED:
                            device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            if (callBack != null) {
                                callBack.update_state(new BluetoothDeviceBean(device, Bluetooth_State.STATE_DISCONNECTED));
                            }
                            Log.d(TAG, "BluetoothProfile.STATE_DISCONNECTED: " + device.getName() + " disconnected");
                            break;
                    }
                    break;
            }
        }
    }

    //连接蓝牙
    public void conectBluetoothDevice(BluetoothDevice device) {
        connectOrDisConnectHidBT(device, true);
    }

    /**
     *
     * @param device
     * @param isConnect true:连接 false:断开
     */
    private void connectOrDisConnectHidBT(BluetoothDevice device, boolean isConnect) {
        if (mHidService != null) {
            //连接
            try {
                String flag = "";
                if (isConnect) {
                    flag = "connect";
                } else {
                    flag = "disconnect";
                }
                if (mHidService.getProfile() == getInputDeviceHiddenConstant()) {
                    if (device != null) {
                        //得到BluetoothInputDevice然后反射connect连接设备
                        Method method = mHidService.getProxy().getClass().getMethod(flag,
                                new Class[]{BluetoothDevice.class});
                        method.invoke(mHidService.getProxy(), device);
                    }
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                // e.printStackTrace();
            }
        }
    }

    public void disConectBluetoothDevice(BluetoothDevice device) {
        if (isHasConnected(device)) {
            //如果设备连接就让他断开连接
            connectOrDisConnectHidBT(device, false);
        }
    }

    //判断连接hid设备的服务是否连上
    private BTHidServiceBean mHidService = null;
    /**
     * 查看BluetoothInputDevice源码,connect(BluetoothDevice device)该方法可以连接HID设备,但是查看BluetoothInputDevice这个类
     * 是隐藏类,无法直接使用,必须先通过BluetoothProfile.ServiceListener回调得到BluetoothInputDevice,然后再反射connect方法连接
     */
    private BluetoothProfile.ServiceListener connect = new BluetoothProfile.ServiceListener() {
        @Override
        public void onServiceConnected(int profile, BluetoothProfile proxy) {
            //BluetoothProfile proxy这个已经是BluetoothInputDevice类型了
            mHidService = new BTHidServiceBean(profile, proxy);
        }

        @Override
        public void onServiceDisconnected(int profile) {

        }
    };


    /**
     * 获取BluetoothProfile中hid的profile,"INPUT_DEVICE"类型隐藏,需反射获取
     * @return
     */
    @SuppressLint("NewApi")
    public static int getInputDeviceHiddenConstant() {
        Class<BluetoothProfile> clazz = BluetoothProfile.class;
        for (Field f : clazz.getFields()) {
            int mod = f.getModifiers();
            if (Modifier.isStatic(mod) && Modifier.isPublic(mod)
                    && Modifier.isFinal(mod)) {
                try {
                    if (f.getName().equals("INPUT_DEVICE")) {
                        return f.getInt(null);
                    }
                } catch (Exception e) {
                }
            }
        }
        return -1;
    }


    public interface BuletoothCallBack {
        void foundDevice(BluetoothDeviceBean deviceBean, Set<BluetoothDeviceBean> hasBoundSet);

        void scan_result(Set<BluetoothDeviceBean> list, Set<BluetoothDeviceBean> hasBoundSet);

        void scanEnd();

        void bluetooth_openOrClose(boolean b);

        void update_state(BluetoothDeviceBean deviceBean);
    }


    private BuletoothCallBack callBack;

    public void setCallBack(BuletoothCallBack callBack) {
        this.callBack = callBack;
    }


    public boolean isConnectedAddress(BluetoothDevice _b) {
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        Class<BluetoothAdapter> bluetoothAdapterClass = BluetoothAdapter.class;//得到BluetoothAdapter的Class对象
        try {//得到蓝牙状态的方法
            Method method = bluetoothAdapterClass.getDeclaredMethod("getConnectionState", (Class[]) null);
            //打开权限
            method.setAccessible(true);
            int state = (int) method.invoke(bluetoothAdapter, (Object[]) null);
            if (state == BluetoothAdapter.STATE_CONNECTED) {
                Log.i(TAG, "BluetoothAdapter.STATE_CONNECTED");
                Set<BluetoothDevice> devices = bluetoothAdapter.getBondedDevices();
                Log.i(TAG, "devices:" + devices.size());
                for (BluetoothDevice device : devices) {
                    Method isConnectedMethod = BluetoothDevice.class.getDeclaredMethod("isConnected", (Class[]) null);
                    method.setAccessible(true);
                    boolean isConnected = (boolean) isConnectedMethod.invoke(device, (Object[]) null);
                    if (isConnected) {
                        Log.i(TAG, "connected:" + device.getAddress());
                        if (getAddress(_b).equals(device.getAddress())) {
                            return true;
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public String getAddress(BluetoothDevice device) {
        return device.getAddress();
    }


    public Set<BluetoothDeviceBean> getHasConnectBlueDevices() {
        Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices();
        Set<BluetoothDeviceBean> bluetoothDeviceBeans = new LinkedHashSet<>();
        if (bondedDevices != null) {
            for (BluetoothDevice de :
                    bondedDevices) {
                bluetoothDeviceBeans.add(new BluetoothDeviceBean(de, Bluetooth_State.State_BOND_BONDED));
            }
            Log.e(TAG, "getHasConnectBlueDevices: 已经配对的蓝牙设备" + bluetoothDeviceBeans.toString());
            return bluetoothDeviceBeans;
        } else {
            Log.e(TAG, "没有已经配对的蓝牙设备");
            return bluetoothDeviceBeans;
        }
    }

    //清除配对历史
    public void unpairDevice(BluetoothDevice device) {
        try {
            Method m = device.getClass()
                    .getMethod("removeBond", (Class[]) null);
            m.invoke(device, (Object[]) null);
        } catch (Exception e) {
            Log.d(TAG, "清除配对异常" + e.getMessage());
        }
    }


    public void createBond(Class btClass, BluetoothDevice btDevice) {
        Method createBondMethod = null;
        try {
            createBondMethod = btClass.getMethod("createBond");
            Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);

        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            Log.d(TAG, "createBond: XXXX");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            Log.d(TAG, "createBond: XXXX1");
        } catch (InvocationTargetException e) {
            Log.d(TAG, "createBond: XXXX2");
            e.printStackTrace();
        }
    }

    /**
     * 注册输入设备的服务
     */
    private void initHidService() {
        mBluetoothAdapter.getProfileProxy(context, connect, getInputDeviceHiddenConstant());
    }


    //判断蓝牙是否已经
    public boolean isHasConnected(BluetoothDevice device) {
        if (mHidService != null) {
            BluetoothProfile proxy = mHidService.getProxy();
            int connectionState = proxy.getConnectionState(device);
            if (connectionState == BluetoothProfile.STATE_CONNECTED) {
                return true;
            }
        }
        return false;
    }
}

 

树莓派4b安装Android TV 10 从TechFigure的视频How to Install Full Android TV 10 on Raspberry Pi 4 with Hardware Acceleration!看到树莓派4b可以安装安卓TV10系统了,就按照视频体验了下。整个过程大概需要20分钟。以下为简单步骤:1. 下载所需要的文件在https://konstakang.com/devices/rpi4/网站中,打开... 阅读详情

相关推荐

Android TV 认证简介

Android TV是在2014年6月26日Google I/O上推出的,专门为TV和机顶盒产品设计的应用程序服务包。基于Android AOSP版本,加上GTVS包就可以编译出来Android TV的Firmware。和AOSP相比,Android TV提供如下内容: • Leanback Launcher • Google Services(Google Play,YouTube,Play Movie&TV, Play Games, etc.) • Search and Assistant

tzr0330的专栏 1万+

Android 4.2蓝牙介绍

Tieto公司某蓝牙大牛写得《程序员》投稿文章Android 4.2蓝牙介绍蓝牙一词源于公元十世纪丹麦国王HaraldBlatand名字中的Blatand。Blatand的英文之意就是Blue tooth。这是因为这位让丹麦人引以为傲的国王酷爱吃蓝莓以至于牙龈都被染成蓝色。由于Blatand统一了丹麦和挪威,所以,作为无线通信技术的一种,蓝牙技术之所以取名Bluetooth可谓志向远大。不过,在以

Innost的专栏 7万+

7款热门智能电视文件管理器横向评测

在智能电视和电视盒子日益普及的今天,一款好用的文件管理器能让您的数字生活更加便捷。本文为您评测了7款广受欢迎的TV版文件管理器,助您找到最适合自己的工具。

flex8888的博客 9043

编写Android中的蓝牙模块驱动和底层HART设备

【背景】 手上有个android设备: 平板PAD:三星的Galaxy Tab 3 10.1 GT-P5210 其中带有蓝牙模块。 另外有个蓝牙的HART猫: 【记录】折腾蓝牙接口的HART猫:MACTek的Viator蓝牙HART猫 是对应的CSR8510 A10的芯片的。 HART设备 蓝牙HART猫已连接好的 现在希望可以

It_BeeCoder的博客 2946

S905L电视盒子刷机实战:Android TV与EmuELEC双系统改造指南

固件刷写是赋予老旧硬件新生的关键技术,其核心原理在于替换设备原有的操作系统镜像。通过线刷工具将定制固件写入存储介质,可以彻底改变设备的功能定位与用户体验。这一技术对于挖掘硬件潜力、延长设备生命周期具有重要价值,尤其在智能电视盒子、路由器等消费电子领域应用广泛。以搭载晶晨S905L芯片的运营商电视盒子为例,通过识别板型与无线模块、准备匹配的Android TV固件与EmuELEC游戏系统镜像,利用短接法进入刷机模式并完成写入,即可实现从单一功能设备到集流媒体播放与复古游戏机于一体的全能终端改造。过程中,精准匹

weixin_34205826的博客 425

别再手动拆解字节了!用博图这个功能指令,5分钟搞定ARRAY转BOOL数组

本文详细介绍了西门子博图中`ARRAY_TO_BOOL`功能指令的高效应用,帮助工程师快速实现ARRAY到BOOL数组的转换。通过实战案例和参数配置指南,展示了如何5分钟内完成传统方法需半小时的任务,大幅提升PLC编程效率,特别适用于通信报文解析和设备状态监控。

weixin_42653691的博客 260

android4.4 bluetooth 配置文件分析

android4.4 bluetooth 配置文件分析

qq_31608451的博客 989

深度解析:如何通过NodeRed实现私有485协议VRF中央空调与HomeAssistant的无缝对接

本文详细介绍了如何利用NodeRed的灵活流程化编程,破解并处理VRF中央空调的私有485协议,实现与HomeAssistant的无缝本地化集成。文章从协议分析、硬件准备到NodeRed核心流程搭建、数据映射及双向通信控制,提供了一套完整的实战方案,帮助用户将非标设备深度融入智能家居生态,摆脱对厂家云服务的依赖。

weixin_29173777的博客 406

Android TV蓝牙模块

一、蓝牙总体架构     二、代码分布 1.应用 /packages/apps/Settings(原生的设置应用) /packages/apps/Bluetooth(原生的蓝牙应用) 2.蓝牙java框架 /frameworks/base/core/java/android/bluetooth(蓝牙部分对应的应用程序api) /frameworks/base/services

Android系统开发-VR OS-系统安全隐私 6623

SAP FICO实操:如何修改已发生业务数据的成本中心公司代码(附RKACOR06程序运行指南)

本文详细解析了SAP FICO系统中使用RKACOR06程序修改已发生业务数据的成本中心和公司代码的实操方法。通过实战案例分享,提供从前期准备到后期验证的全流程指南,帮助企业应对组织架构重组或财务核算体系调整时的数据迁移挑战,特别适用于跨公司代码的成本中心划转场景。

weixin_27303545的博客 189

别再死记硬背Payload了!深入理解Flask/Jinja2 SSTI的Python对象继承链与魔术方法

本文深入解析Flask/Jinja2 SSTI漏洞的底层原理,从Python对象模型出发,详细讲解如何通过魔术方法链实现RCE。文章揭示了Python对象继承链与魔术方法的精妙设计,提供了防御与绕过SSTI漏洞的实用技巧,帮助开发者深入理解漏洞本质并采取有效防护措施。

weixin_42525738的博客 356

盘点2016年炙手可热的TV BOX电视盒子

随着时代的发展,电视盒子渐渐取代了传统的有线电视机顶盒,大多数家庭都用上的更为先进的电视盒子,但目前市面上的电视盒子品牌繁多,很多想买的人都不知道如何去挑选一款合适的盒子,为此我在这里从“品牌、硬件、口碑” 等角度,对几款比较火的盒子进行了仔细的对比,供大家参考选择。 一、小米盒子   外形&接口:小米盒子增强版采用了全新的外观设计,机身更薄。另外,AV线接口更换为3.5

koocan88的博客 3502

Fortify SCA 24.4 最新可用版

Fortify Static Code Analyzer(Fortify SCA) 是一款由 Micro Focus(原惠普旗下)开发的 静态应用安全测试(SAST)工具,专注于在软件开发早期通过分析源代码或编译后的二进制文件,识别潜在的安全漏洞、代码缺陷和合规性问题。以下是其核心特点与功能:核心功能 静态代码分析 在不运行程序的情况下,通过语法、语义分析检测代码中的安全漏洞(如 SQL 注入、跨站脚本(XSS)、缓冲区溢出等)和代码质量问题。

棉花糖的博客 3180

android平板改成电视盒子,安卓平板改裝成電視盒子

2013年購入國產昂X v813s安卓平板,當是上大學看看ppt還行,目前基本不使用,想改裝成電視盒子發揮余熱。這里主要參考兩位先驅的教程,非常感謝:參考一 參考二一、系統篇 系統方面,昂達14年進行過一次升級,安卓由4.1升到4.4.2流暢度大幅度提升,比起台電還算良心廠家。4.4基本能滿足大部分軟件需求,流暢度也不錯。先對系統進行root,這里我用了國產某root工具,自己斟酌。然后將...

weixin_29972227的博客 5698

手把手教你学Simulink实例--基于Simulink的电力电子系统电池管理系统(BMS)设计与仿真实例

本文详细介绍了基于Simulink的电池管理系统(BMS)设计与仿真全过程。首先阐述了BMS在安全防护、寿命延长和性能优化方面的必要性,分析了新能源汽车、光伏储能等典型应用场景的技术指标要求。接着详细讲解了Thevenin等效电路和多电平电池模型构建方法,并给出SOC估算、故障诊断等核心算法的MATLAB实现代码。通过设计正常充放电、过充保护等多场景仿真测试,验证了系统在SOC跟踪精度(误差<1.5%)和故障响应速度(<10ms)方面的优异性能。文章还提出了参数优化方法和未来AI融合、数字孪生等发展方向,提

xiaoheshang_123的博客 376

8.9华为OD机试真题 新系统 - 查找最佳充电策略 (Java/Py/C/C++/Js/Go)

8.9华为OD机试真题 新系统 - 查找最佳充电策略 (Java/Py/C/C++/Js/Go)

算法大师! 1160

安卓平板改装成电视盒子

2013年购入国产昂X v813s安卓平板,当是上大学看看ppt还行,目前基本不使用,想改装成电视盒子发挥余热。 这里主要参考两位先驱的教程,非常感谢:参考一     参考二 一、系统篇               系统方面,昂达14年进行过一次升级,安卓由4.1升到4.4.2流畅度大幅度提升,比起台电还算良心厂家。4.4基本能满足大部分软件需求,流畅度也不错。先对系统进行root,这里我

JarvisKao的博客 2万+

基于Python的Steam游戏评论与销量数据爬取及预测分析

随着数字游戏市场的蓬勃发展,Steam作为全球最大的数字游戏分发平台,积累了海量的游戏数据与玩家行为数据。本文旨在通过Python网络爬虫技术,采集Steam平台的游戏基本信息、玩家评论数据及销量相关信息,为后续的游戏评论情感分析与销量预测模型构建提供数据支持。本文将详细介绍使用requestsselenium等库实现Steam数据爬取的全过程,并提供完整的代码实现与数据处理方法。关键词:Steam;Python爬虫;数据采集;评论分析;销量预测。

2201_76125261的博客 854

目前电视盒子哪个最好?测评员总结五大目前最强的电视盒子

在画质解码方面最高支持8K,最大输出4K的高清画面,同时支持HDR10+/HLG视像技术,通过对画面的色彩和细节,层层渲染最终呈现如在眼前的灵动与鲜活,此外还有针对性的减少有害光,尤其是现在越来越多的电子设备和屏幕越来越大的趋势下,畅爽观影的同时呵护眼睛,体验科技带来的温度。视频体验方面,泰捷完全无愧于专业电视盒子的称号。泰捷品牌作为国内专业水准极高的电视盒子品牌,拥有着十年的电视视频研发经验,致力于为电视盒子打造发烧级的视频体验,优势在于视频流畅、无广告、“零极”系统速度快等等,深受发烧友的喜爱。

xzjkl66的博客 4293

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

android tv盒子哪个好用,电视盒子什么牌子好?内行人都选这五款好用又不贵的机型...

时下电视盒子的品牌很多,而且和智能手机一样,被商家开发了许许多多奇奇怪怪的功能,看着是噱头十足,买到家却发现没有什么实际的用处,不知不觉白花了许多的不必要的钱。以至于现在不少用户在购买电视盒子之前,都会弱弱的问一声:究竟电视盒子什么牌子好呢?去伪存真,抽丝剥茧之后才发现,内行人都会选以下这五款电视盒子,好用还不贵!第一款 泰捷WE60C升级版电视盒子累计收割上百个专业奖项,连续数年入选“年度十大电...

weixin_39797324的博客 2253

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

电视盒子+外贸盒子

关于电视盒子和一些外贸盒子做一些总结(品牌随机排序) 一、小米盒子 1.小米盒子1(MDZ-05-AA) 2.小米盒子1S(MDZ-06-AA)(标准版) 小米盒子1s,支持1080P高清,使用了ARM的Cortex-A9,双核1.5GHz处理器,双核400MHzMali-400 GPU,内存为1GB,支持蓝牙跟无线上网。使用安卓的4.2.2系统,支持3D视频输出播放,一个USBMicro接口,一个上网口,一个HDMI接口+音频接口。 3.小米盒子1增强版(MDZ-09-AA) 支持1080

qq_40458762的博客 5万+

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

谷歌TV认证介绍,谷歌TADA认证,谷歌电视认证介绍,谷歌电视盒子认证介绍

谷歌安卓TV/GTV认证是智能电视及机顶盒接入谷歌生态系统的必经之路。该认证要求设备从硬件到软件全面符合谷歌标准,包括兼容性测试(CTS/GTS/VTS等)、安全补丁更新、系统分区规范等核心要求。认证流程涵盖项目批准、SoC审核、设备测试及Google密钥申请等环节,重点确保设备支持BLE语音遥控、TIF架构等关键技术。通过认证的产品可获准预装GooglePlay、YouTube等应用,并获得投屏功能授权。认证过程严格限制系统修改,要求使用releasekey签名,并定期更新安全补丁以维持认证资格。

weixin_56040418的博客 1470

安卓系统的电视机_小伙买的键盘主机大家都说鸡肋,把它改成安卓电视盒真香...

上一期开箱了一个248元的键盘主机,大家都觉得很鸡肋,说实话这个凌动Z8350处理器性能确实偏弱,但是我买的初衷是接在电视机看电视用的,这不今天给它搞个安卓系统试试看。上期文章没看的点击这里买键盘送电脑?开箱一个248元的键盘,是键盘亦是主机 今天抽空把他装成安卓把,选择的是国产凤凰OS,本来准备装双系统的,但是查了下这个键盘主机只能支持UEFI启动,要装凤凰OS和WIN10双系统UEFI启动的话...

weixin_39695323的博客 1274

android 电视 网上邻居,手机要怎么连接安卓智能电视或电视盒子

原标题:手机要怎么连接安卓智能电视或电视盒子手机是人们生活中离不开的物品,然而如何手机连接智能电视或电视盒子呢?连接上,才能用手机操作智能电视或者电视盒子,这样就方便很多,那么手机如何连接智能电视/电视盒子呢?下面为大家介绍几种常用的方法。通过DLNA或AirPlay连接 当下的手机都支持DLNA或AirPlay功能,简单地说,就是相当于PC中的网上邻居的功能,允许一台设备直接访问在同一网络中的其...

weixin_31951319的博客 3014

android TV for x86,“掌上TV”的第一步,Android TV x86 体验分享

“掌上TV”的第一步,Android TV x86 体验分享2019-08-19 22:25:1610点赞50收藏7评论随着电视智能化的普及,更多功能被应用在了这个曾经的大件上,虽说我个人依然认为显示质量和效果才是电视的正确发展趋势,但事实证明只要价格合理或者产品具有差异化同样能够大卖。比如刚发布的华为智慧屏就已经弱化了电视的概念,将手机、电视、平板这些品类的功能逐渐整合,差别只是根据屏幕尺寸和需...

weixin_35511255的博客 1万+

目前电视盒子哪个最好?数码小编盘点目前性能最好的电视盒子

当然了,天猫魔盒4Pro网络机顶盒的配置也不错,运存2G,日常运行没问题,而存储16G,更是不用担心下载软件过多的情况。泰捷电视盒子是发烧友、老用户都会优选的电视盒子,由于专注于视频体验的提升,为电视机打造发烧级的性能,泰捷电视盒子的口碑一直都居高不下,无论是是流畅度、耐用性还是整体的性能都可以“一台顶三台”,所以销量非常高。天猫魔盒4Pro网络机顶盒的造型,还是非常突出的,风格一向是大红喜庆的配色,看上去很亮眼、吸睛,配色十分的大胆,在一众盒子中鹤立鸡群,喜欢红色的朋友应该会很满意。

xzjkl66的博客 1649
上一篇: android 4.4 wifi 模块开发总结(电视盒子)
下一篇: android 4.4 有线网络开发总结(电视盒子)
泡温泉的咸鱼
博客等级 码龄11年 39粉丝 48原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值