托瓦兹 莱纳斯 是一个天才.
这个项目主要以蓝牙和自己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(){@Overridepublic void handleMessage(Message msg) {switch (msg.what){case NUMBER_CHANGED:numberView.setText(number);//更改UI数据break;}}};@Overrideprotected 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() {@Overridepublic 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);}@Overridepublic 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);}@Overridepublic 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();}}@Overrideprotected void onDestroy() {super.onDestroy();unregisterReceiver(receiver);unregisterReceiver(localReceiver);}private void init(){numberView = (TextView)findViewById(R.id.numberTextView);liitleButton = (LinearLayout) findViewById(R.id.little_circle);contentFrameLayout = (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() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {circle();}@Overridepublic void onAnimationRepeat(Animation animation) {}});}class ClickListener implements View.OnClickListener {@Overridepublic 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控制广播@Overridepublic 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(){@Overridepublic void handleMessage(Message msg) {switch (msg.what){case NUMBER_CHANGED:lineChart.setDataList(dataList);break;}}};@Overrideprotected 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);}@Overrideprotected 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{@Overridepublic 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 finalLog.e("AcceptThread","start");BluetoothSocket tmp = null;mmDevice = device;this.context = context;// Get a BluetoothSocket to connect with the given BluetoothDevicetry {// MY_UUID is the app's UUID string, also used by the server codetmp = 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 exceptionmmSocket.connect();} catch (IOException connectException) {// Unable to connect; close the socket and get outtry {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 finaltry {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 streamint bytes; // bytes returned from read()// Keep listening to the InputStream until an exception occurswhile (true) {try {// Read from the InputStreambytes = mmInStream.read(buffer);// Send the obtained bytes to the UI activityString 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);}@Overridepublic void handleMessage(Message msg){super.handleMessage(msg);Bundle b = msg.getData();String times =b.getString("Size");sendMessage(msg);}
}

仿小米运动的蓝牙开源项目(附详细实现说明+源码)相关推荐

  1. 【开源项目】Dynamic-Tp告警系统的源码解析

    序言 [开源项目]Dynamic-Tp核心流程源码解读,继上回解读完DynamicTp这个开源项目的源码,觉得其中的告警机制也是十分精彩,如果能学会,用在自己的项目中,那才能说得上掌握了Dynamic ...

  2. 【Unity开源项目精选】Unity引擎源码的C#部分

    洪流学堂,让你快人几步.你好,我是你的技术探路者郑洪智,你可以叫我大智. 今天给你分享一个Unity开源项目,我们一起来看看吧! Unity引擎源码的C#部分 Unity 引擎和编辑器源代码的 C# ...

  3. 开源项目推荐:金山卫士源码

    金山卫士开源项目,pcmanager v2.6.3 对于广大开发者尤其是广大做Windows安全方面的朋友来说,这套代码具有很大的借鉴意义,至少我们可以知道那些所谓的"电脑管家"到 ...

  4. android温湿度传感节点指令源代码,Arduino+DHT11+OLED显示温湿度信息(附详细文档+源码)...

    设计者:STCode (公众号同名) 第一章 绪论 1.1实训设计背景与意义 随着生活水平的提高和科技水平的发展,人们对自身和家庭安全方面的考虑也越来越多,越来越多的安全监测系统和设备进入到人们的生活 ...

  5. python tkinter 日期时间选择器,附详细可运行源码

    因为最近需要用的日期时间选择框,网上找了一圈发现大多都用不了,自己结合官方库写了一个,在这免费分享出来,供有需要的小伙伴使用. 先看效果图: 点击开始时间按钮弹出日期选择框,确定后输出到文本框中. 先 ...

  6. 【仿写酷界面】【HenCoder】仿小米运动的运动记录界面

    MISportsConnectWidget 项目地址:sickworm/MISportsConnectWidget  简介:[仿写酷界面][HenCoder]仿小米运动的运动记录界面 更多:作者    ...

  7. android仿小米运动,仿小米运动的运动记录界面

    [实例简介] 仿小米运动的运动记录界面,可用. [实例截图] [核心代码] MISportsConnectWidget-master └── MISportsConnectWidget-master ...

  8. kaggle经典题--“泰坦尼克号”--0.8275准确率--东北大学20级python大作业开源(附详细解法与全部代码以及实验报告)

    kaggle经典题--"泰坦尼克号"--0.8275准确率--东北大学20级python大作业开源(附详细解法与全部代码以及实验报告) 前言 开发环境 一.导入包: 二.实验数据的 ...

  9. 白嫖项目基于ssm房屋租赁系统源码【开源项目】

    ssm房屋租赁系统 运行工具:idea或eclipse均测试,可以运行. 开发技术: 后端ssm(spring springmvc mybatis)   前端:jsp  jquery 数据库:mysq ...

最新文章

  1. android源码中常用的Rect方法
  2. Android的Handler,Looper源码剖析
  3. matlab程序转java_用面向对象的方法将一段JAVA代码转化为matlab
  4. 程序员,与工程师的区别在哪里? (3)
  5. 用PD进行数据库建模经验总结
  6. Spring 中获取 request 的几种方法,及其线程安全性分析
  7. 开发对接微信卡包会员卡_产品||AI刷脸会员+电子会员卡
  8. 为确保网络中不同计算机,在计算机网络中,为确保网络中不同计算机之间能正确地传送和接收数据,它们必须遵循一组共同的规则和约定。这些规则、约定或标准通常被称为____。...
  9. 提升存储过程的效率,用减少表的更新次数来实现
  10. Protel99se信号完整性的最新应用
  11. python入门基本知识
  12. 基于Easy CHM和VS的帮助文档制作
  13. h3c交换机端口加入vlan命令_h3c交换机vlan配置划分命令
  14. xshell连接kali系统
  15. 使用计算机用眼卫生,电脑族日常保护眼睛小常识
  16. 数字漫画行业繁花似锦,国漫扎根本土文化“向外生长”?
  17. 短链接如何为短信营销提效
  18. Python轻松实现AI换脸
  19. \t\t工信部:要求对网站主办者身份信息当面核验
  20. JMP指令寻址方式总结,JMP BX指令寻址方式是什么

热门文章

  1. tesseract OCR的多语言,多字体字符识别
  2. 论文参考文献插入方法,页眉设置
  3. HTML 判断手机的类型(苹果手机安卓手机)
  4. 什么是面向对象OOP
  5. Java 面向对象高级
  6. 安卓手改装成kali linux,人手一份核武器:Android手机装Kali Linux
  7. Intellij IDEA的Bookmarks
  8. 论文笔记:ICML 2019 Simplifying Graph Convolutional Networks
  9. 前端js多个小数相加出现无限循环小数的解决办法
  10. AT6558R 中科微北斗导航芯片 CMOS图像传感器芯片