Android蓝牙4.0开发

本文主要展示一个Android蓝牙4.0的开发示例。

一.蓝牙4.0

      蓝牙4.0应用的设备一般是比较特殊的设备,比如低耗能蓝牙灯泡。并且使用的类的方法也是有点不同的。
      BlueToothAdapter这个类是蓝牙设备的管理类。
      BlueToothDevice蓝牙设备对象,里面包含蓝牙的数据。
上面两个类蓝牙设备都会有用到,下面这两个类只有蓝牙4.0才能用到。
      BlueToothGatt低耗能蓝牙设备的控制对象
      BlueToothGattCharateristic低耗能蓝牙设备的特征值对象

二.下面展示一个蓝牙灯泡的程序设计示例

      这个蓝牙灯泡是低耗能蓝牙设备,需要支持蓝牙4.0的手机,Android版本需要以上4.3就可以了。
      开发蓝牙设备时,蓝牙的传输协议也是要理解的,这个简单说一下,比如这个蓝牙灯泡,它的协议字段是一个十七位的byte数组,其中数组的第二三四六个数组的值,分别是控制RGB和光亮度,所以控制上面数组的四个值,就可以改变蓝牙灯泡的颜色的改变。

下面的代码:

(一)权限

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<!--6.0以上才要加的额外权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

(二)设备选择的页面

package fuxi.bluetooth40;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

/**
 * 设备选择页面
 */

public class DevicesActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {

    private static final int REQUEST_ENABLE = 1001;//请求打开蓝牙的请求码
    private static final int REQUEST_LOCATION = 1002;//请求扫描显示设备的请求码
    BluetoothAdapter bluetoothAdapter;//蓝牙管理器

    ArrayAdapter<String> adapter;//列表的适配器
    List<BluetoothDevice> devices = new ArrayList();//列表的对象
    List<String> deviceNames = new ArrayList<>();//列表对象的数据

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ListView lv = new ListView(this);
        setContentView(lv);//显示列表视图
        //实例化适配器
        adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, deviceNames);
        //给列表设置适配器
        lv.setAdapter(adapter);
        requestPer();//权限的请求
        lv.setOnItemClickListener(this);//给List列表设置点击事件
    }

    /**
     * 权限的请求方法
     */
    private void requestPer() {
        if (Build.VERSION.SDK_INT >= 23) {
            int check = checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION);
            if (check != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_LOCATION);
            } else {
                //有了权限,就扫描蓝牙设备
                checkBlue();
            }
        } else {
            //版本低于6。0
            checkBlue();
        }

    }

    /**
     * 请求权限后的回调方法
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_LOCATION && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //成功了,扫描蓝牙
            checkBlue();
        } else {
            setResult(RESULT_CANCELED);
            finish();
        }
    }


    /**
     * 重写onResume方法,进行广播接收者的注册
     */
    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
    }

    /**
     * 重写生命周期的onPause方法,进行广播接收者的注销
     */
    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(receiver);
    }

    /**
     * 创建广播接收者
     * //获取设备广播
     */
    private BroadcastReceiver receiver = new BroadcastReceiver() {
        //收到广播后的回调方法
        @Override
        public void onReceive(Context context, Intent intent) {
            //获取设备
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            devices.add(device);//添加蓝牙设备对象
            //添加蓝牙设备名称
            deviceNames.add(TextUtils.isEmpty(device.getName()) ? "未命名" : device.getName());
            Toast.makeText(DevicesActivity.this,"",Toast.LENGTH_SHORT).show();
            adapter.notifyDataSetChanged();//刷新适配器
        }
    };

    /**
     * 蓝牙设备的扫描操作,并显示在视图列表中
     */
    public void checkBlue() {
        //是否打开了蓝牙
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter.isEnabled()) {//蓝牙已经就绪,可以进行扫描
            deviceNames.clear();
            devices.clear();
            adapter.notifyDataSetChanged();
            //开始扫描设置,扫描完成后会系统自动发送广播
            bluetoothAdapter.startDiscovery();
        } else {//蓝牙还没有就绪,要先打开蓝牙
            openBlue();
        }
    }

    /**
     * 打开蓝牙设备
     */
    private void openBlue() {
        //打开蓝牙
        startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), REQUEST_ENABLE);
    }

    /**
     * 请求打开蓝牙后返回的回调方法方法
     * 进行扫描蓝牙设备操作
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        checkBlue();
    }

    /**
     * 点击列表视图的回调方法
     * 这里只能选择固定产品的设备,选择其他的就提示重选
     */
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        BluetoothDevice device = devices.get(position);
        //KQX
        if (device.getName().startsWith("KQX")) {
            setResult(RESULT_OK, getIntent().putExtra("device", device));//传递数据,这个对象已经序列化过了
            finish();
        } else {
            Toast.makeText(this, "请选择卡丘熊蓝牙灯", Toast.LENGTH_SHORT).show();
        }
    }
}

(三)主页面显示的布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="test"
        android:text="校验" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="rgb"
        android:text="测试颜色" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="loop"
        android:text="循环显示" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="stopLoop"
        android:text="取消循环显示" />
</LinearLayout>

(四)设备控制的页面

package fuxi.bluetooth40;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

import java.util.List;

/**
 * Android蓝牙4.0演示使用
 */
public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_DEVICE = 1000;//设备选择页面的请求码
    BluetoothDevice device;//蓝牙设备对象
    BluetoothGatt gatt;//低耗能蓝牙设备对象
    BluetoothGattCharacteristic writer;//耗能设备的输入的特征值

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        startActivityForResult(new Intent(this, DevicesActivity.class), REQUEST_DEVICE);
    }

    /**
     * 测试
     */
    public void test(View v) {
        //发送数据
        //  byte[] buf = getBuf((byte) 0x30);
        // byte[] buf = {0x55, (byte) 0xaa, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
        byte[] buf = new byte[17];
        buf[0] = 0x55;
        buf[1] = (byte) 0xaa;
        buf[2] = 0x30;
        writer.setValue(buf);
        gatt.writeCharacteristic(writer);
    }

    /**
     * 改变颜色
     */
    public void rgb(View v) {
        int r = (int) (Math.random() * 255);
        int g = (int) (Math.random() * 255);
        int b = (int) (Math.random() * 255);
        byte[] buf = getBuf(new byte[]{0x07, (byte) r, (byte) g, (byte) b, 0x00, (byte) 0x80});
        writer.setValue(buf);
        gatt.writeCharacteristic(writer);
    }

    /**
     * 循环改变颜色
     */
    public void loop(View v) {
       handler.sendEmptyMessageDelayed(1,1000);
    }
    /**
     * 取消循环改变颜色
     */
    public void stopLoop(View v) {
        handler.removeMessages(1);
    }
    Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            changeLoop();
            handler.sendEmptyMessageDelayed(1,1000);
        }
    };
   private void changeLoop(){
       int r = (int) (Math.random() * 255);
       int g = (int) (Math.random() * 255);
       int b = (int) (Math.random() * 255);
       byte[] buf = getBuf(new byte[]{0x07, (byte) r, (byte) g, (byte) b, 0x00, (byte) 0x80});
       writer.setValue(buf);
       gatt.writeCharacteristic(writer);
   }

    /**
     * 蓝牙设备连接后的回调方法
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_DEVICE && resultCode == RESULT_OK) {
            device = data.getParcelableExtra("device");
            if (device != null)
                conn();//连接这个低耗能蓝牙设备
        } else {
            finish();
        }
    }

    /**
     * 连接低耗能蓝牙设备的方法
     */
    private void conn() {
        //BLE连接过程,这里需要最低版本是API是18,也就是android4.3以后的手机
        //第一个参数上下文
        //第二个参数是否自动连接
        //第三个参数连接后的回调方法
        gatt = device.connectGatt(this, false, mGattCallback);
        //连接
        gatt.connect();
    }

    /**
     * 连接蓝牙时,连接的回调接口
     */
    BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        //选择部分需要的回调方法
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            Log.e("TAG", "-------------------->>第一步");
            Log.e("TAG", "----------->onConnectionStateChange");
            //获取服务   获取设备电量 获取设备名称
            gatt.discoverServices();
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            //获取低耗能蓝牙设备对象
            List<BluetoothGattService> services = gatt.getServices();
            for (BluetoothGattService service : services) {
                Log.e("TAG", "---------------" + service.getUuid());
                for (BluetoothGattCharacteristic bluetoothGattCharacteristic : service.getCharacteristics()) {
                    Log.e("TAG", "------------->>>" + bluetoothGattCharacteristic.getUuid());
                }
            }
            Log.e("TAG", "----------->>onServicesDiscovered");
            //获得需要的数据
            //这里是设备对象的第三个服务的第一个特征值,用来数据的设置
            writer = services.get(2).getCharacteristics().get(0);
            //这里是设备对象的第三个服务的第二个特征值,用来数据的读取
            BluetoothGattCharacteristic reader = gatt.getServices().get(2).getCharacteristics().get(1);
            //打开读取开关
            Log.e("TAG", "----------->>获取到特征值");
            for (BluetoothGattDescriptor descriptor : reader.getDescriptors()) {
                descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                gatt.writeDescriptor(descriptor);
            }
            gatt.setCharacteristicNotification(reader, true);
        }

    };

    /**
     * 设置,获取协议数据
     */
    public byte[] getBuf(byte... buf) {
        byte[] bufs = new byte[17];
        //两位协议头
        bufs[0] = 0x55;
        bufs[1] = (byte) 0xaa;
        //协议命令共14个,不足补0
        if (buf != null && buf.length > 0) {
            for (int i = 0; i < buf.length; i++) {
                bufs[2 + i] = buf[i];//从第三个开始设置
            }
        }
        return bufs;
    }
}

      程序运行后先显示的是选择蓝牙设备的ListView页面,选择对的蓝牙设备,然后进入蓝牙设备控制页面,点击按钮就可以对蓝牙设备进行控制。但是首先你得有一个低耗能的蓝牙设备!

      说一下蓝牙的其他知识:蓝牙2.0和蓝牙3.0其实功能是差不多的,都是可以使用手机连接,并且可以进行手机无线无网通信,蓝牙4.0就和前面的版本有很多的区别,它的发展主要是用来适应其他的蓝牙设备,并且一般是单向连接,比如上面的蓝牙灯泡,只需要手机给蓝牙设备传入指令让它执行就可以了。
      蓝牙2.0开发,之前有个开发示例(实现两个手机无网无线的通信):
http://blog.csdn.net/wenzhi20102321/article/details/53870789

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

峥嵘life

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值