您的位置:首页 > 产品设计 > UI/UE

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

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

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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ui 蓝牙 界面
相关文章推荐