android低功耗蓝牙APP开发问题记录

概述:实现了BLE扫描、连接、读写、通知接收等操作。
1、扫描方法的回调函数更改
在android5.0(SDK 21)以上时,BluetoothAdapter.startLeScan()和stopLEScan已经过时,所以在5.0以上时需要判定android版本.
扫描代码:

private void scanLeDevice(final boolean enable) {
        if (enable) {
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (Build.VERSION.SDK_INT < 21) {
                        mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    } else {
                        mLEScanner.stopScan(mScanCallback);

                    }
                }
            }, SCAN_PERIOD);
            if (Build.VERSION.SDK_INT < 21) {
                mBluetoothAdapter.startLeScan(mLeScanCallback);
            } else {
                mLEScanner.startScan(filters, settings, mScanCallback);
            }
        } else {
            if (Build.VERSION.SDK_INT < 21) {
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
            } else {
                mLEScanner.stopScan(mScanCallback);
            }
        }
    }

回调函数:

 private ScanCallback mScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            Log.i("callbackType", String.valueOf(callbackType));
            Log.i("result", result.toString());
            BluetoothDevice btDevice = result.getDevice();
            connectToDevice(btDevice);
        }

        @Override
        public void onBatchScanResults(List results) {
            for (ScanResult sr : results) {
                Log.i("ScanResult - Results", sr.toString());
            }
        }

        @Override
        public void onScanFailed(int errorCode) {
            Log.e("Scan Failed", "Error Code: " + errorCode);
        }
    };

    private BluetoothAdapter.LeScanCallback mLeScanCallback =
            new BluetoothAdapter.LeScanCallback() {
                @Override
                public void onLeScan(final BluetoothDevice device, int rssi,
                                     byte[] scanRecord) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Log.i("onLeScan", device.toString());
                            connectToDevice(device);
                        }
                    });
                }
            };

2、Android6.0权限问题
在手机上编译调试时,由于android6.0系统APP权限改为手动添加,则在调试低版本android BLE程序时要在build.gradle中将targetSdkVersion改为23以下,否则会运行出错。要想完全解决该问题,则需要判断android系统版本,查看android6.0的权限文档对代码进行修改。
例如:
android低功耗蓝牙APP开发问题记录_第1张图片
android低功耗蓝牙APP开发问题记录_第2张图片
3、低功耗蓝牙读写通信

package com.example.lenovo.ss1003;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
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.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

import static android.bluetooth.BluetoothAdapter.STATE_DISCONNECTED;

/**
 * Created by lenovo on 2016/11/8.
 */

public class BluetoothLeService extends Service {
    //预定义
    private Handler mHandler;
    private final String LIST_NAME = "NAME";
    private final String LIST_UUID = "UUID";
    private final static String TAG = BluetoothLeService.class.getSimpleName();
    private ArrayList> mGattCharateristics = new ArrayList>();//蓝牙数据描述对象链表
    private BluetoothManager bluetoothManager;
    private BluetoothAdapter bluetoothAdapter;
    private String mBluetoothDeviceAddress;
    private BluetoothGatt bluetoothGatt;
    public BluetoothGattService mBluetoothGattService;
    private BluetoothGattCharacteristic mBluetoothGattCharacteristic;
    private int mConnectionState = STATE_CONNECTED;
    private static final int STATE_CONNECTING = 1;
    private static final int STATE_CONNECTED = 2;
    static final String ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
    static final String ACTION_GATT_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
    private static final String ACTION_GATT_SERVICES_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCONNECTED";
    public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
    public final static String ACTION_GATT_WRITE="com.example.bluetooth.le.ACTION_WRITE";
    static final String ACTION_DATA_AVAILABLE = "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
    static final String EXTRA_DATA = "com.example.bluetooth.le.EXTRA_DATA";
    public final static UUID UUID_TENS_MEASUREMWNT = UUID.fromString(SampleGattAttributes.TENS_MEASUREMENT);
    public final static UUID UUID_TENS_CHARACTERISTIC = UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG);
    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        //获取蓝牙的连接状态,gatt客户端,status蓝牙连接操作成功后的连接状态,newState返回新的连接状态
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            String intentAction;
            //判断蓝牙新的连接状态,更新并发送广播
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                intentAction = ACTION_GATT_CONNECTED;
                mConnectionState = STATE_CONNECTED;
                broadcastUpdate(intentAction);
                Log.i(TAG, "Connected to GATT server");
                Log.i(TAG, "Attempting to start service discovery" + bluetoothGatt.discoverServices());
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                intentAction = ACTION_GATT_DISCONNECTED;
                mConnectionState = STATE_DISCONNECTED;
                Log.i(TAG, "Disconnected from GATT server");
                broadcastUpdate(intentAction);
            }
        }

        //readCharacteristic的时候会触发
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                                         BluetoothGattCharacteristic characteristic,
                                         int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
                Log.e("---------------", "onCharacteristicRead可用");
            }
        }

        //回调显示一个远程变化,broadcastUpdate更新变化数据;
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
            Log.e("---------------", "onCharacteristicChanged可用");
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt mBluetoothGatt,
                                          BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(mBluetoothGatt, characteristic, status);
            Log.e(TAG, "onCharWrite " + mBluetoothGatt.getDevice().getName()
                    + " write "
                    + characteristic.getUuid().toString()
                    + " -> ");
        }

        @Override
        public void onDescriptorRead(BluetoothGatt gatt,
                                     BluetoothGattDescriptor descriptor, int status) {
            Log.w("lwj", "lwj---onDescriptorRead");
            // TODO Auto-generated method stub
            //super.onDescriptorRead(gatt, descriptor, status);
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt,
                                      BluetoothGattDescriptor descriptor, int status) {
            UUID uuid = descriptor.getCharacteristic().getUuid();
        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
            Log.w("lwj", "lwj---onReadRemoteRssi");
            // TODO Auto-generated method stub
            super.onReadRemoteRssi(gatt, rssi, status);
        }

        @Override
        public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
            Log.w("lwj", "lwj---onReliableWriteCompleted");
            // TODO Auto-generated method stub
            super.onReliableWriteCompleted(gatt, status);
        }
// 蓝牙连接后回调该函数,立即执行 onServicesDiscovered方法,下列Log都会在Android studio 的error中打印
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            // TODO Auto-generated method stub
            super.onServicesDiscovered(gatt, status);
            //discoverServices()函数的回调函数
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.e(TAG, "discoverServices完成");
                mBluetoothGattService = gatt.getService(UUID_TENS_MEASUREMWNT);
                //还需要进行判断是否为null
                if (mBluetoothGattService == null) {
                    Log.e(TAG, "getService未成功");
                } else {
                    Log.e(TAG, "getService成功");
                }
                //再通过mBluetoothGattService获得BluetoothGattCharacteri
                mBluetoothGattCharacteristic =
                        mBluetoothGattService.getCharacteristic(UUID_TENS_CHARACTERISTIC);
                //还需要在进行判断是否为null
                if (mBluetoothGattCharacteristic == null) {
                    Log.e(TAG, "getCharacteristic未成功");
                } else {
                     Log.e(TAG, "getCharacteristic成功");
                }
            }else {
                Log.e(TAG, "discoverServices未完成");
//              Toast.makeText(MainActivity.this, "discover不成功,请再尝试", Toast.LENGTH_LONG).show();
            }
         **Log.e("++++++++++++",displayGattServices(getSupportedGattServices()).get(3).get(7).toString());
         //行为广播,可在已绑定的Acivity中获取;
            broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
        }**
    };
    //广播发送,更新意图对象。
    private void broadcastUpdate(String action) {
        final Intent intent=new Intent(action);
        sendBroadcast(intent);
    }
    //更新蓝牙行为数据和远程设备
    private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) {
        //创建意图对象
        final Intent intent = new Intent(action);
        //如果TENS_MEASUREMWNT的UUID和获取设备UUID匹配;
        if (UUID_TENS_MEASUREMWNT.equals(characteristic.getUuid())) {
            int flag = characteristic.getProperties();//获取设备属性
            int format = -1;
            if ((flag & 0x01) != 0) {
                format = BluetoothGattCharacteristic.FORMAT_UINT16;//将uuid转为16进制格式
                Log.d(TAG, "Heart rate format UINT16");
            } else {
                format = BluetoothGattCharacteristic.FORMAT_UINT8;//将uuid转为8进制格式
                Log.d(TAG, "Heart rate format UINT8");
            }
            //
            final int TENS = characteristic.getIntValue(format, 1);
            Log.d(TAG, String.format("Recevied TENS data:%d", TENS));
            intent.putExtra(EXTRA_DATA, String.valueOf(TENS));//将心率的数据添加到intent对象中;
        } else {
            //如果数据是byte形式数据,将遍历数据并转化为String形式添加到intent中;
            final byte[] data = characteristic.getValue();
            if (data != null && data.length > 0) {
                final StringBuilder stringBuilder = new StringBuilder(data.length);
                for (byte byteChar : data) {
                    stringBuilder.append(String.format("%02X", byteChar));
                    intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
                }
            }
            sendBroadcast(intent);//广播转发intent对象;
        }

    }
//继承Binder类实现BluetoothLeService 的getService方法;
    public class LocalBinder extends Binder {
        BluetoothLeService getService() {
            return BluetoothLeService.this;
        }
    }
    private final IBinder mBinder = new LocalBinder();
    //绑定intent对象,作为intent和service之间的数据传递中间者。
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
    //解除绑定
    @Override
    public boolean onUnbind(Intent intent) {
        close();
        return super.onUnbind(intent);
    }

    public boolean initialize() {
        if (bluetoothManager == null) {
            bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);//通过蓝牙管理者获取当前系统蓝牙服务
            if (bluetoothManager == null) {
                return false;
            }
        }
        bluetoothAdapter = bluetoothManager.getAdapter();//获取适配器
        if (bluetoothAdapter == null) {
            return false;
        }
        return true;
    }
    /*
          * 获取低功耗蓝牙设备后,连接到GATT服务
          * 目的设备的地址作为参数;
          * 连接初始化成功后异步连接到设备;
          * */
    //判断蓝牙是否可连接
    public boolean Connect(final String address) {
        if (bluetoothAdapter == null || address == null) {
            Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
            return false;
        }else if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
                && bluetoothGatt != null) {
            Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
            if (bluetoothGatt.connect()) {
                mConnectionState = STATE_CONNECTING;
                return true;
            } else {
                return false;
            }
        }
        final BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
        if (device == null) {
            Log.w(TAG, "Device not found.  Unable to connect.");
            return false;
        }
        // We want to directly connect to the device, so we are setting the autoConnect
        // parameter to false.
        bluetoothGatt = device.connectGatt(this,true, mGattCallback);//true是设置自动连接蓝牙;
        Log.e(TAG, "Trying to create a new connection.");
        if(bluetoothGatt.connect()){
           // Toast.makeText(this, "连接成功",Toast.LENGTH_LONG).show();
            //连接成功后,再进行discoverServices()
            //并在其回调函数中执行getService(),获得BluetoothGattService
            if(bluetoothGatt.discoverServices()){
                Log.e(TAG, "discoverServices已经开始了");
            }else{
                Log.e(TAG, "discoverServices没有开始");
            }
        }
        else{
            Toast.makeText(this, "未连接成功,请再尝试", Toast.LENGTH_LONG).show();
        }
        mBluetoothDeviceAddress = address;
        mConnectionState = STATE_CONNECTING;
        return true;
    }
    public void DisConnect(){
        if(bluetoothAdapter==null||bluetoothGatt==null){
            return;
        }
        bluetoothGatt.disconnect();
    }
    //关闭服务,释放Service绑定对象
    private void close() {
        if(bluetoothGatt==null){
            return;
        }
        bluetoothGatt.close();
        bluetoothGatt=null;
    }
   //读取蓝牙设备特征,如果蓝牙适配器为空则返回空对象;否则读取蓝牙特征值
    public void readCharacteristic(BluetoothGattCharacteristic characterristic){
        if(bluetoothAdapter==null||bluetoothGatt==null){
            Log.e("=============", "适配器或协议栈为空");
        }else {
            bluetoothGatt.readCharacteristic(characterristic);
            Log.e("=============", "开始读取");
        }
    }
    //写入指定的characteristic
    public void writeCharacteristic(BluetoothGattCharacteristic characteristic) {
        if (bluetoothAdapter == null || bluetoothGatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        bluetoothGatt.writeCharacteristic(characteristic);
    }
    //获取蓝牙支持的服务
    public List getSupportedGattServices(){
        if(bluetoothGatt==null) {
            return null;
        }else
            return bluetoothGatt.getServices();
    }
    /*
      设置蓝牙通信是否可获取通知;
      如果bluetoothAdapter和bluetoothGatt都不为null,可向bluetoothGatt中设置蓝牙可通知;
      其中public static String CLIENT_CHARACTERISTIC_READ="00002902-0000-1000-8000-00805f9b34fb",是notify中的descriptor的UUID,必须对其进行descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)设置,否知收不到通知。向设备写数据时需要延时操作(200m以上)才能在广播接收者内接收到notify。
    */
   public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,boolean enabled) {
        if (bluetoothAdapter == null || bluetoothGatt == null) {
            Log.e(TAG, "BluetoothAdapter not initalized");
            return;
        }else {
                BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_READ));
                descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                bluetoothGatt.writeDescriptor(descriptor);
                Log.e("设置descriptor:",descriptor.toString());
            bluetoothGatt.setCharacteristicNotification(characteristic, enabled);
            Log.e("设置notify:",characteristic.getUuid().toString()+enabled);
        }
    }
    //遍历蓝牙service和Characteristic列表,返回二维数组;
  public ArrayList> displayGattServices(List gattServices) {
      if (gattServices == null){ return null;}
      String uuid = null;
      String unknownServiceString = getResources().getString(R.string.unknown_service);
      String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
      ArrayList> gattServiceData = new ArrayList>();
      ArrayList>> gattCharacteristicData
              = new ArrayList>>();
      mGattCharateristics= new ArrayList>();

      // Loops through available GATT Services.
      for (BluetoothGattService gattService : gattServices) {
          HashMap currentServiceData = new HashMap();
          uuid = gattService.getUuid().toString();
          currentServiceData.put(
                  LIST_NAME, SampleGattAttributes.lookup(uuid, unknownServiceString));
          currentServiceData.put(LIST_UUID, uuid);
          gattServiceData.add(currentServiceData);

          ArrayList> gattCharacteristicGroupData =
                  new ArrayList>();
          List gattCharacteristics =
                  gattService.getCharacteristics();
          ArrayList charas =
                  new ArrayList();

          // Loops through available Characteristics.
          for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
              charas.add(gattCharacteristic);
              HashMap currentCharaData = new HashMap();
              uuid = gattCharacteristic.getUuid().toString();
              currentCharaData.put(
                      LIST_NAME, SampleGattAttributes.lookup(uuid, unknownCharaString));
              currentCharaData.put(LIST_UUID, uuid);
              gattCharacteristicGroupData.add(currentCharaData);
                  //接受Characteristic被写的通知,收到蓝牙模块的数据后会触发mOnDataAvailable.onCharacteristicWrite()
              setCharacteristicNotification(gattCharacteristic, true);
          }
          mGattCharateristics.add(charas);
          gattCharacteristicData.add(gattCharacteristicGroupData);
      }
/*      Log.e("---------", String.valueOf(mGattCharateristics.get(3).get(0).getUuid()));
      Log.e("---------", String.valueOf(mGattCharateristics.get(3).get(1).getUuid()));
      Log.e("---------", String.valueOf(mGattCharateristics.get(3).get(2).getUuid()));
      Log.e("---------", String.valueOf(mGattCharateristics.get(3).get(3).getUuid()));
      Log.e("---------", String.valueOf(mGattCharateristics.get(3).get(4).getUuid()));
      Log.e("---------", String.valueOf(mGattCharateristics.get(3).get(5).getUuid()));*/
      return  mGattCharateristics;
  }
 }
 private BluetoothGattCharacteristic mGattCharateristics;//蓝牙数据描述对象链表
    private BluetoothGatt mBluetoothGatt;
    private BluetoothLeService mBluetoothLeService;
    public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";//外部仪器地址
    private String mDeviceAddress;
    BluetoothGattCharacteristic mCharacteristic;
    private ArrayList> mGattCharacteristics =
            new ArrayList>();
             private final ServiceConnection mServiceConnection = new ServiceConnection() {
     **//初始化蓝牙连接服务,如果蓝牙初始化成功则进行蓝牙连接;如果没有此方法,广播接收者无法接收数据,则不能进行读写操作。** 
      @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mBluetoothLeService = ((BluetoothLeService.LocalBinder) iBinder).getService();
            if (!mBluetoothLeService.initialize()) {//判断蓝牙是否初始化
                finish();
            }
            mBluetoothLeService.Connect(mDeviceAddress);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mBluetoothLeService = null;
        }
    };
    private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
                mGattCharacteristics=mBluetoothLeService.displayGattServices(mBluetoothLeService.getSupportedGattServices());
            }else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
                intent.getStringExtra(BluetoothLeService.EXTRA_DATA);
                Log.e("+++++++++++",intent.getStringExtra(BluetoothLeService.EXTRA_DATA).toString());
            }
        }
    };

  protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_treatment);
        final Intent intent = getIntent();
        mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
        Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
        bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
        }
@Override
    protected void onResume() {
        super.onResume();
        //发送数据,应该在按钮监听中添加,这里没有设置按钮,就添加在此方法中。
   mGattCharateristics = mGattCharacteristics.get(3).get(8);
                Log.e("======",mGattCharateristics.getUuid().toString());
                final int charaProp =mGattCharateristics.getProperties();
                byte data[] = {(byte)0x33, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00};
                //final int charaProp =CharacteristicService.getProperties();
                if ((charaProp|BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
                    if (mGattCharateristics != null) {
                        Log.d("NotifyCharacteristic:", mGattCharateristics.toString());
                        mBluetoothLeService.setCharacteristicNotification(
                                mGattCharateristics, true);
                    }
                    mGattCharateristics.setValue(data);//随便举个数据
                    mBluetoothLeService.writeCharacteristic(mGattCharateristics);//写命令到设备,
                    Log.e("++++++","数据发送成功");
                }
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(mGattUpdateReceiver);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
    private IntentFilter makeGattUpdateIntentFilter() {
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
        intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
        return intentFilter;
    }

4、android全局变量设置
目的:用于获取的蓝牙BluetoothGattCharacteristic在activity之间传递,否则一个activity销毁后,另一个activity无法获取。
(1)、在AndroidManifest文件中配置全局变量。

<application
        android:allowBackup="true"
        android:name=".BluetoothGattBean"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            intent-filter>
        activity>
    application>

(2)、创建全局变量类

import android.app.Application;
import android.bluetooth.BluetoothGattCharacteristic;

import java.util.ArrayList;

/**
 * Created by lenovo on 2016/12/20.
 */

public class BluetoothGattBean extends Application {
    private ArrayList> bluetoothGattCharacteristicList;
    public void setBluetoothGattCharacteristicList(ArrayList> bluetoothGattCharacteristicList) {
        this.bluetoothGattCharacteristicList = bluetoothGattCharacteristicList;
    }

    public ArrayList> getBluetoothGattCharacteristicList() {
        return bluetoothGattCharacteristicList;
    }
}

(3)、向全局变量中保存广播接收者获取的数据

btn.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
 final BluetoothGattBean bluetoothGattBean= (BluetoothGattBean)getApplication();
              bluetoothGattBean.setBluetoothGattCharacteristicList(mGattCharacteristics);
                Intent bleIntent = new Intent(DeviceControlActivity.this,
                        BleCommunicationActivity.class);
                  }
                        });

(4)、获取上一个activity保存的全局变量数据用于读写操作。

 btn.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                value=0;
                intensity_value.setText("0");
                final BluetoothGattBean bluetoothGattBean= (BluetoothGattBean)getApplication();
                mGattCharacteristics=bluetoothGattBean.getBluetoothGattCharacteristicList();
                mCharacteristic = mGattCharacteristics.get(3).get(8);
                Log.e("获取的BluetoothGattCharacteristic为:",mCharacteristic)
        });

5、倒计时

package utils;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextView;

public class TimerTextView extends TextView implements Runnable {
    public static String Ltime = null;

    public TimerTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

    private long mmin, msecond;
    private boolean run = false;

    public void setTimes(long[] times) {
        mmin = times[0];
        msecond = times[1];

    }

    private void ComputeTime() {
        msecond--;
        if (msecond < 0) {
            mmin--;
            msecond = 59;
        }
    }

    public boolean isRun() {
        return run;
    }

    public void beginRun() {
        this.run = true;
        run();
    }

    public void stopRun() {
        this.run = false;
    }

//多线程,时间按mm:ss格式显示
    @Override
    public void run() {
        if (run) {
            ComputeTime();
            if (mmin>9&&msecond>9) {
                String strTime = mmin + ":" + msecond;
                this.setText(strTime);
            }else if(mmin>9&&msecond<10){
                String strTime = mmin + ":0"+ msecond;
                this.setText(strTime);
            }else if(mmin<10&&msecond>9) {
                String strTime = "0"+mmin + ":"+ msecond;
                this.setText(strTime);
            }else if(mmin<10&&msecond<10){
                String strTime = "0"+mmin + ":0"+ msecond;
                this.setText(strTime);
            }
            postDelayed(this, 1000);
        } else {
            removeCallbacks(this);
        }
        if (mmin == 0 && msecond == 0) {
            stopRun();
        }
        // Log.e("shijian:",getRemainTime());
    }
//回去剩余时间的分和秒
    public long getRemainMinute() {
        return mmin;
    }
    public long getRemainSecond(){
        return msecond;
    }
}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bg"
    android:orientation="vertical">
 <utils.TimerTextView
            android:id="@+id/treattime"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="30:00"
            android:gravity="center"
            android:textSize="52sp"
            android:textColor="#1987C9"
            />
            LinearLayout>

6、不同分辨率手机界面适配
转载:http://blog.csdn.net/lmj623565791/article/details/46695347;
注:有Navigation bar的手机需要获取手机实际分辨率(减去navigation bar占用的尺寸)后再编写一套value布局。

你可能感兴趣的:(android)