Android Bluetooth Phonak蓝牙耳机 交互

公司一款对讲软件需要适配 Phonak这款蓝牙耳机,查找很多资料之后 整理出一个示例。这段代码的完成离不开各路大神无私分享。

public class SCOHelper {
    private final static String TAG = "SCOHelper";
    private static SCOHelper instance;

    private Context context;
    private AudioManager audioManager;
    private BluetoothHeadset bluetoothHeadset;
    private BluetoothDevice bluetoothDevice;
    private BluetoothStateReceiver bluetoothStateReceiver;
    private BluetoothAdapter adapter;
    private MediaSession mediaSession;
    //*****
    private final static String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";
    private ConnectThread connectThread;
    //
    private final static int MESSAGE_RECEIVER_FORM_BLUETOOTH = 0x001;//
    private final static int MESSAGE_WAIT_BLUETOOTH_CONNECTED_REFUSH = 0x002;//刷新等待蓝牙连接后 系统内状态更新
    private final static String ACTION_PHONAK_BLUETOOTH_PTT_PRESS = "+PTT=P";//Phonak 蓝牙耳机PTT按键按下
    private final static String ACTION_PHONAK_BLUETOOTH_PTT_RELEASE = "+PTT=R";//Phonak 蓝牙耳机PTT按键抬起

    public static SCOHelper getInstance() {
        if (instance == null) {
            synchronized (SCOHelper.class) {
                if (instance == null) {
                    instance = new SCOHelper();
                }
            }
        }
        return instance;
    }

    public void init(Context context) {
        this.context = context;
        audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
        registerBlueToothHeadset();
        registerSCO();
        registerMediaButtonReceiver();
        registerBluetooth();
    }


    public void release() {
        unRegisterMediaButtonReceiver();
        unRegisterSCO();
        closeSCO();
        unRegisterBluetooth();


    }


    private void registerBlueToothHeadset() {
        BluetoothManager bm = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
        adapter = bm.getAdapter();
        adapter.getProfileProxy(context, blueHeadsetListener, BluetoothProfile.HEADSET);
    }


    private void registerSCO() {
        IntentFilter newintent = new IntentFilter();
        newintent.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
        newintent.addAction("android.bluetooth.device.action.ACL_CONNECTED");
        context.registerReceiver(mSCOHeadsetAudioState, newintent);
    }


    private void registerBluetooth() {
        bluetoothStateReceiver = new BluetoothStateReceiver();
        IntentFilter intentFilter = new IntentFilter();
        // 监视蓝牙关闭和打开的状态
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        // 监视蓝牙设备与APP连接的状态
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        context.registerReceiver(bluetoothStateReceiver, intentFilter);
    }

    private void unRegisterBluetooth() {
        context.unregisterReceiver(bluetoothStateReceiver);
    }


    public void unRegisterSCO() {
        context.unregisterReceiver(mSCOHeadsetAudioState);
    }


    public void registerMediaButtonReceiver() {
//        mediaSession = new MediaSession(context,"media");
//        ComponentName mediaButtonReceiverComponentName = new ComponentName(context, MediaButtonReceiver.class);
//        Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
//        mediaButtonIntent.setComponent(mediaButtonReceiverComponentName);
//        PendingIntent mediaButtonReceiverPendingIntent = PendingIntent.getBroadcast(context, 0, mediaButtonIntent, 0);
//        mediaSession.setFlags(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS | MediaSession.FLAG_HANDLES_MEDIA_BUTTONS);
//        mediaSession.setMediaButtonReceiver(mediaButtonReceiverPendingIntent);


        ComponentName mComponentName = new ComponentName(context.getPackageName(), MediaButtonReceiver.class.getName());
        int result = audioManager.requestAudioFocus(new MyOnAudioFocusChangeListener(), AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
        if (AudioManager.AUDIOFOCUS_REQUEST_GRANTED == result) {//到这一步,焦点已经请求成功了
            //注册媒体按键 API 21 以下, 通常的做法
            audioManager.registerMediaButtonEventReceiver(mComponentName);
        }

    }

    //解注册 多媒体按钮广播
    public void unRegisterMediaButtonReceiver() {
        mediaSession.release();
    }


    //开启SCO
    public void openSCO() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            audioManager.setMode(AudioManager.MODE_IN_CALL);
        } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
        } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            audioManager.setMode(AudioManager.MODE_IN_CALL);
        }

        if (audioManager.isBluetoothScoOn()) {
            audioManager.stopBluetoothSco();
            audioManager.setBluetoothScoOn(false);
        }
        audioManager.setBluetoothScoOn(true);
        audioManager.startBluetoothSco();
    }

    //关闭SCO
    public void closeSCO() {
        audioManager.setMode(AudioManager.MODE_NORMAL);//切换为普通模式
        if (audioManager.isBluetoothScoOn()) {
            audioManager.stopBluetoothSco();
            audioManager.setBluetoothScoOn(false);
        }
    }


    private BluetoothProfile.ServiceListener blueHeadsetListener = new BluetoothProfile.ServiceListener() {

        @Override
        public void onServiceDisconnected(int profile) {
            Log.i(TAG, "onServiceDisconnected:" + profile);

            if (profile == BluetoothProfile.HEADSET) {

                if (bluetoothHeadset != null) {
                    bluetoothHeadset.stopVoiceRecognition(bluetoothDevice);
                }
                closeSCO();
                bluetoothHeadset = null;
                if (connectThread != null) {
                    connectThread.dissConnect();
                }
            }
        }

        @Override
        public void onServiceConnected(int profile, BluetoothProfile proxy) {
            Log.i(TAG, "onServiceConnected: profile-->" + profile + proxy.getConnectedDevices().size());
            if (profile == BluetoothProfile.HEADSET) {
                bluetoothHeadset = (BluetoothHeadset) proxy;
                openSCO();
                handler.sendEmptyMessageDelayed(MESSAGE_WAIT_BLUETOOTH_CONNECTED_REFUSH, 1000);
//                if (bluetoothHeadset.getConnectedDevices().size() > 0) {
//                    for (BluetoothDevice bluetoothDevice : bluetoothHeadset.getConnectedDevices()) {
//                        Log.d(TAG, "onServiceConnected: " + bluetoothDevice.getName() + " " + bluetoothDevice.getAddress() + " " + bluetoothDevice.getBondState());
//                    }
//                    bluetoothDevice = bluetoothHeadset.getConnectedDevices().get(0);
//                    Log.i(TAG, bluetoothHeadset.startVoiceRecognition(bluetoothDevice) + "");
//
//
//                }

            }
        }
    };


    private final BroadcastReceiver mSCOHeadsetAudioState = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction() == null) {
                return;
            }
//            Log.d(TAG, "onReceive: " + intent.getAction() + "  " + intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1));
            if (intent.getAction().equals("android.bluetooth.device.action.ACL_CONNECTED")) {
                registerBlueToothHeadset();
            } else {
                //if(DEBUG)
                int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
//                Log.d(TAG, " mSCOHeadsetAudioState--->onReceive:" + state);
                if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
                    Log.i(TAG, "SCO_AUDIO_STATE_CONNECTED");
                    unRegisterSCO();
                } else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) {
                    Log.i(TAG, "SCO_AUDIO_STATE_DISCONNECTED");
                }
            }

        }
    };


    class MyOnAudioFocusChangeListener implements AudioManager.OnAudioFocusChangeListener {
        @Override
        public void onAudioFocusChange(int focusChange) {
            switch (focusChange) {
                case AudioManager.AUDIOFOCUS_GAIN:
                    break;
                case AudioManager.AUDIOFOCUS_LOSS:
                    break;
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                    break;
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                    break;
            }
        }
    }


    //
    private class BluetoothStateReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action != null) {
                switch (action) {
                    case BluetoothAdapter.ACTION_STATE_CHANGED:
                        int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
                        switch (blueState) {
                            case BluetoothAdapter.STATE_TURNING_ON:
                                Log.d(TAG, "onReceive:----> 蓝牙正在打开");
                                break;
                            case BluetoothAdapter.STATE_ON:
                                Log.d(TAG, "onReceive:----> 蓝牙已经开启");
                                break;
                            case BluetoothAdapter.STATE_TURNING_OFF:
                                Log.d(TAG, "onReceive:----> 蓝牙正在关闭");
                                break;
                            case BluetoothAdapter.STATE_OFF:
                                Log.d(TAG, "onReceive:----> 蓝牙已经关闭");

                                break;
                        }
                        break;
                    case BluetoothDevice.ACTION_ACL_CONNECTED:
                        handler.sendEmptyMessageDelayed(MESSAGE_WAIT_BLUETOOTH_CONNECTED_REFUSH, 1000);
                        Log.d(TAG, "onReceive:----> 蓝牙设备已连接");
                        break;
                    case BluetoothDevice.ACTION_ACL_DISCONNECTED:
                        Log.d(TAG, "onReceive:----> 蓝牙设备已断开");

                        break;
                }

            }

        }
    }


    /**
     * 定义 SPP 连接线程
     */
    private class ConnectThread implements Runnable {
        private BluetoothDevice device;
        private BluetoothSocket bluetoothSocket;
        private boolean transfer = false;

        public ConnectThread(BluetoothDevice bluetoothDevice) {
            this.device = bluetoothDevice;
            try {
                transfer = true;
                adapter.cancelDiscovery();
                bluetoothSocket = device.createRfcommSocketToServiceRecord(UUID.fromString(SPP_UUID));
                Log.d(TAG, "ConnectThread:  connected..");
            } catch (IOException e) {
                transfer = false;
                e.printStackTrace();
            }
        }

        //判断 Bluetoothsocket 是否连接
        public boolean isConnect() {
            return bluetoothSocket.isConnected();
        }

        //断开 Bluetooth连接
        public void dissConnect() {
            try {
                transfer = false;
                if (bluetoothSocket != null) {
                    bluetoothSocket.close();

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

        }


        @Override
        public void run() {
            try {
                if (!bluetoothSocket.isConnected()) {
                    bluetoothSocket.connect();
                }
                InputStream inputStream = bluetoothSocket.getInputStream();
                int bytes = 0;
                byte[] buffer = new byte[1024];
                while (transfer) {
                    bytes = inputStream.read(buffer);
                    Log.d(TAG, "run: " + bytes);

                    Message message = handler.obtainMessage();
                    message.obj = buffer;
                    message.arg1 = bytes;
                    message.what = MESSAGE_RECEIVER_FORM_BLUETOOTH;
                    handler.sendMessage(message);
                }


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


        }
    }


    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == MESSAGE_RECEIVER_FORM_BLUETOOTH) {
                String s = new String((byte[]) msg.obj, StandardCharsets.UTF_8).trim();
                Log.d(TAG, "handleMessage: " + s);
                if (s.equals(ACTION_PHONAK_BLUETOOTH_PTT_PRESS)) {
                    ProcessControl.getInstance().getControl().startTalk();//开始PTT 对讲

                } else if (s.equals(ACTION_PHONAK_BLUETOOTH_PTT_RELEASE)) {
                    ProcessControl.getInstance().getControl().stopTalk();//停止PTT 对讲
                }

            } else if (msg.what == MESSAGE_WAIT_BLUETOOTH_CONNECTED_REFUSH) {
                Class<BluetoothAdapter> bluetoothAdapterClass = BluetoothAdapter.class;//得到BluetoothAdapter的Class对象
                try {//得到连接状态的方法
                    Method method = bluetoothAdapterClass.getDeclaredMethod("getConnectionState", (Class[]) null);
                    //打开权限
                    method.setAccessible(true);
                    int state = (int) method.invoke(adapter, (Object[]) null);
                    if (state == BluetoothAdapter.STATE_CONNECTED) {
                        Log.i(TAG, "BluetoothAdapter.STATE_CONNECTED");
                        Set<BluetoothDevice> devices = adapter.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) {
                                bluetoothDevice = device;
                                Log.i(TAG, "connected:" + device.getName());
                            }
                        }
                    }

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

                if (bluetoothDevice == null) {
                    return;
                }
                Log.d(TAG, "onServiceConnected: " + bluetoothDevice.getName());

                connectThread = new ConnectThread(bluetoothDevice);
                new Thread(connectThread).start();

            }

        }
    };


}

以上代码可能冗余 不完善,请谅解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值