精华内容
下载资源
问答
  • Android 蓝牙开发基本流程

    万次阅读 多人点赞 2015-04-24 16:42:40
    对于一般的软件开发人员来说,蓝牙是很少用到的,尤其是Android的蓝牙开发,国内的例子很少 Android对于蓝牙开发从2.0版本的sdk才开始支持,而且模拟器不支持,测试至少需要两部手机,所以制约了很多技术人员的开发...

    此例子基于 android demo

     

    对于一般的软件开发人员来说,蓝牙是很少用到的,尤其是Android的蓝牙开发,国内的例子很少     Android对于蓝牙开发从2.0版本的sdk才开始支持,而且模拟器不支持,测试至少需要两部手机,所以制约了很多技术人员的开发;
        鉴于很多开发人员现在也有蓝牙开发的需求,也为了大家少走些弯路,先将我积攒的一点点在Android蓝牙开发经验与大家分享一下!

       首先,要操作蓝牙,先要在AndroidManifest.xml里加入权限

    <uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN" />

    <uses-permissionandroid:name="android.permission.BLUETOOTH" />

     

     

    注:Android 6.0后需要加上

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" 

    这个权限

    然后,看下api,Android所有关于蓝牙开发的类都在android.bluetooth包下,如下图,只有8个类

                    
    而我们需要用到了就只有几个而已:

        1.BluetoothAdapter 

    顾名思义,蓝牙适配器,直到我们建立bluetoothSocket连接之前,都要不断操作它BluetoothAdapter里的方法很多,常用的有以下几个:

          cancelDiscovery() 根据字面意思,是取消发现,也就是说当我们正在搜索设备的时候调用这个方法将不再继续搜索

          disable()关闭蓝牙

          enable()打开蓝牙,这个方法打开蓝牙不会弹出提示,更多的时候我们需要问下用户是否打开,一下这两行代码同样是打开蓝牙,不过会提示用户

    Intemtenabler=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

    startActivityForResult(enabler,reCode);//同startActivity(enabler);

          getAddress()获取本地蓝牙地址

          getDefaultAdapter()获取默认BluetoothAdapter,实际上,也只有这一种方法获取BluetoothAdapter

          getName()获取本地蓝牙名称

          getRemoteDevice(String address)根据蓝牙地址获取远程蓝牙设备

          getState()获取本地蓝牙适配器当前状态(感觉可能调试的时候更需要)

          isDiscovering()判断当前是否正在查找设备,是返回true

          isEnabled()判断蓝牙是否打开,已打开返回true,否则,返回false

         listenUsingRfcommWithServiceRecord(String name,UUID uuid)根据名称,UUID创建并返回BluetoothServerSocket,这是创建BluetoothSocket服务器端的第一步

          startDiscovery()开始搜索,这是搜索的第一步

    2.BluetoothDevice

    看名字就知道,这个类描述了一个蓝牙设备

          createRfcommSocketToServiceRecord(UUIDuuid)根据UUID创建并返回一个BluetoothSocket

    getState() 蓝牙状态这里要说一下,只有在 BluetoothAdapter.STATE_ON 状态下才可以监听,具体可以看andrid api;

    这个方法也是我们获取BluetoothDevice的目的——创建BluetoothSocket
    这个类其他的方法,如getAddress(),getName(),同BluetoothAdapter

        3.BluetoothServerSocket

    如果去除了Bluetooth相信大家一定再熟悉不过了,既然是Socket,方法就应该都差不多,这个类一种只有三个方法两个重载的accept(),accept(inttimeout)两者的区别在于后面的方法指定了过时时间,需要注意的是,执行这两个方法的时候,直到接收到了客户端的请求(或是过期之后),都会阻塞线程,应该放在新线程里运行!


    还有一点需要注意的是,这两个方法都返回一个BluetoothSocket,最后的连接也是服务器端与客户端的两个BluetoothSocket的连接

          close()这个就不用说了吧,翻译一下——关闭!

     4.BluetoothSocket

     跟BluetoothServerSocket相对,是客户端一共5个方法,不出意外,都会用到

          close(),关闭

          connect()连接

          getInptuStream()获取输入流

          getOutputStream()获取输出流

          getRemoteDevice()获取远程设备,这里指的是获取bluetoothSocket指定连接的那个远程蓝牙设备

     

     

    1、获取本地蓝牙适配器

          BluetoothAdapter
    mAdapter= BluetoothAdapter.getDefaultAdapter();

     2、打开蓝牙

          if(!mAdapter.isEnabled()){

    //弹出对话框提示用户是后打开

    Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

    startActivityForResult(enabler, REQUEST_ENABLE);

          //不做提示,强行打开

          // mAdapter.enable();

    }

    3、搜索设备
       1)刚才说过了mAdapter.startDiscovery()

    是第一步,可以你会发现没有返回的蓝牙设备,怎么知道查找到了呢?向下看,不要急

    2)定义BroadcastReceiver,关于BroadcastReceiver不多讲了,不是今天的讨论内容,代码如下

     

        BroadcastReceiver mReceiver = new BroadcastReceiver() {
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                //找到设备
                if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                    BluetoothDevice device = intent
                            .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
    
                    if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
    
                        Log.v(TAG, "find device:" + device.getName()
                                + device.getAddress());
                    }
                }
                //搜索完成
                else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED
                        .equals(action)) {
                    setTitle("搜索完成");
                    if (mNewDevicesAdapter.getCount() == 0) {
                        Log.v(TAG, "find over");
                    }
                }
            }
        };

     这样,没当查找到新设备或是搜索完成,相应的操作都在上段代码的两个if里执行了,不过前提是你要先注册

     

    BroadcastReceiver,具体代码如下

     

        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        registerReceiver(mReceiver, filter);
        filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        registerReceiver(mReceiver, filter)<span style="font-family:SimSun;">;</span>


    (这段代码,一般写在onCreate()里..)
      4、建立连接,首先Android sdk(2.0以上版本)支持的蓝牙连接是通过BluetoothSocket建立连接(说的不对请高人指正),服务器端(BluetoothServerSocket)和客户端(BluetoothSocket)需指定同样的UUID,才能建立连接,因为建立连接的方法会阻塞线程,所以服务器端和客户端都应启动新线程连接

     

    1)服务器端:


    //UUID格式一般是"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"可到

            //http://www.uuidgenerator.com 申请


    BluetoothServerSocket serverSocket = mAdapter. listenUsingRfcommWithServiceRecord(serverSocketName,UUID);
    serverSocket.accept();


    2)客户端:
    //还记得我们刚才在BroadcastReceiver获取了BLuetoothDevice么?
    BluetoothSocket clienSocket=dcvice. createRfcommSocketToServiceRecord(UUID);
    clienSocket.connect();


    5、数据传递,通过以上操作,就已经建立的BluetoothSocket连接了,数据传递无非是通过流的形式
    1)获取流
    inputStream = socket.getInputStream();
    outputStream = socket.getOutputStream();
    2)写出、读入
    这是基础的东西,在这就不多赘述了
    终于写完了,这是我这两天的学习经验,希望对有蓝牙需求的朋友有所帮助!另外,之前我们提过

    android.bluetooth下有8个类,还有4个类没有用到,那4个类里定义的都是常量,我也没用到它们..

     

      最后把我找到的几个蓝牙的例子附在后面,希望从事软件开发,尤其是Android开发的朋友以后多沟通、多分享!

    补充一下,使设备能够被搜索

    Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);

    startActivityForResult(enabler,REQUEST_DISCOVERABLE);

     

    demo是包括客户端和服务端;分别放到两个手机上就可以通信;大家改改应该就可以用;

    http://download.csdn.net/detail/q610098308/8681065
    这个是官方的demo:
    http://download.csdn.net/detail/q610098308/8628675

     

    https://edu.csdn.net/course/detail/24723 Android bluetooth 蓝牙通信 视频教程

     

    展开全文
  • Android蓝牙开发—经典蓝牙详细开发流程

    万次阅读 多人点赞 2018-07-16 13:41:12
    Android蓝牙开发前,首先要区分是经典蓝牙开发还是BLE(低功耗)蓝牙开发,它们的开发是有区别的,如果还分不清经典蓝牙和BLE(低功耗)蓝牙的小伙伴,可以先看Android蓝牙开发—经典蓝牙和BLE(低功耗)蓝牙的区别 ...

           Android蓝牙开发前,首先要区分是经典蓝牙开发还是BLE(低功耗)蓝牙开发,它们的开发是有区别的,如果还分不清经典蓝牙和BLE(低功耗)蓝牙的小伙伴,可以先看Android蓝牙开发—经典蓝牙和BLE(低功耗)蓝牙的区别

    本文是针对经典蓝牙开发的,如果是BLE(低功耗)蓝牙开发,可以看Android蓝牙开发—BLE(低功耗)蓝牙详细开发流程

    开发流程

    • 开启蓝牙
    • 扫描蓝牙
    • 配对蓝牙
    • 连接蓝牙
    • 通信

    开启蓝牙

    1.获取BluetoothAdapter对象

    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

    2.判断设备是否支持蓝牙

    /**
     * 设备是否支持蓝牙  true为支持
     * @return
     */
    public boolean isSupportBlue(){
        return mBluetoothAdapter != null;
    }

    3.判断蓝牙是否开启

    /**
     * 蓝牙是否打开   true为打开
     * @return
     */
    public boolean isBlueEnable(){
        return isSupportBlue() && mBluetoothAdapter.isEnabled();
    }

    4.开启蓝牙

    • 异步自动开启蓝牙
    /**
     * 自动打开蓝牙(异步:蓝牙不会立刻就处于开启状态)
     * 这个方法打开蓝牙不会弹出提示
     */
    public void openBlueAsyn(){
        if (isSupportBlue()) {
            mBluetoothAdapter.enable();
        }
    }
    • 同步提示开启蓝牙
    /**
     * 自动打开蓝牙(同步)
     * 这个方法打开蓝牙会弹出提示
     * 需要在onActivityResult 方法中判断resultCode == RESULT_OK  true为成功
     */
    public void openBlueSync(Activity activity, int requestCode){
        Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        activity.startActivityForResult(intent, requestCode);
    }

    5.权限处理

    • 处理6.0以下版本的权限

        在AndroidManifest里面添加权限

    <!-- 使用蓝牙的权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <!-- 扫描蓝牙设备或者操作蓝牙设置 -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    • 处理6.0以上版本的权限

        (1)在AndroidManifest里面添加权限

    <!-- 使用蓝牙的权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <!-- 扫描蓝牙设备或者操作蓝牙设置 -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <!--模糊定位权限,仅作用于6.0+-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <!--精准定位权限,仅作用于6.0+-->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

        (2)动态检查权限

    /**
     * 检查权限
     */
    private void checkPermissions() {
        String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION};
        List<String> permissionDeniedList = new ArrayList<>();
        for (String permission : permissions) {
            int permissionCheck = ContextCompat.checkSelfPermission(this, permission);
            if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
                onPermissionGranted(permission);
            } else {
                permissionDeniedList.add(permission);
            }
        }
        if (!permissionDeniedList.isEmpty()) {
            String[] deniedPermissions = permissionDeniedList.toArray(new String[permissionDeniedList.size()]);
            ActivityCompat.requestPermissions(this, deniedPermissions, REQUEST_CODE_PERMISSION_LOCATION);
        }
    }
    
    /**
     * 权限回调
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    @Override
    public final void onRequestPermissionsResult(int requestCode,
                                                 @NonNull String[] permissions,
                                                 @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case REQUEST_CODE_PERMISSION_LOCATION:
                if (grantResults.length > 0) {
                    for (int i = 0; i < grantResults.length; i++) {
                        if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                            onPermissionGranted(permissions[i]);
                        }
                    }
                }
                break;
        }
    }

        (3)开启GPS

    /**
     * 开启GPS
     * @param permission
     */
    private void onPermissionGranted(String permission) {
        switch (permission) {
            case Manifest.permission.ACCESS_FINE_LOCATION:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !checkGPSIsOpen()) {
                    new AlertDialog.Builder(this)
                            .setTitle("提示")
                            .setMessage("当前手机扫描蓝牙需要打开定位功能。")
                            .setNegativeButton("取消",
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            finish();
                                        }
                                    })
                            .setPositiveButton("前往设置",
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                                            startActivityForResult(intent, REQUEST_CODE_OPEN_GPS);
                                        }
                                    })
    
                            .setCancelable(false)
                            .show();
                } else {
                    //GPS已经开启了
                }
                break;
        }
    }

        (4)检查GPS是否开启

    /**
     * 检查GPS是否打开
     * @return
     */
    private boolean checkGPSIsOpen() {
        LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        if (locationManager == null)
            return false;
        return locationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER);
    }

    扫描蓝牙

    1.扫描周围蓝牙设备(配对上的设备有可能扫描不出来)

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

    2.取消扫描蓝牙

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

    3.通过广播的方式接收扫描结果

        (1)注册广播

    IntentFilter filter1 = new IntentFilter(android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_STARTED);
    IntentFilter filter2 = new IntentFilter(android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
    IntentFilter filter3 = new IntentFilter(BluetoothDevice.ACTION_FOUND);
    registerReceiver(scanBlueReceiver,filter1);
    registerReceiver(scanBlueReceiver,filter2);
    registerReceiver(scanBlueReceiver,filter3);

        (2)接收广播

    /**
     *扫描广播接收类
     * Created by zqf on 2018/7/6.
     */
    
    public class ScanBlueReceiver extends BroadcastReceiver {
        private static final String TAG = ScanBlueReceiver.class.getName();
        private ScanBlueCallBack callBack;
    
        public ScanBlueReceiver(ScanBlueCallBack 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);
            switch (action){
                case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
                    Log.d(TAG, "开始扫描...");
                    callBack.onScanStarted();
                    break;
                case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
                    Log.d(TAG, "结束扫描...");
                    callBack.onScanFinished();
                    break;
                case BluetoothDevice.ACTION_FOUND:
                    Log.d(TAG, "发现设备...");
                    callBack.onScanning(device);
                    break;
            }
        }
    }

    配对蓝牙

    1.开始配对

    /**
     * 配对(配对成功与失败通过广播返回)
     * @param device
     */
    public void pin(BluetoothDevice device){
        if (device == null){
            Log.e(TAG, "bond device null");
            return;
        }
        if (!isBlueEnable()){
            Log.e(TAG, "Bluetooth not enable!");
            return;
        }
        //配对之前把扫描关闭
        if (mBluetoothAdapter.isDiscovering()){
            mBluetoothAdapter.cancelDiscovery();
        }
        //判断设备是否配对,没有配对在配,配对了就不需要配了
        if (device.getBondState() == BluetoothDevice.BOND_NONE) {
            Log.d(TAG, "attemp to bond:" + device.getName());
            try {
                Method createBondMethod = device.getClass().getMethod("createBond");
                Boolean returnValue = (Boolean) createBondMethod.invoke(device);
                returnValue.booleanValue();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                Log.e(TAG, "attemp to bond fail!");
            }
        }
    }

    2.取消配对

    /**
     * 取消配对(取消配对成功与失败通过广播返回 也就是配对失败)
     * @param device
     */
    public void cancelPinBule(BluetoothDevice device){
        if (device == null){
            Log.d(TAG, "cancel bond device null");
            return;
        }
        if (!isBlueEnable()){
            Log.e(TAG, "Bluetooth not enable!");
            return;
        }
        //判断设备是否配对,没有配对就不用取消了
        if (device.getBondState() != BluetoothDevice.BOND_NONE) {
            Log.d(TAG, "attemp to cancel bond:" + 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.e(TAG, "attemp to cancel bond fail!");
            }
        }
    }

    3.通过广播的方式接收配对结果

        (1)注册广播

    IntentFilter filter4 = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST);
    IntentFilter filter5 = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
    registerReceiver(pinBlueReceiver,filter4);
    registerReceiver(pinBlueReceiver,filter5);

        (2)接收广播

    /**配对广播接收类
     * Created by zqf on 2018/7/7.
     */
    
    public class PinBlueReceiver extends BroadcastReceiver {
        private String pin = "0000";  //此处为你要连接的蓝牙设备的初始密钥,一般为1234或0000
        private static final String TAG = PinBlueReceiver.class.getName();
        private PinBlueCallBack callBack;
    
        public PinBlueReceiver(PinBlueCallBack 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 (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)){
                try {
                    callBack.onBondRequest();
                    //1.确认配对
    //                ClsUtils.setPairingConfirmation(device.getClass(), device, true);
                    Method setPairingConfirmation = device.getClass().getDeclaredMethod("setPairingConfirmation",boolean.class);
                    setPairingConfirmation.invoke(device,true);
                    //2.终止有序广播
                    Log.d("order...", "isOrderedBroadcast:"+isOrderedBroadcast()+",isInitialStickyBroadcast:"+isInitialStickyBroadcast());
                    abortBroadcast();//如果没有将广播终止,则会出现一个一闪而过的配对框。
                    //3.调用setPin方法进行配对...
    //                boolean ret = ClsUtils.setPin(device.getClass(), device, pin);
                    Method removeBondMethod = device.getClass().getDeclaredMethod("setPin", new Class[]{byte[].class});
                    Boolean returnValue = (Boolean) removeBondMethod.invoke(device, new Object[]{pin.getBytes()});
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)){
                switch (device.getBondState()) {
                    case BluetoothDevice.BOND_NONE:
                        Log.d(TAG, "取消配对");
                        callBack.onBondFail(device);
                        break;
                    case BluetoothDevice.BOND_BONDING:
                        Log.d(TAG, "配对中");
                        callBack.onBonding(device);
                        break;
                    case BluetoothDevice.BOND_BONDED:
                        Log.d(TAG, "配对成功");
                        callBack.onBondSuccess(device);
                        break;
                }
            }
        }
    }

    连接蓝牙

    经典蓝牙连接相当于socket连接,是个非常耗时的操作,所以应该放到子线程中去完成。

    1.连接线程

    /**连接线程
     * Created by zqf on 2018/7/7.
     */
    
    public class ConnectBlueTask extends AsyncTask<BluetoothDevice, Integer, BluetoothSocket> {
        private static final String TAG = ConnectBlueTask.class.getName();
        private BluetoothDevice bluetoothDevice;
        private ConnectBlueCallBack callBack;
    
        public ConnectBlueTask(ConnectBlueCallBack callBack){
            this.callBack = callBack;
        }
    
        @Override
        protected BluetoothSocket doInBackground(BluetoothDevice... bluetoothDevices) {
            bluetoothDevice = bluetoothDevices[0];
            BluetoothSocket socket = null;
            try{
                Log.d(TAG,"开始连接socket,uuid:" + ClassicsBluetooth.UUID);
                socket = bluetoothDevice.createRfcommSocketToServiceRecord(UUID.fromString(ClassicsBluetooth.UUID));
                if (socket != null && !socket.isConnected()){
                    socket.connect();
                }
            }catch (IOException e){
                Log.e(TAG,"socket连接失败");
                try {
                    socket.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                    Log.e(TAG,"socket关闭失败");
                }
            }
            return socket;
        }
    
        @Override
        protected void onPreExecute() {
            Log.d(TAG,"开始连接");
            if (callBack != null) callBack.onStartConnect();
        }
    
        @Override
        protected void onPostExecute(BluetoothSocket bluetoothSocket) {
            if (bluetoothSocket != null && bluetoothSocket.isConnected()){
                Log.d(TAG,"连接成功");
                if (callBack != null) callBack.onConnectSuccess(bluetoothDevice, bluetoothSocket);
            }else {
                Log.d(TAG,"连接失败");
                if (callBack != null) callBack.onConnectFail(bluetoothDevice, "连接失败");
            }
        }
    }

    2.启动连接线程

    /**
     * 连接 (在配对之后调用)
     * @param device
     */
    public void connect(BluetoothDevice device, ConnectBlueCallBack callBack){
        if (device == null){
            Log.d(TAG, "bond device null");
            return;
        }
        if (!isBlueEnable()){
            Log.e(TAG, "Bluetooth not enable!");
            return;
        }
        //连接之前把扫描关闭
        if (mBluetoothAdapter.isDiscovering()){
            mBluetoothAdapter.cancelDiscovery();
        }
        new ConnectBlueTask(callBack).execute(device);
    }

    3.判断是否连接成功

    /**
     * 蓝牙是否连接
     * @return
     */
    public boolean isConnectBlue(){
        return mBluetoothSocket != null && mBluetoothSocket.isConnected();
    }

    4.断开连接

    /**
     * 断开连接
     * @return
     */
    public boolean cancelConnect(){
        if (mBluetoothSocket != null && mBluetoothSocket.isConnected()){
            try {
                mBluetoothSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        }
        mBluetoothSocket = null;
        return true;
    }

    5.MAC地址连接

    /**
     * 输入mac地址进行自动配对
     * 前提是系统保存了该地址的对象
     * @param address
     * @param callBack
     */
    public void connectMAC(String address, ConnectBlueCallBack callBack) {
        if (!isBlueEnable()){
            return ;
        }
        BluetoothDevice btDev = mBluetoothAdapter.getRemoteDevice(address);
        connect(btDev, callBack);
    }

    通信

    1.读取数据线程

    /**读取线程
     * Created by zqf on 2018/7/7.
     */
    
    public class ReadTask extends AsyncTask<String, Integer, String> {
        private static final String TAG = ReadTask.class.getName();
        private ReadCallBack callBack;
        private BluetoothSocket socket;
    
        public ReadTask(ReadCallBack callBack, BluetoothSocket socket){
            this.callBack = callBack;
            this.socket = socket;
        }
        @Override
        protected String doInBackground(String... strings) {
            BufferedInputStream in = null;
            try {
                StringBuffer sb = new StringBuffer();
                in = new BufferedInputStream(socket.getInputStream());
    
                int length = 0;
                byte[] buf = new byte[1024];
                while ((length = in.read()) != -1) {
                    sb.append(new String(buf,0,length));
                }
                return sb.toString();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return "读取失败";
        }
    
        @Override
        protected void onPreExecute() {
            Log.d(TAG,"开始读取数据");
            if (callBack != null) callBack.onStarted();
        }
    
        @Override
        protected void onPostExecute(String s) {
            Log.d(TAG,"完成读取数据");
            if (callBack != null){
                if ("读取失败".equals(s)){
                    callBack.onFinished(false, s);
                }else {
                    callBack.onFinished(true, s);
                }
            }
        }
    }

    2.写入数据线程

    /**写入线程
     * Created by zqf on 2018/7/7.
     */
    
    public class WriteTask extends AsyncTask<String, Integer, String>{
        private static final String TAG = WriteTask.class.getName();
        private WriteCallBack callBack;
        private BluetoothSocket socket;
    
        public WriteTask(WriteCallBack callBack, BluetoothSocket socket){
            this.callBack = callBack;
            this.socket = socket;
        }
        @Override
        protected String doInBackground(String... strings) {
            String string = strings[0];
            OutputStream outputStream = null;
            try{
                outputStream = socket.getOutputStream();
    
                outputStream.write(string.getBytes());
            } catch (IOException e) {
                Log.e("error", "ON RESUME: Exception during write.", e);
                return "发送失败";
            }finally {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return "发送成功";
    
    
        }
    
        @Override
        protected void onPreExecute() {
            if (callBack != null) callBack.onStarted();
        }
    
        @Override
        protected void onPostExecute(String s) {
            if (callBack != null){
                if ("发送成功".equals(s)){
                    callBack.onFinished(true, s);
                }else {
                    callBack.onFinished(false, s);
                }
    
            }
        }
    }

     

    以上就是经典蓝牙的开发流程和部分代码,后期会提供demo下载。若有不当之处,请留言讨论,一起学习进步。

    展开全文
  • 讲解了打开蓝牙设备和搜索蓝牙设备,这篇文章来讲解蓝牙配对和蓝牙连接 1.蓝牙配对 搜索到蓝牙设备后,将设备信息填充到listview中,点击listiew则请求配对 蓝牙配对有点击配对和自动配对,点击配对就是我们...

    上篇文章:https://blog.csdn.net/huangliniqng/article/details/82185983

    讲解了打开蓝牙设备和搜索蓝牙设备,这篇文章来讲解蓝牙配对和蓝牙连接

    1.蓝牙配对

       搜索到蓝牙设备后,将设备信息填充到listview中,点击listiew则请求配对

      蓝牙配对有点击配对和自动配对,点击配对就是我们选择设备两个手机弹出配对确认框,点击确认后配对

      自动配对就是搜索到蓝牙设备后自动配对不需要输入pin码,但在基本开发中都不采用这种方式,所以这里说的是第一种配对方式

      点击配对,调用

    BluetoothDevice.class.getMethod
    

    进行配对,代码如下:

    Method method = BluetoothDevice.class.getMethod("createBond");
    Log.e(getPackageName(), "开始配对");
    method.invoke(listdevice.get(position));

    invoke传的参数就是要配对的设备(我这里是存在list中所以从list中取)

    点击之后怎会弹出配对确认框,且必须被配对的手机也点击确认配对才可以配对成功如图:

    同样的,如果我们想要配对的设备取消配对

    只需要将creatBond改为removeBond

    2.蓝牙连接:

      配对成功之后,就可以进行蓝牙连接了,蓝牙连接操作比较耗时,可以在一个线程中进行:

    调用自己定义的

    connect(listdevice.get(position));

    同样传递的参数也是设备device

    首先声明蓝牙套接字:

    private BluetoothSocket mBluetoothSocket;
    mBluetoothSocket = bluetoothDevice.createRfcommSocketToServiceRecord(BltContant.SPP_UUID);

    BltContant.SPP_UUID是一个UUID常量,至于UUID是什么,大家可以自行百度,因为详细的文章已经很多了。

    连接的时候要先判断蓝牙是否在扫描,如果在扫描就停止扫描,并且没有连接才进行连接,代码如下:

    if (bluetoothadapter.isDiscovering()) {
        bluetoothadapter.cancelDiscovery();
    }
    if (!mBluetoothSocket.isConnected()) {
        mBluetoothSocket.connect();
    }

    比如我们让其连接成功后,跳转到消息通讯界面,界面中有edittext输入框并显示当前连接的设备名称如图所示:

    在这里我们需要注意的是,当连接成功时,我们要让被连接的那部手机也自动跳转到聊天页面,所以我们要开启蓝牙服务端等待设备的连接,当设备连接时,自动跳转页面,蓝牙服务端代码如下:

    /**
     * 开启服务端
     */
    public void startBluService() {
    
        while (true) {
            try {
                if (getBluetoothServerSocket() == null){
                    Log.e("在这里获取的为空","在这里获取的为空");
                }
                bluetoothSocket = getBluetoothServerSocket().accept();
                if (bluetoothSocket != null) {
                    APP.bluetoothSocket = bluetoothSocket;
                    EventBus.getDefault().post(new BluRxBean(SERVER_ACCEPT, bluetoothSocket.getRemoteDevice()));
                    //如果你的蓝牙设备只是一对一的连接,则执行以下代码
                    getBluetoothServerSocket().close();
                    //如果你的蓝牙设备是一对多的,则应该调用break;跳出循环
                    //break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    服务端运行也在一个线程中,一直处于等待状态直到有设备连接进来。

    下篇文章 蓝牙通信:https://blog.csdn.net/huangliniqng/article/details/82189735

    欢迎关注技术公众号,微信号搜索ColorfulCode 代码男人

    分享技术文章,投稿分享,不限技术种类,不限技术深度,让更多人因为分享而受益。

    展开全文
  • andrid 蓝牙开发 bluetooth

    千次下载 热门讨论 2015-04-24 16:58:17
    android 蓝牙简单通信,蓝牙开发
  • Android蓝牙开发(一)之打开蓝牙和设备搜索

    万次阅读 多人点赞 2018-08-29 17:10:04
    Android蓝牙开发系列目录: https://blog.csdn.net/huangliniqng/article/details/82185635 一、判断是否系统是否支持蓝牙 在使用蓝牙之前,我们首先要判断手机设备是否支持蓝牙,虽然现在基本都支持蓝牙了,但是...

    Android蓝牙开发系列目录:

    https://blog.csdn.net/huangliniqng/article/details/82185635

    一、判断是否系统是否支持蓝牙

    在使用蓝牙之前,我们首先要判断手机设备是否支持蓝牙,虽然现在基本都支持蓝牙了,但是为了代码的严谨性我们还是需要在代码中判断:

    private BluetoothManager bluetoothmanger;
    private BluetoothAdapter bluetoothadapter;
    /**
      判断设备是否支持蓝牙
    */
    bluetoothmanger = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    bluetoothadapter = bluetoothmanger.getAdapter();
    if (bluetoothadapter == null) {
        Toast.makeText(MainActivity.this, "设备不支持蓝牙", Toast.LENGTH_SHORT).show();
    }

    二、判断蓝牙是否打开

    开始使用蓝牙之前,首先要判断蓝牙是否开启,如果没有开启则开启,蓝牙开启有两种方式一种是直接默认开启,另一种是弹出框让用户选择开启:

    /**
     * 判断蓝牙是否开启
     *
     * @return
     */
    public boolean blueisenable() {
        if (bluetoothadapter.isEnabled()) {
            return true;
        } else {
            return false;
        }
    }

    打开方式一:

    Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enabler, 1);

    打开方式二:

    bluetoothadapter.enable()

    如果打开蓝牙的同时想设置让自己手机蓝牙多少秒可见可以使用

    Intent discoveryIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);//默认是120秒

    discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);//设置持续时间(最多300秒)

    startActivity(discoveryIntent);

    3.搜索设备

    搜索之前我们需要判断是否正在搜索,如果正在搜索则取消搜索后再搜索,使用:

    if (bluetoothadapter.isDiscovering()) {
        bluetoothadapter.cancelDiscovery();
    }
    bluetoothadapter.startDiscovery();

    这样蓝牙就开始搜索设备了,此外我们还需要注册蓝牙广播,当扫描到设备时才方便做处理

    设置蓝牙广播过滤器也就是添加广播类型,在这里我们把蓝牙状态改变、搜索到设备、搜索完成等广播都添加进来,后续都可以用到

    /**
     * 蓝牙广播过滤器
     * 蓝牙状态改变
     * 找到设备
     * 搜索完成
     * 开始扫描
     * 状态改变
     *
     * @return
     */
    public IntentFilter makeFilter() {
        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);//状态改变
        return filter;
    }

    新建广播

    BlueToothReceiver,在OnReceive中判断,当查找到设备时我们可以得到device,在这里做处理即可,在这里我们是将设备存放在list集合中,方便做后续处理,读者可自行做处理,记得在Activity或者AndroidManifest.xml注册广播。
    
    case BluetoothDevice.ACTION_FOUND:
        Log.d(TAG, "查找设备");
        BluetoothDevice device = intent
                .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
        EventBus.getDefault().post(new BluRxBean(findDevice,device));
        break;

    4.获取本地蓝牙属性

    //获取本地蓝牙名称
    String name = bluetoothadapter.getName();
    //获取本地蓝牙地址
    String address = bluetoothadapter.getAddress();

    5.特别注意事项

       记得在配置文件中添加权限:

    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-feature android:name="android.hardware.location.gps" />
    <uses-feature
        android:name="android.hardware.bluetooth_le"
        android:required="true" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />、

    这些权限是都可以用到的,Android5.0以上要添加定位权限才可以,所以最后两项是定位权限,在扫描的时候,Android6.0以上的手机记得动态申请权限才可以扫描到设备,动态权限文章推荐AndroidAcp百度即可。

     请阅读下一篇文章:

    Android蓝牙开发(二)之蓝牙配对和蓝牙连接:https://blog.csdn.net/huangliniqng/article/details/82187966

    展开全文
  • Android 蓝牙开发(一)蓝牙通信

    万次阅读 多人点赞 2016-06-07 15:57:55
    随着可穿戴设备的流行,研究蓝牙是必不可少的...总结了下蓝牙开发使用的一些东西分享一下。 首先需要AndroidManifest.xml文件中添加操作蓝牙的权限。 /> 允许程序连接到已配对的蓝牙设备。 <uses-permissionandro
  • Android蓝牙开发—BLE(低功耗)蓝牙详细开发流程

    千次阅读 多人点赞 2018-07-25 15:36:28
    Android蓝牙开发前,首先要区分是经典蓝牙开发还是BLE(低功耗)蓝牙开发,它们的开发是有区别的,如果还分不清经典蓝牙和BLE(低功耗)蓝牙的小伙伴,可以先看Android蓝牙开发—经典蓝牙和BLE(低功耗)蓝牙的区别 ...
  • 本章节讲述Android蓝牙 开发的基础知识   1.权限   在android 清单文件中加入相应的权限   允许程序连接到已配对的蓝牙设备 &lt;uses-permissionandroid:name="Android.permission.BLUETOOTH&...
  • ST BlueNRG蓝牙开发平台

    千次阅读 2020-04-05 09:35:03
    ST BlueNRG蓝牙开发平台
  • 最近因为需要开始蓝牙相关开发,所以在网上搜索了很多内容,并且结合自己的开发过程做了一个总结,先储备上,也许可能帮到正在做蓝牙开发的同学。 蓝牙很早就是android设备上基本通讯功能了,只是以前的没有那么多...
  • 蓝牙开发经验总结

    千次阅读 2017-01-15 17:45:15
    蓝牙开发经验总结
  • Android蓝牙开发

    千次阅读 2015-08-09 11:48:59
    Android蓝牙开发 最近做蓝牙小车,需要Android端来控制小车的运动,以此文记录开发过程。使用HC-06无线蓝牙串口透传模块。对于其他的蓝牙设备本文同样适用。 蓝牙开发的流程: 获取本地蓝牙适配器 ——> ...
  • Android 经典蓝牙开发

    千次阅读 2018-11-29 18:02:26
    相信通过这三个步骤,您会很快上手一个 Android 经典蓝牙开发的 App。 蓝牙规范简介 蓝牙是一种无线技术标准,用来让固定与移动设备,在短距离间交换数据,以形成个人局域网(PAN)。其使用短波特高频(UHF)无线...
  • 最近在做蓝牙开发,刚接触时傻傻的分不清经典蓝牙和低功耗蓝牙的区别,一直用开发低功耗蓝牙的方法去连接经典蓝牙设备,最后当然是一直连接不上了。在此记录下经典蓝牙和低功耗蓝牙的区别和联系。 Android中的蓝牙 ...
  • 蓝牙开发说简单也简单,说不简单也有点难,开发人员在首次开发蓝牙前首先需要搞清楚蓝牙开发的概念,还要了解掌握蓝牙开发的一整套流程,这样才能快速上手开发蓝牙。
  • Qt for Bluetooth 蓝牙开发系列文章总纲

    千次阅读 多人点赞 2020-12-04 16:06:58
    文章目录叙述大纲金典蓝牙开发篇Qt经典蓝牙系列一(什么是经典蓝牙开发,经典蓝牙的通信机制原理)Qt经典蓝牙系列二(认识QBluetooth金典蓝牙,各种类库的介绍)Qt经典蓝牙系列三(经典蓝牙服务端的设计(win)上)Qt经典...
  • Android 蓝牙开发

    千次阅读 2016-04-15 15:47:08
    今天给大家带来蓝牙开发的基础,主要展示的是程序搜到蓝牙会通过list展示出来,并实时排序,远近与信号强弱 首先我们要有次jar包 我们先判断手机能否支持蓝牙功能 if (!getPackageManager()....
  • CSR蓝牙开发资源

    千次阅读 2017-10-26 10:05:10
    安卓蓝牙开发教程–搜索蓝牙设备 安卓蓝牙开发教程–连接蓝牙设备 转发自 http://blog.csdn.net/a1533588867/article/details/52442349 http://blog.csdn.net/a1533588867/article/details/52448065
  • Android低功耗蓝牙开发官方示例Demo

    千次下载 热门讨论 2015-12-17 09:41:44
    谷歌官方提供的Android平台上的关于低功耗蓝牙开发的示例代码,该示例包含了Android低功耗蓝牙开发的完整过程:(低功耗蓝牙可简称“BLE”) 1、声明蓝牙权限 2、设置BLE 3、扫描BLE 4、连接到GATT服务器(即低...
  • 文章目录IOS 蓝牙开发(一)蓝牙协议基础知识 IOS 蓝牙开发(一)蓝牙协议基础知识
  • iOS蓝牙开发:蓝牙连接和数据读写

    千次阅读 2017-08-01 14:41:45
    当下蓝牙开发可谓是越来越火,不论是智能穿戴的兴起还是蓝牙家具,车联网蓝牙等等,很多同学也会接触到蓝牙的项目,我从事蓝牙开发也有一段时间了,经手了两个项目。废话不多说了,先向大家简单的介绍有关蓝牙开发的...
  • Android蓝牙开发系列文章-蓝牙mesh(一)

    千次阅读 2020-03-08 08:02:18
    在《Android蓝牙开发系列文章-策划篇》中我们对蓝牙专题的内容进行整体规划,现在让我们一点点揭开他的面纱~ 本文是关于蓝牙mesh的首篇文章,由好友CSDN博主yk150915提供,在CSDN查看原文:蓝牙mesh(一) 移步微信...
  • Android蓝牙开发如何实现搜索,并将搜索的设备放到textview或者listview中,然后在对相应蓝牙设备点击后实现连接。如何确定点击的是哪个蓝牙设备?
  • Android蓝牙开发(三)之蓝牙通信

    万次阅读 2018-08-29 17:59:38
    上篇文章我们讲解了,蓝牙配对和蓝牙连接相关知识,还没有了解的朋友... 无论是做Java还是Android开发的朋友肯定都比较熟悉Socket的连接,在java中通信用的是Socket,同样的蓝牙之间通信(这里说的是经典蓝牙)方式...
  • Android BLE蓝牙开发知识总结

    千次阅读 2018-08-11 17:29:28
    Android BLE蓝牙开发知识总结 1.蓝牙介绍 1.1什么是蓝牙?   蓝牙( Bluetooth® ):是一种无线技术标准,可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换(使用2.4—2.485GHz的ISM波段的UHF...
  • Android 蓝牙开发(三)蓝牙Hid 开发

    万次阅读 热门讨论 2017-03-13 15:34:40
    Demo下载:... 最近客户需求,android系统的一个设备,想连接一个扫描枪(类似蓝牙键盘,只支持hid协议),并且可以收到其数据,填写到输入框中。我这里借了一个蓝牙鼠标,用来与android设备连接。 ...
  • 之前的几篇文章,主要介绍了经典蓝牙开发相关的知识,今天我们就来看看低功耗蓝牙的开发。如果小伙伴们对之前的文章感兴趣兴趣,也可以看看,欢迎提出不足或者建议。 【Android】蓝牙开发——经典蓝牙(附Demo源码...
  • Android蓝牙开发常见问题

    千次阅读 2017-07-04 14:29:32
    Android蓝牙开发常见问题
  • iOS 蓝牙开发 swift (一)

    千次阅读 2019-07-09 08:55:41
    iOS 蓝牙开发 1.蓝牙简介2. 蓝牙连接2.1 CoreBluetooth框架2.2 外设、服务、特征间的关系2.3 蓝牙连接过程2.4 蓝牙中心模式,外设模式2.5 蓝牙设备状态 1.蓝牙简介 蓝牙模式简介 蓝牙开发分为两种模式,中心模式...
  • Android蓝牙开发教程(一)——搜索蓝牙设备

    万次阅读 多人点赞 2016-09-05 17:59:16
    Android蓝牙功能的开发一直是很多新手头疼的问题,网上虽然也有很多教程贴,但大多都写得不全面,不能让我们真正掌握蓝牙开发的基本知识。本教程主要讲解搜索蓝牙设备、蓝牙设备之间的连接和蓝牙之间的通讯三个主要...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 59,720
精华内容 23,888
关键字:

蓝牙开发