机器人姿态(17):安卓系统重力感应App开发
现在的手机都具有传感器,也基本都有低功耗蓝牙。利用加速度计可以写一些游戏,例如桌面台球等等手机小游戏。再加上蓝牙就可以做一些硬件设备,例如体感控制器,挥挥手就可以控制灯泡鼠标,等等。程序实现上,重力感应比较简单,蓝牙BLE相对复杂。
- 重力感应
Android从SDK1.5开始就支持重力传感器,也称为加速度传感器。这个传感器可以检测手机姿态,手机反转倾斜程度可以由传感器检测到,类似三轴加速度计MPU-3050。
这个主要包括传感器扫描和一个回调函数:
//变量
private SensorManager sm;
private Sensor sensor;
private SensorEventListener mySensorListener;//ͨ通过服务得到传感器管理对象
sm = (SensorManager) MainActivity.ma.getSystemService(Service.SENSOR_SERVICE);
sensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);//得到重力传感器实例mySensorListener = new SensorEventListener() {
…
public void onSensorChanged(SensorEvent event) {
//传感器获取值发生改变,在此处理
x = event.values[0]; //手机横向翻滚,x>0左翻,x<0右翻
y = event.values[1]; //手机纵向翻滚,y>0后翻,y<0前翻
z = event.values[2]; //屏幕朝向上下,z>0朝上,z<0 朝下//传感器的精度发生改变时响应此函数
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}…
sm.registerListener(mySensorListener, sensor, SensorManager.SENSOR_DELAY_FASTEST);
//第一个参数是传感器监听器,第二个是需要监听的传感实例
以上x/y/z单位是重力加速度m/s^-2。
- 蓝牙通讯
这个主要包括设备扫描、交互控制、基础服务三部分
- 设备扫描
一、设备扫描
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private DeviceListAdapter mDeviceListAdapter;//设备列表private BluetoothDevice mBluetoothDevice;//设备
…
- 交互控制
//变量
private ExpandableListView mGattServicesList;//服务列表
private BluetoothLeService mBluetoothLeService;//服务private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics;//特征列表
private BluetoothGattCharacteristic mNotifyCharacteristic;//特征
…
private final ServiceConnection mServiceConnection = new ServiceConnection() {…
//实例化ServiceConnection接口;重写onServiceConnected和onServiceDisconnected…
public void onServiceConnected(ComponentName componentName, IBinder service){
BluetoothLeService mBluetoothLeService =;//在这初始化这个关键服务类
…
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {…
//处理蓝牙服务触发的事件
displayGattServices(mBluetoothLeService.getSupportedGattServices());
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
…
//可以设置一个按钮主动发送字符出去用于测试
mBluetoothLeService.sendSetting();
… …
public void onCreate(Bundle savedInstanceState) {…
Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);//在onCreate()里新建Intent
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);//并绑定服务
//注意后面需要unbindService
protected void onResume() {…
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());//注册分发事件的receiver,注意后面需要unregisterReceiver
boolean result = mBluetoothLeService.connect(mDeviceAddress);//建立服务
…
private void displayGattServices(List<BluetoothGattService> gattServices) {//示例
List<BluetoothGattService> gattServices;
//服务的gat列表
ArrayList<HashMap<String, String>>
gattServiceData;//服务的MAP表
ArrayList<ArrayList<BluetoothGattCharacteristic>>;//特征的gat列表们
ArrayList<ArrayList<HashMap<String, String>>>
gattCharacteristicData;//特征的MAP表们
for (BluetoothGattService gattService : gattServices) {
//对于每项的gat服务
HashMap<String, String> newServiceData;
//对应该项的MAP服务
–ArrayList<BluetoothGattCharacteristic> newgattCharas;//特征的gat表们
–ArrayList<HashMap<String, String>> newCharacteristicGroupData;//特征的MAP表们
…
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
…
- 基础服务
//GATT负责BLE连接读写属Profile通用规范。Service是Characteristic的集合,例如一个“Heart Rate Monitor”的service可能包含多个Characteristics,其中一个Characteristic可能叫做“heart rate measurement”。Characteristic为一个数据类型,包括一个value以及零到多个对此value的描述(Descriptor),Descriptor对Characteristic的描述一般例如范围、计量单位等。
//变量
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;private BluetoothGatt mBluetoothGatt;
private int mConnectionState = STATE_DISCONNECTED;
…
//需要注意一些函数调用是异步的,需要得到的值不会立即返回,而会在BluetoothGattCallback的回调函数中返回,例如discoverServices与onServicesDiscovered回调。例如readCharacteristic要在onCharacteristicRead里面。setCharacteristicNotification要在onCharacteristicChanged里面。 writeCharacteristic会到onCharacteristicWrite里面。
…
//操作的回调函数CB。重写接收到的消息的处理。
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
//—1—状态改变
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
–String intentAction = ACTION_GATT_CONNECTED;
–broadcastUpdate(intentAction);//广播意图,在交互控制里面处理
mBluetoothGatt.discoverServices();//发起活动,在交互控制里面处理
//—2—发现服务
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);//广播意图,在交互控制里面处理
//寻找服务之后,我们就可以和设备进行通信,比如下发配置值,获取设备电量什么的
//—3—读取到值
public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic,int status) {
if (characteristic.getUuid().toString().equals(“00002a19-0000-1000-8000-00805f9b34fb”)){//根据UUID来判断读到的是什么值
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic););//广播意图,在交互控制里面处理
//—4—收到上报值
public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {
//—5—特征被写
public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status)
{
//根据 characteristic.getValue()来判断是哪个值发送成功了
//比如连接上设备之后有一大串命令需要下发,调用多次写命令, 这样需要判断是不是所有命令都成功了
…
//操作的主动方法。常规用到的有:connect,discoverServices,disconnect,readCharacteristic,setCharacteristicNotification,getServices
//—1—connect
public boolean connect(final String address) {
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);//连接成功,到回调onConnectionStateChange
//—2—disconnect
public void disconnect() {
//—3—read
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
mBluetoothGatt.readCharacteristic(characteristic);
//—4—读操作示例
public void readBatrery(){
//—5—写操作示例
public void sendSetting(){
- 读写示例
//中心设备向外围设备的写入命令字
public void WriteSetting(){
BluetoothGattService sendService
= mBluetoothGatt.getService(UUID.fromString(“0000fff0-0000-1000-8000-00805f9b34fb”));
//此处的0000180f…取决于询问硬件
if(sendService!=null) {
BluetoothGattCharacteristic sendCharacteristic
= sendService.getCharacteristic(UUID.fromString(“0000fff1-0000-1000-8000-00805f9b34fb”));
//此处的0000180f…取决于询问硬件
if(sendCharacteristic!=null) {
sendCharacteristic.setValue //(new byte[] { 0x01,0x02,0x03 });
(new byte[] {0x24,0x4d,0x3c,} );//命令字
mBluetoothGatt.writeCharacteristic(sendCharacteristic);//写命令到设备,}
//中心设备向外围设备的读取信息