android 藍(lán)牙開(kāi)發(fā)

藍(lán)牙知識(shí)了解:

每個(gè)手機(jī)如果有藍(lán)牙的話,可以通過(guò)藍(lán)牙掃描到你手機(jī)的mac地址。

(1)、MAC地址:每個(gè)設(shè)備都有全球唯一的,根據(jù)此MAC地址判斷藍(lán)牙設(shè)備

(2)、藍(lán)牙傳輸數(shù)據(jù),通常一秒鐘會(huì)傳輸很多個(gè)包,每個(gè)包的數(shù)據(jù)情況如下:

此時(shí),這個(gè)包有11個(gè)字節(jié),0x55 是首碼,通常通過(guò)他來(lái)判斷一個(gè)包的開(kāi)始

SUM是驗(yàn)證碼,會(huì)有一套公式來(lái)計(jì)算,判斷當(dāng)前包是不是一個(gè)有效的完整的包

中間的即是數(shù)據(jù),然后硬件方面會(huì)給我們一套計(jì)算公式,可以以此獲取我們要的數(shù)據(jù)。

當(dāng)然每個(gè)硬件的包的數(shù)據(jù)大小都是不同的,有的可能有21個(gè)字節(jié),每個(gè)硬件的數(shù)據(jù)的計(jì)算方式也不想同.

代碼實(shí)現(xiàn):

一共就三部分,因?yàn)榇a篇幅可能較大,不適合一段段代碼講解,直接貼出整個(gè)代碼。所有的解釋都在注釋當(dāng)中。

一:MainActivity

  public class MainActivity extends Activity {

      private BluetoothService mBluetoothService; //自定義藍(lán)牙服務(wù)類
      private BluetoothAdapter mBluetoothAdapter;
      private String mConnectedDeviceName = null; //連接設(shè)備的名稱

      //默認(rèn)是1,因?yàn)槌绦騿?dòng)時(shí)首先會(huì)連接一個(gè)藍(lán)牙
      private int current_pos = 1;

      //hanlder消息標(biāo)識(shí) message.what
      public static final int MESSAGE_STATE_CHANGE = 1; // 狀態(tài)改變
      public static final int MESSAGE_READ = 2;          // 讀取數(shù)據(jù)
      public static final int MESSAGE_WRITE = 3;         // 給硬件傳數(shù)據(jù),暫不需要,看具體需求
      public static final int MESSAGE_DEVICE_NAME = 4;  // 設(shè)備名字
      public static final int MESSAGE_TOAST = 5;         // Toast

  //傳感器 ,這里默認(rèn)同時(shí)需要和三個(gè)硬件連接,分別設(shè)置id 1,2,3進(jìn)行區(qū)分,demo中實(shí)際只用到 MAGIKARE_SENSOR_DOWN = 1
//可以根據(jù)情況自行添加刪除
public static final int MAGIKARE_SENSOR_UP = 2;
public static final int MAGIKARE_SENSOR_DOWN = 1;
public static final int MAGIKARE_SENSOR_CENTER = 3;

public static float[] m_receive_data_up;                    //傳感器的數(shù)據(jù)
public static float[] m_receive_data_down;                  //傳感器的數(shù)據(jù) ,demo中我們只需要這一個(gè),因?yàn)橹挥幸粋€(gè)硬件設(shè)備,
public static float[] m_receive_data_center;                //傳感器的數(shù)據(jù)

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //獲取藍(lán)牙適配器
    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

    // 1、判斷設(shè)備是否支持藍(lán)牙功能
    if (mBluetoothAdapter == null) {
        //設(shè)備不支持藍(lán)牙功能
        Toast.makeText(this, "當(dāng)前設(shè)備不支持藍(lán)牙功能!", Toast.LENGTH_SHORT).show();
        return;
    }

    // 2、打開(kāi)設(shè)備的藍(lán)牙功能
    if (!mBluetoothAdapter.isEnabled()) {
        boolean enable = mBluetoothAdapter.enable(); //返回值表示 是否成功打開(kāi)了藍(lán)牙設(shè)備
        if (enable) {
            Toast.makeText(this, "打開(kāi)藍(lán)牙功能成功!", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "打開(kāi)藍(lán)牙功能失敗,請(qǐng)到'系統(tǒng)設(shè)置'中手動(dòng)開(kāi)啟藍(lán)牙功能!", Toast.LENGTH_SHORT).show();
            return;
        }
    }


    // 3、創(chuàng)建自定義藍(lán)牙服務(wù)對(duì)象
    if (mBluetoothService == null) {
        mBluetoothService = new BluetoothService(MainActivity.this, mHandler);
    }
    if (mBluetoothService != null) {
        //根據(jù)MAC地址遠(yuǎn)程獲取一個(gè)藍(lán)牙設(shè)備,這里固定了,實(shí)際開(kāi)發(fā)中,需要?jiǎng)討B(tài)設(shè)置參數(shù)(MAC地址)
        BluetoothDevice sensor_down = mBluetoothAdapter.getRemoteDevice("20:16:06:15:78:76");
        if (sensor_down != null) {
            //成功獲取到遠(yuǎn)程藍(lán)牙設(shè)備(傳感器),這里默認(rèn)只連接MAGIKARE_SENSOR_DOWN = 1這個(gè)設(shè)備
            mBluetoothService.connect(sensor_down, MAGIKARE_SENSOR_DOWN);
        }
    }


}
private Handler mHandler = new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what){
            case MESSAGE_READ:
                try {
                    String str=msg.getData().getString("index");
                    int index=Integer.valueOf(str);
                    switch (index)
                    {
                        //獲取到藍(lán)牙傳輸過(guò)來(lái)的數(shù)據(jù)
                        case MAGIKARE_SENSOR_UP:
                            m_receive_data_up=msg.getData().getFloatArray("Data");
                            break;
                        //實(shí)際只用到這個(gè)case ,因?yàn)閐emo只連接了一個(gè)硬件設(shè)備
                        case MAGIKARE_SENSOR_DOWN:
                            m_receive_data_down=msg.getData().getFloatArray("Data");
                            break;
                        case MAGIKARE_SENSOR_CENTER:
                            m_receive_data_center=msg.getData().getFloatArray("Data");
                            break;

                    }
                } catch (Exception e) {
                    // TODO: handle exception
                }
                break;
            case MESSAGE_STATE_CHANGE:
                //連接狀態(tài)
                switch (msg.arg1) {
                    case BluetoothService.STATE_CONNECTED:
                        break;
                    case BluetoothService.STATE_CONNECTING:
                        break;
                    case BluetoothService.STATE_LISTEN:
                        break;
                    case BluetoothService.STATE_NONE:
                        break;
                }
                break;
            case MESSAGE_DEVICE_NAME:
                mConnectedDeviceName = msg.getData().getString("device_name");
                Log.i("bluetooth","成功連接到:"+mConnectedDeviceName);
                Toast.makeText(getApplicationContext(),"成功連接到設(shè)備" + mConnectedDeviceName,Toast.LENGTH_SHORT).show();

                break;
            case MESSAGE_TOAST:
                int index=msg.getData().getInt("device_id");
                Toast.makeText(getApplicationContext(),msg.getData().getString("toast"), Toast.LENGTH_SHORT).show();
                //當(dāng)失去設(shè)備或者不能連接設(shè)備時(shí),重新連接
                Log.d("Magikare","當(dāng)失去設(shè)備或者不能連接設(shè)備時(shí),重新連接");

       //重新連接硬件設(shè)備
               if(mBluetoothService!=null)
                {
                    switch (index) {
                        case MAGIKARE_SENSOR_DOWN:
          //根據(jù)你的硬件的MAC地址寫參數(shù),每一個(gè)硬件設(shè)備都有一個(gè)MAC地址,此方法是根據(jù)MAC地址得到藍(lán)牙設(shè)備
                            BluetoothDevice sensor_down = mBluetoothAdapter.getRemoteDevice("20:16:06:15:78:76");
                            if (sensor_down != null)
                                mBluetoothService.connect(sensor_down, MAGIKARE_SENSOR_DOWN);
                            break;
                        case MAGIKARE_SENSOR_UP:
                            BluetoothDevice sensor_up = mBluetoothAdapter.getRemoteDevice("");  //參數(shù)寫你這個(gè)設(shè)備的MAC碼
                            if (sensor_up != null)
                                mBluetoothService.connect(sensor_up, MAGIKARE_SENSOR_UP);
                            break;
                        case MAGIKARE_SENSOR_CENTER:
                            BluetoothDevice center = mBluetoothAdapter.getRemoteDevice("");    //參數(shù)寫你這個(gè)設(shè)備的MAC碼
                            if (center != null)
                                mBluetoothService.connect(center, MAGIKARE_SENSOR_CENTER);
                            break;
                    }
                }
                break;
        }
        return false;
    }
});

public synchronized void onResume() {
    super.onResume();

    if (mBluetoothService != null) {
        if (mBluetoothService.getState() == BluetoothService.STATE_NONE) {
            mBluetoothService.start();
        }
    }
}

@Override
public void onDestroy() {
    super.onDestroy();
    if (mBluetoothService != null) mBluetoothService.stop();
}

      // 硬件通過(guò)藍(lán)牙傳輸?shù)腷yte類型已經(jīng)轉(zhuǎn)換為float類型,并且通過(guò)handler傳輸?shù)?m_receive_data_down[]數(shù)組中,一下操作是獲取這個(gè)數(shù)據(jù),根據(jù)個(gè)人情況使用
      //獲取角度
      public float[] GetAngle(int index)
      {
          float[] angles=new float[3];
          if(m_receive_data_up==null
                  ||m_receive_data_down==null
                )
          {
              return angles;
          }
          switch (index)
          {
              case  MAGIKARE_SENSOR_DOWN:
                  angles[0]=m_receive_data_down[6];
                  angles[1]=m_receive_data_down[7];
                  angles[2]=m_receive_data_down[8];
                  break;
              case MAGIKARE_SENSOR_UP:
                  angles[0]=m_receive_data_up[6];
                  angles[1]=m_receive_data_up[7];
                  angles[2]=m_receive_data_up[8];
                 Log.d("安卓 Up 角度",angles[0]+","+angles[1]+","+angles[2]);
                  break;
          }
            return angles;
      }

//獲取角速度
public static float[] GetAngleSpeed(int index){
    float [] anglespeed=new float[3];
    if(m_receive_data_down==null)
    {
        return anglespeed;
    }
    switch (index)
    {
        case MAGIKARE_SENSOR_DOWN:

            anglespeed[0]=m_receive_data_down[3];
            anglespeed[1]=m_receive_data_down[4];
            anglespeed[2]=m_receive_data_down[5];
            break;
        case MAGIKARE_SENSOR_UP:
            anglespeed[0]=m_receive_data_up[3];
            anglespeed[1]=m_receive_data_up[4];
            anglespeed[2]=m_receive_data_up[5];
            break;
    }
    return  anglespeed;
}

public float[] GetQuaternion(int index)
{
    float[] quaternion=new float[4];

    if(m_receive_data_down==null)
    {
        return quaternion;
    }
    switch (index)
    {
        case  MAGIKARE_SENSOR_DOWN:
            quaternion[0]=m_receive_data_down[23];
            quaternion[1]=m_receive_data_down[24];
            quaternion[2]=m_receive_data_down[25];
            quaternion[3]=m_receive_data_down[26];
            Log.i("saveinfo","m_receive_data_down23"+m_receive_data_down[23]);
            Log.i("saveinfo","m_receive_data_down24"+m_receive_data_down[24]);
            Log.i("saveinfo","m_receive_data_down25"+m_receive_data_down[25]);
            Log.i("saveinfo","m_receive_data_down26"+m_receive_data_down[26]);
            break;
        case MAGIKARE_SENSOR_UP:
            quaternion[0]=m_receive_data_up[23];
            quaternion[1]=m_receive_data_up[24];
            quaternion[2]=m_receive_data_up[25];
            quaternion[3]=m_receive_data_up[26];
            break;
        case MAGIKARE_SENSOR_CENTER:
            quaternion[0]=m_receive_data_center[23];
            quaternion[1]=m_receive_data_center[24];
            quaternion[2]=m_receive_data_center[25];
            quaternion[3]=m_receive_data_center[26];
    }
    return  quaternion;
}

}

二、BluetoothService

  public class BluetoothService {
      private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
      private Context context;
      //藍(lán)牙適配器
      private BluetoothAdapter mAdapter;
      private Handler mHandler;

      //當(dāng)前傳感器設(shè)備的個(gè)數(shù),即要開(kāi)啟的線程個(gè)數(shù),用于設(shè)置線程數(shù)組的大小
      //這里默認(rèn)為1,因?yàn)槲覀兡壳爸恍枰鸵粋€(gè)傳感器連接, 比如:你要連接兩個(gè)硬件設(shè)備,那就設(shè)置值為2,這樣就會(huì)開(kāi)啟兩個(gè)線程,分別去執(zhí)行想要操作
      public static final int  SENSEOR_NUM=1;

      private AcceptThread mAcceptThread;// 請(qǐng)求連接的監(jiān)聽(tīng)進(jìn)程
      private ConnectThread mConnectThread;// 連接一個(gè)設(shè)備的進(jìn)程
      public ConnectedThread[] mConnectedThread=new ConnectedThread[SENSEOR_NUM];// 已經(jīng)連接之后的管理進(jìn)程
      private int mState;// 當(dāng)前狀態(tài)

      // 指明連接狀態(tài)的常量
      public static final int STATE_NONE = 0;         //沒(méi)有連接
      public static final int STATE_LISTEN = 1;       //等待連接
      public static final int STATE_CONNECTING = 2;  //正在連接
      public static final int STATE_CONNECTED = 3;   //已經(jīng)連接

      public BluetoothService(Context context, Handler mHandler) {
      this.context = context;
      this.mHandler = mHandler;
      mAdapter = BluetoothAdapter.getDefaultAdapter();//獲取藍(lán)牙適配器
      mState = STATE_NONE ; //當(dāng)前連接狀態(tài):未連接
      }

      // 參數(shù) index 是 硬件設(shè)備的id ,隨便設(shè)的,目的在于當(dāng) 同時(shí)連接多個(gè)硬件設(shè)備的時(shí)候,根據(jù)此id進(jìn)行區(qū)分
      public synchronized void connect(BluetoothDevice device, int index) {

      //連接一個(gè)藍(lán)牙時(shí),將該設(shè)備 的藍(lán)牙連接線程關(guān)閉,如果有的話
      //demo  就只有一個(gè)硬件設(shè)備,默認(rèn)該設(shè)備id 取值index=1;
      if (mConnectedThread[index-1] != null) {
            mConnectedThread[index-1].cancel();
            mConnectedThread[index-1]=null;
       }
          mConnectThread=new ConnectThread(device,index);
          mConnectThread.start();
          setState(STATE_CONNECTING);
      }

      private class ConnectThread extends Thread{
          private final BluetoothSocket mmSocket;
          private final BluetoothDevice mmDevice;
          private int index;
          public ConnectThread(BluetoothDevice device,int index) {
              mmDevice = device;
              this.index=index;
              BluetoothSocket tmp = null;
          try {
                tmp = device.createRfcommSocketToServiceRecord(MY_UUID);// Get a BluetoothSocket for a connection with the given BluetoothDevice
          }
            catch (IOException e) {}
            mmSocket = tmp;
        }

      public void run() {

        setName("ConnectThread");
        //當(dāng)連接成功,取消藍(lán)牙適配器搜索藍(lán)牙設(shè)備的操作,因?yàn)樗阉鞑僮鞣浅:臅r(shí)
        mAdapter.cancelDiscovery();// Always cancel discovery because it will slow down a connection

        try {
            mmSocket.connect();// This is a blocking call and will only return on a successful connection or an exception
        }
        catch (IOException e) {
            connectionFailed(this.index);
            try {
                mmSocket.close();
            } catch (IOException e2) {}

            BluetoothService.this.start();// 引用來(lái)說(shuō)明要調(diào)用的是外部類的方法 run
            return;
        }

        synchronized (BluetoothService.this) {// Reset the ConnectThread because we're done
            mConnectThread = null;
        }
        connected(mmSocket, mmDevice,index);// Start the connected thread
    }

    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) {
        }
    }
}

class ConnectedThread extends Thread{
    private BluetoothSocket mmSocket;
    private InputStream mmInStream;
    private OutputStream mmOutStream;
    private int index;
    private Queue<Byte> queueBuffer = new LinkedList<Byte>();
    private byte[] packBuffer = new byte[11];


    //構(gòu)造方法
    public ConnectedThread(BluetoothSocket socket,int index) {
        mmSocket = socket;
        InputStream tmpIn = null;
        OutputStream tmpOut = null;
        this.index=index;
        // Get the BluetoothSocket input and output streams
        try {
            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();
        } catch (IOException e) {}

        mmInStream = tmpIn;
        mmOutStream = tmpOut;
    }

    // 數(shù)組大小看你的數(shù)據(jù)需求,這里存的是你處理藍(lán)牙傳輸來(lái)的字節(jié)數(shù)據(jù)之后實(shí)際要用到的數(shù)據(jù)
    private float [] fData=new float[31];

    @Override
    public void run() {
        byte[] tempInputBuffer = new byte[1024];
        int acceptedLen = 0; //記錄每次讀取數(shù)據(jù)的數(shù)據(jù)長(zhǎng)度
        byte sHead;
        long lLastTime = System.currentTimeMillis(); //獲取開(kāi)始時(shí)間
        while(true){
            try {
                acceptedLen = mmInStream.read(tempInputBuffer);//返回接收的長(zhǎng)度
                //從緩沖區(qū)中讀取數(shù)據(jù)
                for (int i = 0; i < acceptedLen; i++) {
                    queueBuffer.add(tempInputBuffer[i]);
                }
                // 這里需要按個(gè)人硬件數(shù)據(jù)的情況自行修改了
                // 如果你的硬件藍(lán)牙傳輸 一個(gè)包有11個(gè)字節(jié),那queueBuffer.size()>=11
                // 如果你的硬件藍(lán)牙傳輸 一個(gè)包有21個(gè)字節(jié),那queueBuffer.size()>=21
                while (queueBuffer.size()>=11){
                    //返回隊(duì)首并刪除,判斷隊(duì)首是不是0x55,如果不是,說(shuō)明不是一個(gè)包的數(shù)據(jù),跳過(guò),
                    //注意這里的0x55是你的包的首字節(jié)
                    if (queueBuffer.poll()!=0x55)
                        continue;
                    // 進(jìn)入到這里,說(shuō)明得到一個(gè)包的數(shù)據(jù)了,然后就要根據(jù)個(gè)人硬件的數(shù)據(jù)情況,將byte類型的數(shù)據(jù)轉(zhuǎn)換為float類型的數(shù)據(jù)
                  sHead = queueBuffer.poll(); //返回隊(duì)首并刪除
    // 現(xiàn)在得到的就是你數(shù)據(jù)部分了,如果有9位字節(jié)代表數(shù)據(jù),j<9 ,如果有19位字節(jié)代表數(shù)據(jù),j<19
    //將字節(jié)數(shù)組存到packBuffer[]數(shù)據(jù)中,用于byte-->float數(shù)據(jù)的轉(zhuǎn)換
                    for (int j = 0; j < 9; j++) {
                        packBuffer[j] = queueBuffer.poll();
                    }
                    switch (sHead) {//
                        case 0x52://角速度
                            fData[3] = ((((short) packBuffer[1]) << 8) | ((short) packBuffer[0] & 0xff)) / 32768.0f * 2000;
                            fData[4] = ((((short) packBuffer[3]) << 8) | ((short) packBuffer[2] & 0xff)) / 32768.0f * 2000;
                            fData[5] = ((((short) packBuffer[5]) << 8) | ((short) packBuffer[4] & 0xff)) / 32768.0f * 2000;
                            fData[17] = ((((short) packBuffer[7]) << 8) | ((short) packBuffer[6] & 0xff)) / 100.0f;
                            break;
                        case 0x53://角度
                            fData[6] = ((((short) packBuffer[1]) << 8) | ((short) packBuffer[0] & 0xff)) / 32768.0f * 180;
                            fData[7] = ((((short) packBuffer[3]) << 8) | ((short) packBuffer[2] & 0xff)) / 32768.0f * 180;
                            fData[8] = ((((short) packBuffer[5]) << 8) | ((short) packBuffer[4] & 0xff)) / 32768.0f * 180;
                            fData[17] = ((((short) packBuffer[7]) << 8) | ((short) packBuffer[6] & 0xff)) / 100.0f;
                            break;
                        case 0x59://四元數(shù)
                            fData[23] = ((((short) packBuffer[1]) << 8) | ((short) packBuffer[0] & 0xff)) / 32768.0f;
                            fData[24] = ((((short) packBuffer[3]) << 8) | ((short) packBuffer[2] & 0xff))/32768.0f;
                            fData[25] = ((((short) packBuffer[5]) << 8) | ((short) packBuffer[4] & 0xff))/32768.0f;
                            fData[26] = ((((short) packBuffer[7]) << 8) | ((short) packBuffer[6] & 0xff))/32768.0f;
                            break;
                    }
                }
                long lTimeNow = System.currentTimeMillis(); // 獲取收據(jù)轉(zhuǎn)換之后的時(shí)間
                // 如果數(shù)據(jù)處理后的時(shí)間  與 接收到數(shù)據(jù)的時(shí)間 的時(shí)間差>80 則發(fā)送消息傳輸數(shù)據(jù),
                // 這個(gè)時(shí)間需要看你硬件一秒鐘發(fā)送的包的個(gè)數(shù)
                if (lTimeNow - lLastTime > 80) {
                    lLastTime = lTimeNow;
                    Message msg = mHandler.obtainMessage(MainActivity.MESSAGE_READ);
                    Bundle bundle = new Bundle();
                    bundle.putString("index",String.valueOf(this.index));
                    bundle.putFloatArray("Data", fData);
                    msg.setData(bundle);
                    mHandler.sendMessage(msg);
                }
            } catch (IOException e) {
                connectionLost(this.index);
                e.printStackTrace();
            }
        }
    }
    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) {}
    }
}
//連接失敗
private void connectionFailed(int index) {
    setState(STATE_LISTEN);
    // Send a failure message back to the Activity
    Message msg = mHandler.obtainMessage(MainActivity.MESSAGE_TOAST);
    Bundle bundle = new Bundle();
    bundle.putString("toast", "未能連接設(shè)備"+index);
    bundle.putInt("device_id",index);
    msg.setData(bundle);
    mHandler.sendMessage(msg);
}
// 連接丟失
private void connectionLost(int index) {
    setState(STATE_LISTEN);
    Message msg = mHandler.obtainMessage(MainActivity.MESSAGE_TOAST);
    Bundle bundle = new Bundle();
    bundle.putString("toast", "設(shè)備丟失"+index);
    bundle.putInt("device_id",index);
    msg.setData(bundle);
    mHandler.sendMessage(msg);
}


//用于 藍(lán)牙連接的Activity onResume()方法
public synchronized void start() {
    // Cancel any thread attempting to make a connection
    if (mConnectThread != null) {
        mConnectThread.cancel();
        mConnectThread = null;
    }

    if (mAcceptThread == null) {
        mAcceptThread = new AcceptThread();
        mAcceptThread.start();
    }
    setState(STATE_LISTEN);
}

public synchronized void connected(BluetoothSocket socket,BluetoothDevice device,int index) {
    Log.d("MAGIKARE","連接到線程"+index);
    // Cancel the thread that completed the connection
    if (mConnectThread != null) {
        mConnectThread.cancel();
        mConnectThread = null;
    }
    // Cancel the accept thread because we only want to connect to one device
    if (mAcceptThread != null) {
        mAcceptThread.cancel();
        mAcceptThread = null;
    }

    // Start the thread to manage the connection and perform transmissions
    mConnectedThread[index-1] = new ConnectedThread(socket,index);

    mConnectedThread[index-1].start();

    // Send the name of the connected device back to the UI Activity
    Message msg = mHandler.obtainMessage(MainActivity.MESSAGE_DEVICE_NAME);
    Bundle bundle = new Bundle();
    bundle.putString("device_name", device.getName()+" "+index);

    msg.setData(bundle);
    mHandler.sendMessage(msg);

    setState(STATE_CONNECTED);
}

private synchronized void setState(int state) {
    mState = state;
    // Give the new state to the Handler so the UI Activity can update
    mHandler.obtainMessage(MainActivity.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}

private class AcceptThread extends Thread {
    // The local server socket
    private final BluetoothServerSocket mmServerSocket;
    //private int index;
    public AcceptThread() {
        BluetoothServerSocket tmp = null;
        // this.index=index;
        // Create a new listening server socket
        try {
            tmp = mAdapter.listenUsingRfcommWithServiceRecord("BluetoothData", MY_UUID);
        }
        catch (IOException e) {}
        mmServerSocket = tmp;
    }

    public void run() {
        new Thread(new Runnable() {
            @Override
            public void run() {

            }
        }).start();

    }

    public void cancel() {

        try {
            if(mmServerSocket!=null) {
                mmServerSocket.close();
            }
        }
        catch (IOException e) {}
    }
}
public synchronized int getState() {
    return mState;
}


public synchronized void stop() {
    if (mConnectedThread != null) {
        for(int i=0;i<mConnectedThread.length;i++)
        {
                mConnectedThread[i].cancel();
        }
        mConnectedThread = null;
    }
    if (mAcceptThread != null) {
        mAcceptThread.cancel();
        mAcceptThread = null;
    }
    setState(STATE_NONE);
}

}

三、自定義即時(shí)變化的折線圖:

public class MyView extends View {
      /*http://www.cnblogs.com/aibuli/p/950c34f2bc0d02cbd290dd6a8339d42a.html*/
      //坐標(biāo)軸原點(diǎn)的位置
      private int xPoint=60;
      private int yPoint=260;
    //刻度長(zhǎng)度
    private int xScale=8;  //8個(gè)單位構(gòu)成一個(gè)刻度
    private int yScale=40;
    //x與y坐標(biāo)軸的長(zhǎng)度
    private int xLength=580;
    private int yLength=480;
    private int MaxDataSize=xLength/xScale;   //橫坐標(biāo)  最多可繪制的點(diǎn)
    private List<Float> data=new ArrayList<Float>();   //存放 縱坐標(biāo) 所描繪的點(diǎn)
    private String[] yLabel=new String[yLength/yScale];  //Y軸的刻度上顯示字的集合

    private Handler mh=new Handler(){
        public void handleMessage(android.os.Message msg) {
            if(msg.what==0){                //判斷接受消息類型
                MyView.this.invalidate();  //刷新View
            }
        };
    };
public MyView(Context context, AttributeSet attrs) {
    super(context, attrs);
    for (int i = 0; i <yLabel.length; i++) {
        yLabel[i]=(i+1)+"M/s";
    }
    new Thread(new Runnable() {
        @Override
        public void run() {
            while(true){     //在線程中不斷往集合中增加數(shù)據(jù)
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(data.size()>MaxDataSize){  //判斷集合的長(zhǎng)度是否大于最大繪制長(zhǎng)度
                    data.remove(0);  //刪除頭數(shù)據(jù)
                }
                // 這里得到藍(lán)牙設(shè)備得到的數(shù)據(jù)
                float[] floats = MainActivity.GetAngleSpeed(1);
                data.add(floats[0]);
                mh.sendEmptyMessage(0);   //發(fā)送空消息通知刷新
            }
        }
    }).start();
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Paint paint=new Paint();
    paint.setStyle(Paint.Style.STROKE);
    paint.setAntiAlias(true);
    paint.setColor(Color.RED);
    //繪制Y軸
    canvas.drawLine(xPoint, yPoint-yLength, xPoint, yPoint, paint);
    //繪制Y軸左右兩邊的箭頭
    canvas.drawLine(xPoint, yPoint-yLength, xPoint-3,yPoint-yLength+6, paint);
    canvas.drawLine(xPoint, yPoint-yLength, xPoint+3,yPoint-yLength+6, paint);
    //Y軸上的刻度與文字
    for (int i = 0; i * yScale< yLength; i++) {
        canvas.drawLine(xPoint, yPoint-i*yScale, xPoint+5, yPoint-i*yScale, paint);  //刻度
        canvas.drawText(yLabel[i], xPoint-50, yPoint-i*yScale, paint);//文字
    }
    //X軸
    canvas.drawLine(xPoint, yPoint, xPoint+xLength, yPoint, paint);
    //如果集合中有數(shù)據(jù)
    if(data.size()>1){
        for (int i = 1; i < data.size(); i++) {  //依次取出數(shù)據(jù)進(jìn)行繪制
            canvas.drawLine(xPoint+(i-1)*xScale, yPoint-data.get(i-1)*yScale, xPoint+i*xScale, yPoint-data.get(i)*yScale, paint);
        }
    }
  }}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容