仿小米运动的蓝牙开源项目(附详细实现说明+源码)
2017-05-18 16:52
239 查看
托瓦兹 莱纳斯 是一个天才.
这个项目主要以蓝牙和自己diy的手环连接,可以记录测试数据,绘制成折线坐标图之类的功能.
项目结构很简单
6个类,其中AcceptThread,ConnectedThread,为线程工具类.只有两个界面活动类,分别是MainActivity,DataActivity;然后ViewHandler 是为了实现异步改变UI , CircleTextView是我自定义的TextView.
大概思路是 通过 AcceptThread 连接 蓝牙设备 ,ConnectedThread 建立流通信.然后收到信息后 用本地广播 LocalBroadcast 进行本地全局 , 再触发 handler 来更改ui .
主界面那个转圈的小球用的是动画 animation 为了保证以某一圆心 旋转,所以其实 旋转的是一个 framlayout.而圆点 是一个位于framlayout左中间的button哈哈.
关于曲线坐标图,我用了一个挺不错的框架.https://github.com/QQ951127336/SmallChart
项目源码
https://github.com/QQ951127336/Bluetooth-Assistant
注:android5.0后小变化
需添加权限
android.permission.ACCESS_COARSE_LOCATION
贴代码了
MainActivity
DataActivity
AcceptThread
ConnectedThread
ViewHandler
这个项目主要以蓝牙和自己diy的手环连接,可以记录测试数据,绘制成折线坐标图之类的功能.
项目结构很简单
6个类,其中AcceptThread,ConnectedThread,为线程工具类.只有两个界面活动类,分别是MainActivity,DataActivity;然后ViewHandler 是为了实现异步改变UI , CircleTextView是我自定义的TextView.
大概思路是 通过 AcceptThread 连接 蓝牙设备 ,ConnectedThread 建立流通信.然后收到信息后 用本地广播 LocalBroadcast 进行本地全局 , 再触发 handler 来更改ui .
主界面那个转圈的小球用的是动画 animation 为了保证以某一圆心 旋转,所以其实 旋转的是一个 framlayout.而圆点 是一个位于framlayout左中间的button哈哈.
关于曲线坐标图,我用了一个挺不错的框架.https://github.com/QQ951127336/SmallChart
项目源码
https://github.com/QQ951127336/Bluetooth-Assistant
注:android5.0后小变化
需添加权限
android.permission.ACCESS_COARSE_LOCATION
贴代码了
MainActivity
package com.tree.max.assistant; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Handler; import android.os.Message; import android.support.design.widget.Snackbar; import android.support.v4.content.LocalBroadcastManager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.ContentFrameLayout; import android.util.Log; import android.view.View; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import java.util.Set; public class MainActivity extends AppCompatActivity { final int NUMBER_CHANGED=1;//用来判断是否接到数据 TextView numberView; final String name = "HC-06";//设备名字 LinearLayout liitleButton ; FrameLayout contentFrameLayout ; Button startBuletooth,connectBlueTooth,dataButton; BluetoothAdapter bluetoothAdapter; ArrayAdapter<String> arrayAdapter ; ListView listView; BroadcastReceiver receiver; String number = "0"; LocalReceiver localReceiver; int i = 0; final Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case NUMBER_CHANGED: numberView.setText(number);//更改UI数据 break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main_new); init(); circle(); // arrayAdapter = new ArrayAdapter<String>(MainActivity.this,R.layout.list_item); listView.setAdapter(arrayAdapter); bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();//蓝牙适配器 if (bluetoothAdapter == null) { Snackbar.make(startBuletooth,"You have no bluetooth",Snackbar.LENGTH_INDEFINITE).show(); } receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { BluetoothDevice device =intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // arrayAdapter.add(device.getName()+ " : "+device.getAddress()); if (device.getName().equals(name)) { findDevice(device); Log.e("device",device.getName()); } } } }; IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);//找到设备发出广播 registerReceiver(receiver,intentFilter); } @Override public void onResume() { super.onResume(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("LOCAL_BROAD_EV_PROGRESS");//本地UI线程广播 localReceiver= new LocalReceiver(); LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this); localBroadcastManager.registerReceiver(localReceiver,intentFilter); } @Override public void onPause() { super.onPause(); } public void findDevice(BluetoothDevice device) { if (device.getName().equals(name)) { Log.e("device","find"); if (bluetoothAdapter.isDiscovering()) { bluetoothAdapter.cancelDiscovery(); } AcceptThread acceptThread = new AcceptThread(device,MainActivity.this); acceptThread.start(); } } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(receiver); unregisterReceiver(localReceiver); } private void init(){ numberView = (TextView)findViewById(R.id.numberTextView); liitleButton = (LinearLayout) findViewById(R.id.little_circle); c 122d2 ontentFrameLayout = (FrameLayout) findViewById(R.id.contentLayout); startBuletooth = (Button)findViewById(R.id.startBluetooth); connectBlueTooth = (Button)findViewById(R.id.connectBluetooth); dataButton = (Button)findViewById(R.id.dataButton); listView = (ListView)findViewById(R.id.listView); ClickListener clickListener = new ClickListener(); startBuletooth.setOnClickListener(clickListener); connectBlueTooth.setOnClickListener(clickListener); dataButton.setOnClickListener(clickListener); } public void circle() { Animation sanimation = AnimationUtils.loadAnimation(MainActivity.this,R.anim.circle_anim); liitleButton.startAnimation(sanimation); sanimation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { circle(); } @Override public void onAnimationRepeat(Animation animation) { } }); } class ClickListener implements View.OnClickListener { @Override public void onClick(View view) { switch (view.getId()){ case R.id.startBluetooth://开启蓝牙 if (!bluetoothAdapter.isEnabled()) { int REQUEST_ENABLE_BT = 1; Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(intent,REQUEST_ENABLE_BT); } break; case R.id.connectBluetooth://扫描,连接设备 if (bluetoothAdapter.isDiscovering()) { bluetoothAdapter.cancelDiscovery(); i = 0; } bluetoothAdapter.startDiscovery(); break; case R.id.dataButton://进入数据界面 Intent intent = new Intent(MainActivity.this,DataActivity.class); startActivity(intent); } } } private class LocalReceiver extends BroadcastReceiver{//本地ui控制广播 @Override public void onReceive(Context context, Intent intent) { switch (intent.getAction()) { case "LOCAL_BROAD_EV_PROGRESS": Bundle bundle = intent.getExtras(); number = bundle.getString("Times"); Message msg =new Message(); msg.what =NUMBER_CHANGED; handler.sendMessage(msg); i++; if (i==1) { Snackbar.make(startBuletooth,"已连接到手环",Snackbar.LENGTH_SHORT).show(); } break; } } } }
DataActivity
package com.tree.max.assistant; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Color; import android.graphics.PointF; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.annotation.Nullable; import android.support.v4.content.LocalBroadcastManager; import com.idtk.smallchart.chart.LineChart; import com.idtk.smallchart.data.LineData; import com.idtk.smallchart.interfaces.iData.ILineData; import java.util.ArrayList; /** * Created by max on 17-5-18. */ public class DataActivity extends Activity { LineChart lineChart; LineData lineData; ArrayList<ILineData> dataList; ArrayList<PointF> linePointList ; LocalReceiver localReceiver; int[] x = new int[10]; int[] y = new int[10]; final int NUMBER_CHANGED = 1; String number; final Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case NUMBER_CHANGED: lineChart.setDataList(dataList); break; } } }; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.data_view); init(); linePointList.add(new PointF(1,2)); linePointList.add(new PointF(10,10)); linePointList.add(new PointF(100,100)); linePointList.add(new PointF(200,200)); lineData.setValue(linePointList); lineData.setColor(Color.CYAN); lineData.setPaintWidth(1); lineData.setTextSize(4); dataList.add(lineData); lineChart.isAnimated = false; lineChart.setDataList(dataList); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("LOCAL_BROAD_EV_PROGRESS"); localReceiver= new LocalReceiver(); LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this); localBroadcastManager.registerReceiver(localReceiver,intentFilter); } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(localReceiver); } public void init() { lineChart = (LineChart)findViewById(R.id.times_data_view); lineData = new LineData(); linePointList = new ArrayList<>(); dataList = new ArrayList<>(); for (int j= 0; j<10;j++) { x[j] = j*10; } } private class LocalReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { switch(intent.getAction()) { case "LOCAL_BROAD_EV_PROGRESS": Bundle bundle = intent.getExtras(); number = bundle.getString("Times"); for (int i = 1;i<=9;i++) { x[i-1] = x[i]; y[i-1] = y[i]; } x[9] = 10; y[9] = 10; linePointList.clear(); for (int i = 0 ; i<10;i++) { linePointList.add(new PointF(x[i],y[i])); } lineData.setValue(linePointList); dataList.clear(); dataList.add(lineData); Message msg =new Message(); msg.what =NUMBER_CHANGED; handler.sendMessage(msg); } } } }
AcceptThread
package com.tree.max.assistant; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothSocket; import android.content.Context; import android.support.design.internal.NavigationMenu; import android.util.Log; import android.widget.TextView; import java.io.IOException; import java.util.UUID; /** * Created by max on 17-5-17. */ public class AcceptThread extends Thread { private final BluetoothSocket mmSocket; private final BluetoothDevice mmDevice; private Context context; private final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); public AcceptThread(BluetoothDevice device,Context context) { // Use a temporary object that is later assigned to mmSocket, // because mmSocket is final Log.e("AcceptThread","start"); BluetoothSocket tmp = null; mmDevice = device; this.context = context; // Get a BluetoothSocket to connect with the given BluetoothDevice try { // MY_UUID is the app's UUID string, also used by the server code tmp = device.createRfcommSocketToServiceRecord(MY_UUID); } catch (IOException e) { } mmSocket = tmp; } public void run() { // Cancel discovery because it will slow down the connection // mBluetoothAdapter.cancelDiscovery(); try { // Connect the device through the socket. This will block // until it succeeds or throws an exception mmSocket.connect(); } catch (IOException connectException) { // Unable to connect; close the socket and get out try { mmSocket.close(); } catch (IOException closeException) { } return; } // Do work to manage the connection (in a separate thread) manageConnectedSocket(mmSocket); } /** Will cancel an in-progress connection, and close the socket */ public void cancel() { try { mmSocket.close(); } catch (IOException e) { } } private void manageConnectedSocket(BluetoothSocket socket) { Log.e("AcceptThread","finished"); ConnectedThread connectedThread = new ConnectedThread(socket,context); connectedThread.start(); } }
ConnectedThread
package com.tree.max.assistant; import android.bluetooth.BluetoothSocket; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.Message; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import android.widget.TextView; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import android.os.Handler; /** * Created by max on 17-5-17. */ public class ConnectedThread extends Thread { private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; Handler mHandler; Message message; Bundle bundle; LocalBroadcastManager localBroadcastManager; Intent intent = new Intent("LOCAL_BROAD_EV_PROGRESS"); public ConnectedThread(BluetoothSocket socket,Context context) { localBroadcastManager = LocalBroadcastManager.getInstance(context); Log.e("ConnectedThread","start"); message = new Message(); bundle = new Bundle(); mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; // Get the input and output streams, using temp objects because // member streams are final try { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (IOException e) { } mmInStream = tmpIn; mmOutStream = tmpOut; } public void run() { byte[] buffer = new byte[1024]; // buffer store for the stream int bytes; // bytes returned from read() // Keep listening to the InputStream until an exception occurs while (true) { try { // Read from the InputStream bytes = mmInStream.read(buffer); // Send the obtained bytes to the UI activity String str = new String(buffer, "ISO-8859-1"); str = str.substring(0, bytes); Log.e("recv", str); Bundle bundle = new Bundle(); bundle.putString("Times",str); intent.putExtras(bundle); localBroadcastManager.sendBroadcast(intent); } catch (IOException e) { break; } } } /* Call this from the main activity to send data to the remote device */ public void write(byte[] bytes) { try { mmOutStream.write(bytes); } catch (IOException e) { } } /* Call this from the main activity to shutdown the connection */ public void cancel() { try { mmSocket.close(); } catch (IOException e) { } } }
ViewHandler
package com.tree.max.assistant; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; /** * Created by max on 17-5-17. */ public class ViewHandler extends Handler { public ViewHandler() { } public ViewHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); Bundle b = msg.getData(); String times =b.getString("Size"); sendMessage(msg); } }
相关文章推荐
- 酷炫开源项目cardsui-for-android-超详细源码分析,详解所用特效是如何实现的
- 斗地主算法的设计与实现(六)--项目源码和说明
- BaseRecyclerViewAdapterHelper开源项目之BaseQuickAdapter源码学习上拉加载的实现代码(三)
- BaseRecyclerViewAdapterHelper开源项目之BaseSectionQuickAdapter 实现Expandable And collapse效果的源码学习
- 斗地主算法的设计与实现(六)--项目源码和说明
- BaseRecyclerViewAdapterHelper开源项目之BaseSectionQuickAdapter 实现分组效果的源码学习
- BaseRecyclerViewAdapterHelper开源项目之BaseQuickAdapter源码学习上拉加载的实现代码(三)
- 斗地主算法的设计与实现(六)--项目源码和说明
- Fresco(Facebook开源的android项目)图片缓存框架的eclipse整合与使用探索(较详细配置说明)
- BaseRecyclerViewAdapterHelper开源项目之BaseMultiItemQuickAdapter 实现多类型源码学习
- BaseRecyclerViewAdapterHelper开源项目之BaseSectionQuickAdapter 实现分组效果的源码学习
- BaseRecyclerViewAdapterHelper开源项目之BaseMultiItemQuickAdapter 实现多类型源码学习
- BaseRecyclerViewAdapterHelper开源项目之BaseQuickAdapter源码学习之预加载的实现(二)
- [开源类库/项目] android保存崩溃时的错误信息log至本地【源码+jar包+使用说明
- 斗地主算法的设计与实现(六)--项目源码和说明
- 移植开源项目obexftp到android平台下实现蓝牙ftp的功能
- BaseRecyclerViewAdapterHelper开源项目之BaseSectionQuickAdapter 实现Expandable And collapse效果的源码学习
- VC++ & MFC实现的优秀的开源项目
- Eclipse下实现软件项目的源码管理
- VOIP开源项目源码地址