Android 经典蓝牙开发(二)

本文章经典蓝牙开发目录:

1、权限申请
2、开启蓝牙
3、扫描蓝牙
4、配对蓝牙
5、连接蓝牙
6、通信(实现双向通信)(我用的两个手机通过蓝牙进行通信的~)
7、关闭各种通信
Android 蓝牙开发 经典蓝牙和低功耗蓝牙(一)
Android 低功耗蓝牙开发(三)

先看一串效果图
小米LTE作为客户端,小米5作为服务端
双方配对

Android 经典蓝牙开发(二)_第1张图片
小米lte配对.png

Android 经典蓝牙开发(二)_第2张图片
小米5配对.png

客户端向服务端发送数据
Android 经典蓝牙开发(二)_第3张图片
小米lte发送数据.png

Android 经典蓝牙开发(二)_第4张图片
小米5接收数据.png

服务端向客户端回传数据
Android 经典蓝牙开发(二)_第5张图片
小米5发送数据.png

Android 经典蓝牙开发(二)_第6张图片
小米lte接收数据.png

==================开始正文==============

Android 经典蓝牙开发(二)_第7张图片
哈哈哈哈

第一步,权限申请

1、Android6.0搜索周围的蓝牙设备,需要位置权限 ACCESS_COARSE_LOCATIONACCESS_FINE_LOCATION 其中的一个,并且将手机的位置服务(定位 GPS)打开。
清单文件:

  
   
   
   
   
   
   
   

权限申请工具类:LocalUtils.java
1、这个类用来检查GPS和定位权限,回调在Activity里面。

public class LocalUtils {

    //申请权限
    public static final int permission_LocationCode = 101;
    //打开gps定位
    public static final int open_GPSCode = 102;
    static String[] permissionsIndex;
    /**
     * 此方法用来检查gps和定位权限,先检查gps是否打开,在检查是否有定位权限
     * @param activity 上下文对象
     * @param permissions 权限的名称
     * @return
     */
    public static boolean checkLocalPermissiion(Activity activity, String[] permissions) {
        permissionsIndex = permissions;
        if (checkGPSIsOpen(activity)) {
            return checkPermissions(activity);
        } else {
            Toast.makeText(activity, "需要打开GPS", Toast.LENGTH_SHORT).show();
            goToOpenGPS(activity);
        }
        return false;
    }

    /**
     * 检查GPS是否打开
     *
     */
    public static boolean checkGPSIsOpen(Activity activity) {
        LocationManager locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
        if (locationManager == null)
            return false;
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    }


    /**
     * 检查权限并申请权限
     */
    public static boolean checkPermissions(final Activity activity) {
        List permissionDeniedList = new ArrayList<>();
        for (String permission : permissionsIndex) {
            int permissionCheck = ContextCompat.checkSelfPermission(activity, permission);
            if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
                return true;
            } else {
                permissionDeniedList.add(permission);
            }
        }
        if (!permissionDeniedList.isEmpty()) {
            String[] deniedPermissions = permissionDeniedList.toArray(new String[permissionDeniedList.size()]);
            ActivityCompat.requestPermissions(activity, deniedPermissions, permission_LocationCode);
        }
        return false;
    }


    /**
     * 去手机设置打开GPS
     *
     * @param activity
     */
    public static void goToOpenGPS(Activity activity) {
        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        activity.startActivityForResult(intent, open_GPSCode);

    }
}

在Activity里面回调:


    //GPS
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case LocalUtils.open_GPSCode://检查是否手机打开定位
                if (LocalUtils.checkGPSIsOpen(this)) {
                    LocalUtils.checkLocalPermissiion(this, permissions);//检查定位权限
                } else {
                    LocalUtils.goToOpenGPS(this);//打开GPS
                }
                break;
        }
    }

    /**
     * 权限回调
     */
    @Override
    public final void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case LocalUtils.permission_LocationCode://是否打开允许定位权限
                if (grantResults.length > 0) {
                    for (int i = 0; i < grantResults.length; i++) {
                        if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                            initClassica();//初始化经典蓝牙
                        }
                    }
                }
                break;
        }
    }
Android 经典蓝牙开发(二)_第8张图片
哈哈哈.gif

ps:第一步是比较简单的哦~~看看就明白了

第二步,开启蓝牙

1、获取BluetoothAdapter
 获取BluetoothAdapter两种方式:
方式一:

  BluetoothManager systemService = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
  BluetoothAdapter bluetoothAdapter = systemService.getAdapter();

方式二:

 BluetoothAdapter bluetoothAdapter =BluetoothAdapter.getDefaultAdapter();

2、判断设备是否支持蓝牙
 如果 BluetoothAdapter.getDefaultAdapter()==null,不支持,否则支持。
3、开启蓝牙

 /**
    * 自动打开蓝牙(同步)
    * 这个方法打开蓝牙会弹出提示
    * 需要在onActivityResult 方法中判断resultCode == RESULT_OK  true为成功
    */
   public void openBlueSync(Activity activity, int requestCode) {
       Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
       activity.startActivityForResult(intent, requestCode);
   }
Android 经典蓝牙开发(二)_第9张图片
哈哈哈.jpg

ps:第二步,嗯嗯嗯....我就开始百度了~~~

第三步,扫描蓝牙

1、扫描蓝牙

/**
        * 扫描的方法 返回true 扫描成功
        * 通过接收广播获取扫描到的设备
        * @return
        */
       public boolean scanBlueTooth() {
           //当前是否在扫描,如果是就取消当前的扫描,重新扫描
           if (bluetoothAdapter.isDiscovering()) {
               bluetoothAdapter.cancelDiscovery();
           }
           //此方法是个异步操作,一般搜索12秒
           return bluetoothAdapter.startDiscovery();
       }

2、取消扫描

      /**
         * 取消扫描蓝牙
         * @return true 为取消成功
         */
        public boolean cancelScanBule() {
            return bluetoothAdapter.cancelDiscovery();
        }

3、广播接收扫描的结果
  系统自动回发送广播,告诉我们,扫描出来的蓝牙设备。
先定义接口,来回调广播中的结果(在activity接收结果的哦~~~)
ClientCallBack.java

public interface ClientCallBack {
    //开始扫描
    void onScanStarted();

    //扫描结束
    void onScanFinished();

    //扫描中
    void onScanning(BluetoothDevice device);

    //配对请求
    void onBondRequest();

    //配对成功
    void onBondSuccess(BluetoothDevice device);

    //正在配对
    void onBonding(BluetoothDevice device);

    //配对失败
    void onBondFail(BluetoothDevice device);

    //连接成功
    void onConnectSuccess();

    //连接失败
    void onConnectFail(String errorMsg);

    //连接关闭
    void onConnectClose();
}

BlueReceiver.java

public class BlueReceiver extends BroadcastReceiver {
  private String pin = "0000";  //此处为你要连接的蓝牙设备的初始密钥,一般为1234或0000
  private static final String TAG = "mcy_Receiver";
  private ClientCallBack callBack;

  public BlueReceiver(ClientCallBack callBack) {
      this.callBack = callBack;
  }

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

  //广播接收器,当远程蓝牙设备被发现时,回调函数onReceiver()会被执行
  @Override
  public void onReceive(Context context, Intent intent) {
      String action = intent.getAction();
      Log.d(TAG, "action:" + action);
      BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
      if(callBack==null){
          return;
      }
      switch (action) {
          case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
              callBack.onScanStarted();
              break;
          case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
              callBack.onScanFinished();
              break;
          case BluetoothDevice.ACTION_FOUND:
              callBack.onScanning(device);
              break;
          case BluetoothDevice.ACTION_PAIRING_REQUEST:
                  callBack.onBondRequest();
              break;
          case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
              switch (device.getBondState()) {
                  case BluetoothDevice.BOND_NONE:
                      callBack.onBondFail(device);
                      break;
                  case BluetoothDevice.BOND_BONDING:
                      callBack.onBonding(device);
                      break;
                  case BluetoothDevice.BOND_BONDED:
                      callBack.onBondSuccess(device);
                      break;
              }
              break;
      }
  }

}

为了方便统一管理,把蓝牙的操作写在服务里面,ClassicsBlueToothService.java,因此,把广播注册在服务里面,生命周期跟着服务走~~

public class ClassicsBlueToothService extends Service {
    private IntentFilter filter;
    private BlueReceiver pinBlueReceiver;
    @Override
    public void onCreate() {
        super.onCreate();
        //获取蓝牙适配器
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        //注册广播
        //蓝牙广播,系统自动发送广播,只要设置制定的 action 即可
        filter = new IntentFilter();
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//开始扫描
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//结束扫描
        filter.addAction(BluetoothDevice.ACTION_FOUND);//发现设备
        filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);//发起配对请求
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//配对状态
        pinBlueReceiver = new BlueReceiver(blueCallBack);

        registerReceiver(pinBlueReceiver, filter);//注册广播
    }

   @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(pinBlueReceiver);
    }
       ........还有很多代码,就不全部拿出来了,去github上看吧
}
Android 经典蓝牙开发(二)_第10张图片
委屈.png

ps:第三步的广播和服务的结合使用搬出来了,好久没用了,又从头过一遍,才写出来的~~~

第四步,配对蓝牙

配对:

  /**
         * 配对(配对成功与失败通过广播返回)
         * !!!弹出配对框
         *
         * @param device
         */
        public void pinBlueTooth(BluetoothDevice device) {
            if (device == null) {
                Log.e("mcy", "设备不可以为空");
                return;
            }
            //配对之前把扫描关闭
            if (bluetoothAdapter.isDiscovering()) {
                bluetoothAdapter.cancelDiscovery();
            }
            //判断设备是否配对,没有配对在配,配对了就不需要配了
            if (device.getBondState() == BluetoothDevice.BOND_NONE) {//BOND_NONE 没有配对状态
                Log.d("mcy", "attemp to bond:" + device.getName());
                try {
                    boolean returnValue = device.createBond();
                    Log.e("是否配对成功:", "" + returnValue);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    Log.d("mcy", "配对失败");

                }
            }
        }

取消配对:


        /**
         * 取消配对(取消配对成功与失败通过广播返回 也就是配对失败)
         *
         * @param device
         */
        public void cancelPinBuleTooth(BluetoothDevice device) {
            if (device == null) {
                Log.d("mcy", "设备不可以为空");
                return;
            }
            //判断设备是否配对,没有配对就不用取消了
            if (device.getBondState() != BluetoothDevice.BOND_NONE) {
                Log.d("mcy", "配对--" + device.getName());
                try {
                    Method removeBondMethod = device.getClass().getMethod("removeBond");
                    Boolean returnValue = (Boolean) removeBondMethod.invoke(device);
                    returnValue.booleanValue();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    Log.d("mcy", "取消配对失败");
                }
            }
        }
Android 经典蓝牙开发(二)_第11张图片
开心.jpg

ps:第四步,嗯嗯嗯,还是比较好看的,只是操作蓝牙

第五步,连接蓝牙

这里说一下 uuid 的问题,要想进行通信,客户端和服务端必须一致,否则连接失败,因为我用的手机进行的通讯,所有,我写了双向通信,既可以写也可以读。
连接蓝牙
注意:在连接蓝牙的同时,开启一个子线程,用来写入数据!!!!

  /**
         * @param uuid   用户指定的 uuid ,可随意写,只要格式对就行
         * @param device 连接的设备
         */
        public void connectionBlueTooth(String uuid, BluetoothDevice device) {
            try {
                bluetoothSocket = device.createRfcommSocketToServiceRecord(UUID.fromString(uuid));
                if (bluetoothSocket != null && !bluetoothSocket.isConnected()) {
                    sendDataThread = new ClientThread(bluetoothSocket, blueCallBack);
                    sendDataThread.start();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

ClientThread.java

public class ClientThread extends Thread {

    private static final String TAG = "mcy";
    private ClientCallBack callBack;
    private BluetoothSocket bluetoothSocket = null;
    private Handler handler;
    private OutputStream outputStream;

    public ClientThread(BluetoothSocket bluetoothSocket, ClientCallBack callBack) {
        this.callBack = callBack;
        this.bluetoothSocket = bluetoothSocket;
    }

    /**
     * 写数据
     *
     * @param data
     */

    public void write(byte[] data) {
        Message message = new Message();
        message.obj = data;
        handler.sendMessage(message);
    }

    /**
     * 关闭各种连接连接
     */
    public void closeSocket() {
        try {
            outputStream.close();
            bluetoothSocket.close();
            callBack.onConnectClose();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            bluetoothSocket.connect();
            outputStream = bluetoothSocket.getOutputStream();//读取需要发送的的数据
            Looper.prepare();
            handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    try {
                        byte[] data = (byte[]) msg.obj;
                        outputStream.write(data);
                        outputStream.flush();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            };
            callBack.onConnectSuccess();
            Looper.loop();
        } catch (IOException e) {
            callBack.onConnectFail(e.getMessage());
        }
    }
}
Android 经典蓝牙开发(二)_第12张图片
变少

ps:第五步,有难度,光这个uuid,我就研究了好久,到底是个什么玩意,哼、、、头大日渐变少了~~

第六步,通信(实现双向通信)

1、客户端发送数据

 /**
         * 写数据
         */
        public void sendData(byte[] data) {
            if (sendDataThread != null) {
                sendDataThread.write(data);
            }
        }

2、客户端接收数据

/**
         * 读数据
         */
        public void readListern(String name, String uuid, ServiceCallback callBack) {
            acceptThread = new AcceptThread(name, uuid, bluetoothAdapter, callBack);
            acceptThread.start();
        }

定义一个接口,来监听,收到数据的状态

public interface ServiceCallback {
    //连接成功
    void onConnectSuccess();

    //连接失败
    void onConnectFail(String errorMsg);

    //连接关闭
    void onConnectClose();

    //接收到的数据
    void onResultMessage(byte[] data);
}

开启一个子线程,用来监听服务端发过来的数据

public class AcceptThread extends Thread {
    private static final String TAG = "mcy";
    private ServiceCallback callBack;
    private BluetoothServerSocket serverSocket = null;
    private InputStream inputStream;
    private BufferedInputStream bufferedInputStream;
    private byte[] data;

    public AcceptThread(String name, String uuid, BluetoothAdapter bluetoothAdapter, ServiceCallback callBack) {
        this.callBack = callBack;
        try {
            serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(name, UUID.fromString(uuid));

        } catch (IOException e) {
            e.printStackTrace();
            callBack.onConnectFail(e.getMessage());
        }
    }

    /**
     * 关闭各种流和通信的socket
     */
    public void closeSocket() {
        try {
            inputStream.close();
            bufferedInputStream.close();
            serverSocket.close();
            callBack.onConnectClose();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            final BluetoothSocket bluetoothSocket = serverSocket.accept();
            callBack.onConnectSuccess();
            inputStream = bluetoothSocket.getInputStream();//获取服务端发来的消息
            bufferedInputStream = new BufferedInputStream(inputStream);
            while (true) {
                int available =0;
                wh:
lable==0){
                    available=inputStream.available();
                }
                data = new byte[available];
                bufferedInputStream.read(data);
                callBack.onResultMessage(data);//回传数据
            }
        } catch (IOException e) {
            callBack.onConnectFail(e.getMessage());
            e.printStackTrace();
        }
    }
}
Android 经典蓝牙开发(二)_第13张图片
哈哈哈.jpeg

ps:第六步,昨晚这一步,基本上做完了~~头发没了、、、

第七步,关闭各种通信

在第五步和第六步的子线程里均有关闭通信的方法

      /**
         * 写数据断开连接
         *
         * @return
         */
        public void cancleConnecion() {
            sendDataThread.closeSocket();
        }
        /**
         * 写数据断开连接
         *
         * @return
         */
        public void cancleServiceConnecion() {
            acceptThread.closeSocket();
        }

好了,放大招,请看activity和service

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "mcy";
    private TextView textView;
    private TextView textView2;
    private TextView textView3;
    private EditText editTxt;
    String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION};
    private final int openBTCode = 100;
    // ----------------经典蓝牙------------------
    private ClassicsBlueToothService.ClassicaBlueToothBind classicaBTBind;
    private ServiceConnection classicaConnection;
    private List devicesList = new ArrayList<>();
    private ClientCallBack blueCallBack;
    private String text = "";


    private String uuid = "6db14d27-04f1-4df8-98ca-356dfc16ee43";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        //检查权限   >6.0以上版本需要动态的申请定位权限,< 6.0 清单文件声明了即可
        if (LocalUtils.checkLocalPermissiion(this, permissions)) {
            initClassica();
        }

    }


    private void initView() {
        textView = findViewById(R.id.textView);
        textView2 = findViewById(R.id.textView2);
        textView3 = findViewById(R.id.textView3);
        editTxt = findViewById(R.id.editTxt);
        findViewById(R.id.button5).setOnClickListener(this);
        findViewById(R.id.button11).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button5://经典--写数据
                text = editTxt.getText().toString();
                classicaBTBind.sendData(text.getBytes());
                break;
            case R.id.button11://低功耗--发送数据
                break;

        }
    }

   
    private void initClassica() {
        blueCallBack = new ClientCallBack() {
            @Override
            public void onScanStarted() {
                Log.e("mcy", "开始扫描");

            }

            @Override
            public void onScanFinished() {
                Log.e("mcy", "结束扫描");
            }

            @Override
            public void onScanning(BluetoothDevice device) {
                Log.e("mcy", "扫描到设备-->" + device.getName());
                if (!devicesList.contains(device)) {
                    //将设备加入列表数据中
                    devicesList.add(device);
                }
                textView.setText(textView.getText() + "\n" + device.getName());
                Log.e(TAG, "" + device.getName());
                //已配对的蓝牙
                if (device.getBondState() == BluetoothDevice.BOND_BONDED) {//BOND_BONDED 已经配对状态
                    textView2.setText(textView2.getText() + "\n" + device.getName());
                } else {
                    classicaBTBind.pinBlueTooth(devicesList.get(0));
                }

            }

            @Override
            public void onBondRequest() {
                Log.e("mcy", "开始配对");

            }

            @Override
            public void onBondFail(BluetoothDevice device) {
                Log.e("mcy", "取消配对");
            }

            @Override
            public void onBonding(BluetoothDevice device) {
                Log.e("mcy", "配对中");
            }

            @Override
            public void onBondSuccess(BluetoothDevice device) {
                Log.e("mcy", "配对成功");
                classicaBTBind.connectionBlueTooth(uuid, device);
                //registReadListener(); //测试使用,双端通讯

            }

            @Override
            public void onConnectSuccess() {
                Log.e("mcy", "连接成功");
            }

            @Override
            public void onConnectFail(String errorMsg) {
                Log.e("mcy", "连接失败" + errorMsg);
            }

            @Override
            public void onConnectClose() {
                Log.e("mcy", "连接关闭");

            }
        };
        classicaConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                classicaBTBind = ((ClassicsBlueToothService.ClassicaBlueToothBind) service);
                if (blueCallBack != null) {
                    classicaBTBind.setBlueCallback(blueCallBack);//设置广播监听
                }
                if (classicaBTBind.getAdapter() != null) {
                    //判断蓝牙是否开启
                    if (!classicaBTBind.getAdapter().isEnabled()) {
                        //打开蓝牙
                        openBlueSync(MainActivity.this, openBTCode);
                    } else {
                        //========================开始执行工作=============================
                        classicaBTBind.scanBlueTooth();//扫描蓝牙
                        registReadListener();//注册读数据事件
                    }
                } else {
                    Toast.makeText(MainActivity.this, "此设备不支持蓝牙", Toast.LENGTH_SHORT).show();
                }


            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                classicaBTBind = null;

            }
        };
        bindService(new Intent(this, ClassicsBlueToothService.class), classicaConnection, BIND_AUTO_CREATE);
    }

    //经典蓝牙注册读数据事件
    private void registReadListener() {
        classicaBTBind.readListern("Demo", uuid, new ServiceCallback() {

            @Override
            public void onConnectSuccess() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Log.e("mcy", "读数据连接成功~");
                    }
                });
            }

            @Override
            public void onConnectFail(final String errorMsg) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Log.e("mcy", "读数据连接失败" + errorMsg);
                    }
                });

            }

            @Override
            public void onConnectClose() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Log.e("mcy", "读数据连接关闭");

                    }
                });
            }

            @Override
            public void onResultMessage(final byte[] data) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        textView3.setText(new String(data));
                    }
                });
            }
        });
    }

    /**
     * 自动打开蓝牙(同步)
     * 这个方法打开蓝牙会弹出提示
     * 需要在onActivityResult 方法中判断resultCode == RESULT_OK  true为成功
     */
    public void openBlueSync(Activity activity, int requestCode) {
        Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        activity.startActivityForResult(intent, requestCode);
    }


    //GPS
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case LocalUtils.open_GPSCode://检查是否手机打开定位
                if (LocalUtils.checkGPSIsOpen(this)) {
                    LocalUtils.checkLocalPermissiion(this, permissions);
                } else {
                    LocalUtils.goToOpenGPS(this);
                }
                break;
        }
    }

    /**
     * 权限回调
     */
    @Override
    public final void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case LocalUtils.permission_LocationCode://是否打开允许定位权限
                if (grantResults.length > 0) {
                    for (int i = 0; i < grantResults.length; i++) {
                        if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                            initClassica();//初始化经典蓝牙
                        }
                    }
                }
                break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(classicaConnection);
    }
}

ClassicsBlueToothService.java:

public class ClassicsBlueToothService extends Service {
    private IntentFilter filter;
    private BlueReceiver pinBlueReceiver;
    private BluetoothAdapter bluetoothAdapter;
    private ClientThread sendDataThread;
    private BluetoothSocket bluetoothSocket;
    private ClientCallBack blueCallBack;
    private AcceptThread acceptThread;

    @Override
    public void onCreate() {
        super.onCreate();
        //获取蓝牙适配器
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        //注册广播
        //蓝牙广播,系统自动发送广播,只要设置制定的 action 即可
        filter = new IntentFilter();
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//开始扫描
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//结束扫描
        filter.addAction(BluetoothDevice.ACTION_FOUND);//发现设备
        filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);//发起配对请求
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//配对状态
        pinBlueReceiver = new BlueReceiver(blueCallBack);

        registerReceiver(pinBlueReceiver, filter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(pinBlueReceiver);
    }

    public class ClassicaBlueToothBind extends Binder {

        public BluetoothAdapter getAdapter() {
            return bluetoothAdapter;
        }

        public void setBlueCallback(ClientCallBack callback) {
            ClassicsBlueToothService.this.blueCallBack = callback;
            pinBlueReceiver.setCallBack(callback);
        }

        /**
         * 扫描的方法 返回true 扫描成功
         * 通过接收广播获取扫描到的设备
         *
         * @return
         */
        public boolean scanBlueTooth() {
            //当前是否在扫描,如果是就取消当前的扫描,重新扫描
            if (bluetoothAdapter.isDiscovering()) {
                bluetoothAdapter.cancelDiscovery();
            }
            //此方法是个异步操作,一般搜索12秒
            return bluetoothAdapter.startDiscovery();
        }

        /**
         * 取消扫描蓝牙
         *
         * @return true 为取消成功
         */
        public boolean cancelScanBule() {
            return bluetoothAdapter.cancelDiscovery();
        }

        /**
         * 配对(配对成功与失败通过广播返回)
         * !!!弹出配对框
         *
         * @param device
         */
        public void pinBlueTooth(BluetoothDevice device) {
            if (device == null) {
                Log.e("mcy", "设备不可以为空");
                return;
            }
            //配对之前把扫描关闭
            if (bluetoothAdapter.isDiscovering()) {
                bluetoothAdapter.cancelDiscovery();
            }
            //判断设备是否配对,没有配对在配,配对了就不需要配了
            if (device.getBondState() == BluetoothDevice.BOND_NONE) {//BOND_NONE 没有配对状态
                Log.d("mcy", "attemp to bond:" + device.getName());
                try {
                    boolean returnValue = device.createBond();
                    Log.e("是否配对成功:", "" + returnValue);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    Log.d("mcy", "配对失败");

                }
            }
        }

        /**
         * 取消配对(取消配对成功与失败通过广播返回 也就是配对失败)
         *
         * @param device
         */
        public void cancelPinBuleTooth(BluetoothDevice device) {
            if (device == null) {
                Log.d("mcy", "设备不可以为空");
                return;
            }
            //判断设备是否配对,没有配对就不用取消了
            if (device.getBondState() != BluetoothDevice.BOND_NONE) {
                Log.d("mcy", "配对--" + device.getName());
                try {
                    Method removeBondMethod = device.getClass().getMethod("removeBond");
                    Boolean returnValue = (Boolean) removeBondMethod.invoke(device);
                    returnValue.booleanValue();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    Log.d("mcy", "取消配对失败");
                }
            }
        }

        /**
         * @param uuid   用户指定的 uuid ,可随意写,只要格式对就行,客户端和服务端保持一致即可。
         * @param device 连接的设备
         */



        public void connectionBlueTooth(String uuid, BluetoothDevice device) {
            try {
                bluetoothSocket = device.createRfcommSocketToServiceRecord(UUID.fromString(uuid));
                if (bluetoothSocket != null && !bluetoothSocket.isConnected()) {
                    sendDataThread = new ClientThread(bluetoothSocket, blueCallBack);
                    sendDataThread.start();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        /**
         * 写数据
         */
        public void sendData(byte[] data) {
            if (sendDataThread != null) {
                sendDataThread.write(data);
            }
        }

        /**
         * 写数据断开连接
         *
         * @return
         */
        public void cancleConnecion() {
            sendDataThread.closeSocket();
        }


        /**
         * 读数据
         */
        public void readListern(String name, String uuid, ServiceCallback callBack) {
            acceptThread = new AcceptThread(name, uuid, bluetoothAdapter, callBack);
            acceptThread.start();
        }

        /**
         * 写数据断开连接
         *
         * @return
         */
        public void cancleServiceConnecion() {
            acceptThread.closeSocket();
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new ClassicaBlueToothBind();
    }
}

github,地址 : https://github.com/Mchunyan/BlueToothTest

-----------------------The End-----------------

下一篇写,低功耗蓝牙开发~~

你可能感兴趣的:(Android 经典蓝牙开发(二))