原文: Android項目實戰(二十六):藍牙連接配接硬體裝置開發規範流程
前言:
最近接觸藍牙開發,主要是通過藍牙連接配接擷取傳感器硬體裝置的資料,并進行處理。
網上學習一番,現整理出一套比較标準的 操作流程代碼。
如果大家看得懂,将來隻需要改下 硬體裝置的MAC碼 和 改下對接收資料的處理 即可。 一切都是套路~~~
現在以一個小型項目需求來學習Android藍牙程式設計
需求: 通過藍牙擷取硬體資料,并顯示在一個随資料即時變化的動态折線圖中。
實作思路:
(1) 配對藍牙裝置
(2) 連接配接藍牙裝置 ,根據MAC位址,代碼中修改
(3) 接收資料
(4) 處理資料 ,根據硬體廠商提供給你的資料轉換公式,在BluetoothService類中 修改
(5) 傳資料給折線圖,展現實時變化
-----------------------------------------------------------------------
藍牙知識了解:
(1)、MAC位址:每個裝置都有全球唯一的,根據此MAC位址判斷藍牙裝置
(2)、藍牙傳輸資料,通常一秒鐘會傳輸很多個包,每個包的資料情況如下:
此時,這個包有11個位元組,0x55 是首碼,通常通過他來判斷一個包的開始
SUM是驗證碼,會有一套公式來計算,判斷目前包是不是一個有效的完整的包
中間的即是資料,然後硬體方面會給我們一套計算公式,可以以此擷取我們要的資料。
當然每個硬體的包的資料大小都是不同的,有的可能有21個位元組,每個硬體的資料的計算方式也不想同
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuYTO1ETM5UmZ0UTN0MGZ2AzN2UWM5AjNzUWZlBzNxAjZfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
代碼實作:
一共就三部分,因為代碼篇幅可能較大,不适合一段段代碼講解,直接貼出整個代碼。所有的解釋都在注釋當中。
其中:
(1)、紅色部分是需要大家根據個人硬體情況進行修改的
(2)、紫色部分是根據個人資料情況添加删除修改的。
一:MainActivity
public class MainActivity extends Activity {
private BluetoothService mBluetoothService; //自定義藍牙服務類
private BluetoothAdapter mBluetoothAdapter;
private String mConnectedDeviceName = null; //連接配接裝置的名稱
//預設是1,因為程式啟動時首先會連接配接一個藍牙
private int current_pos = 1;
//hanlder消息辨別 message.what
public static final int MESSAGE_STATE_CHANGE = 1; // 狀态改變
public static final int MESSAGE_READ = 2; // 讀取資料
public static final int MESSAGE_WRITE = 3; // 給硬體傳資料,暫不需要,看具體需求
public static final int MESSAGE_DEVICE_NAME = 4; // 裝置名字
public static final int MESSAGE_TOAST = 5; // Toast
//傳感器 ,這裡預設同時需要和三個硬體連接配接,分别設定id 1,2,3進行區分,demo中實際隻用到 MAGIKARE_SENSOR_DOWN = 1
//可以根據情況自行添加删除
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; //傳感器的資料
public static float[] m_receive_data_down; //傳感器的資料 ,demo中我們隻需要這一個,因為隻有一個硬體裝置,
public static float[] m_receive_data_center; //傳感器的資料
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//擷取藍牙擴充卡
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// 1、判斷裝置是否支援藍牙功能
if (mBluetoothAdapter == null) {
//裝置不支援藍牙功能
Toast.makeText(this, "目前裝置不支援藍牙功能!", Toast.LENGTH_SHORT).show();
return;
}
// 2、打開裝置的藍牙功能
if (!mBluetoothAdapter.isEnabled()) {
boolean enable = mBluetoothAdapter.enable(); //傳回值表示 是否成功打開了藍牙裝置
if (enable) {
Toast.makeText(this, "打開藍牙功能成功!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "打開藍牙功能失敗,請到'系統設定'中手動開啟藍牙功能!", Toast.LENGTH_SHORT).show();
return;
}
}
// 3、建立自定義藍牙服務對象
if (mBluetoothService == null) {
mBluetoothService = new BluetoothService(MainActivity.this, mHandler);
}
if (mBluetoothService != null) {
//根據MAC位址遠端擷取一個藍牙裝置,這裡固定了,實際開發中,需要動态設定參數(MAC位址)
BluetoothDevice sensor_down = mBluetoothAdapter.getRemoteDevice("20:16:06:15:78:76");
if (sensor_down != null) {
//成功擷取到遠端藍牙裝置(傳感器),這裡預設隻連接配接MAGIKARE_SENSOR_DOWN = 1這個裝置
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)
{
//擷取到藍牙傳輸過來的資料
case MAGIKARE_SENSOR_UP:
m_receive_data_up=msg.getData().getFloatArray("Data");
break;
//實際隻用到這個case ,因為demo隻連接配接了一個硬體裝置
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:
// 連接配接狀态
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(),"成功連接配接到裝置" + 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();
//當失去裝置或者不能連接配接裝置時,重新連接配接
Log.d("Magikare","當失去裝置或者不能連接配接裝置時,重新連接配接");
//重新連接配接硬體裝置
if(mBluetoothService!=null)
{
switch (index) {
case MAGIKARE_SENSOR_DOWN:
//根據你的硬體的MAC位址寫參數,每一個硬體裝置都有一個MAC位址,此方法是根據MAC位址得到藍牙裝置
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(""); //參數寫你這個裝置的MAC碼
if (sensor_up != null)
mBluetoothService.connect(sensor_up, MAGIKARE_SENSOR_UP);
break;
case MAGIKARE_SENSOR_CENTER:
BluetoothDevice center = mBluetoothAdapter.getRemoteDevice(""); //參數寫你這個裝置的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();
}
// 硬體通過藍牙傳輸的byte類型已經轉換為float類型,并且通過handler傳輸到 m_receive_data_down[]數組中,一下操作是擷取這個資料,根據個人情況使用
//擷取角度
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;
//藍牙擴充卡
private BluetoothAdapter mAdapter;
private Handler mHandler;
//目前傳感器裝置的個數,即要開啟的線程個數,用于設定線程數組的大小
//這裡預設為1,因為我們目前隻需要和一個傳感器連接配接, 比如:你要連接配接兩個硬體裝置,那就設定值為2,這樣就會開啟兩個線程,分别去執行想要操作
public static final int SENSEOR_NUM=1;
private AcceptThread mAcceptThread;// 請求連接配接的監聽程序
private ConnectThread mConnectThread;// 連接配接一個裝置的程序
public ConnectedThread[] mConnectedThread=new ConnectedThread[SENSEOR_NUM];// 已經連接配接之後的管理程序
private int mState;// 目前狀态
// 指明連接配接狀态的常量
public static final int STATE_NONE = 0; //沒有連接配接
public static final int STATE_LISTEN = 1; //等待連接配接
public static final int STATE_CONNECTING = 2; //正在連接配接
public static final int STATE_CONNECTED = 3; //已經連接配接
public BluetoothService(Context context, Handler mHandler) {
this.context = context;
this.mHandler = mHandler;
mAdapter = BluetoothAdapter.getDefaultAdapter();//擷取藍牙擴充卡
mState = STATE_NONE ; //目前連接配接狀态:未連接配接
}
// 參數 index 是 硬體裝置的id ,随便設的,目的在于當 同時連接配接多個硬體裝置的時候,根據此id進行區分
public synchronized void connect(BluetoothDevice device, int index) {
//連接配接一個藍牙時,将該裝置 的藍牙連接配接線程關閉,如果有的話
//demo 就隻有一個硬體裝置,預設該裝置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");
//當連接配接成功,取消藍牙擴充卡搜尋藍牙裝置的操作,因為搜尋操作非常耗時
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();// 引用來說明要調用的是外部類的方法 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];
//構造方法
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;
}
// 數組大小看你的資料需求,這裡存的是你處理藍牙傳輸來的位元組資料之後實際要用到的資料
private float [] fData=new float[31];
@Override
public void run() {
byte[] tempInputBuffer = new byte[1024];
int acceptedLen = 0; //記錄每次讀取資料的資料長度
byte sHead;
long lLastTime = System.currentTimeMillis(); //擷取開始時間
while(true){
try {
acceptedLen = mmInStream.read(tempInputBuffer);//傳回接收的長度
//從緩沖區中讀取資料
for (int i = 0; i < acceptedLen; i++) {
queueBuffer.add(tempInputBuffer[i]);
}
// 這裡需要按個人硬體資料的情況自行修改了
// 如果你的硬體藍牙傳輸 一個包有11個位元組,那queueBuffer.size()>=11
// 如果你的硬體藍牙傳輸 一個包有21個位元組,那queueBuffer.size()>=21
while (queueBuffer.size()>=11){
//傳回隊首并删除,判斷隊首是不是0x55,如果不是,說明不是一個包的資料,跳過,
//注意這裡的0x55是你的包的首位元組
if (queueBuffer.poll()!=0x55)
continue;
// 進入到這裡,說明得到一個包的資料了,然後就要根據個人硬體的資料情況,将byte類型的資料轉換為float類型的資料
sHead = queueBuffer.poll(); //傳回隊首并删除
// 現在得到的就是你資料部分了,如果有9位位元組代表資料,j<9 ,如果有19位位元組代表資料,j<19
//将位元組數組存到packBuffer[]資料中,用于byte-->float資料的轉換
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://四元數
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(); // 擷取收據轉換之後的時間
// 如果資料處理後的時間 與 接收到資料的時間 的時間差>80 則發送消息傳輸資料,
// 這個時間需要看你硬體一秒鐘發送的包的個數
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", "未能連接配接裝置"+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", "裝置丢失"+index);
bundle.putInt("device_id",index);
msg.setData(bundle);
mHandler.sendMessage(msg);
}
//用于 藍牙連接配接的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);
}
}
三、自定義即時變化的折線圖:
public class MyView extends View {
/*http://www.cnblogs.com/aibuli/p/950c34f2bc0d02cbd290dd6a8339d42a.html*/
//坐标軸原點的位置
private int xPoint=60;
private int yPoint=260;
//刻度長度
private int xScale=8; //8個機關構成一個刻度
private int yScale=40;
//x與y坐标軸的長度
private int xLength=580;
private int yLength=480;
private int MaxDataSize=xLength/xScale; //橫坐标 最多可繪制的點
private List<Float> data=new ArrayList<Float>(); //存放 縱坐标 所描繪的點
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){ //線上程中不斷往集合中增加資料
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(data.size()>MaxDataSize){ //判斷集合的長度是否大于最大繪制長度
data.remove(0); //删除頭資料
}
// 這裡得到藍牙裝置得到的資料
float[] floats = MainActivity.GetAngleSpeed(1);
data.add(floats[0]);
mh.sendEmptyMessage(0); //發送空消息通知重新整理
}
}
}).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);
//如果集合中有資料
if(data.size()>1){
for (int i = 1; i < data.size(); i++) { //依次取出資料進行繪制
canvas.drawLine(xPoint+(i-1)*xScale, yPoint-data.get(i-1)*yScale, xPoint+i*xScale, yPoint-data.get(i)*yScale, paint);
}
}
}
}
相關知識:
淺談Bluetooth藍牙開發有問題歡迎留言交流!