藍(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);
}
}
}}