Android蓝牙4.0开发

来源:互联网 发布:电脑扩音器软件 话筒 编辑:程序博客网 时间:2024/04/30 08:48

本文主要展示一个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

4 0
原创粉丝点击