android蓝牙与下位机交互
2015-06-03 10:47
423 查看
最近在做一个项目,是蓝牙与下位机进行交互,只是简单的数据交互,使用蓝牙4.0.。。。
先看看项目的简易通信协议:
协议内容,是一个44位字节的通信命令式协议:
协议格式:
输出格式:pump on + (char)13 + (char)10
返回格式 10PID 9PStatus 10FID 9FStatus <CF><LR>,去掉结尾符共42位,结尾以char[10]char[13];
解释下:
char[13]char[10]就是“\r\n”;
看懂了这些,开始找思路,其实蓝牙无非就是socket通信,下位机当做S端,终端设备是C端,请求连接S端,然后用socket向S端写数据,写过C的都知道,C中没有String的概
念,只有char*[],这样就有个问题,我们java的命令行是拼接的String字符串,如何去转化成char*[]呢,我们知道C接受数据时候的没有byte,但是要理解byte其实就是无属的char
即(C没有这个类型,byte表示一个字节,对应C的unsigned char),java是没有指针概念的,,其实这里非常简单,,char*[]无非就是一个char型的数组,那么有了这条思路,我
们用String.getByteArray()
即可。转化成字节数组,那么对应的就是C中unsigned char[ ],既然数据类型匹配完成,那么就开始从java入手书写代码:
主界面:
[html] view
plaincopy
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageButton
android:id="@+id/btnOpenBT"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/bluetooth_off" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/tvDeviceName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="right"
android:text="Bluetooth"
android:textSize="14sp" />
</LinearLayout>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="写入测试" />
<EditText
android:id="@+id/output_test"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="数据回显测试" />
<TextView
android:id="@+id/input_test"
android:layout_width="fill_parent"
android:textSize="14sp"
android:layout_height="30dp" />
<Button
android:id="@+id/start_test"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="开始测试" />
<Button
android:id="@+id/btn1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="pump on" />
<Button
android:id="@+id/btn2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="pump off" />
<Button
android:id="@+id/btn3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="detector pid_fid" />
<Button
android:id="@+id/btn4"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="ignite" />
</LinearLayout>
</ScrollView>
搜索蓝牙布局界面:
[html] view
plaincopy
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/newdevice" />
<ListView
android:id="@+id/lvNewDevices"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:stackFromBottom="true" >
</ListView>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/paireddevice" />
<ListView
android:id="@+id/lvPairedDevices"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:stackFromBottom="true" >
</ListView>
<Button
android:id="@+id/btnScan"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/scan" />
</LinearLayout>
开始代码:
[java] view
plaincopy
package com.simpledraw.bluetoothservice;
import java.text.DecimalFormat;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.simpledraw.bluetooth.BluetoothCommService;
import com.simpledraw.bluetooth.BluetoothEnvironment;
import com.simpledraw.bluetooth.ConstantsBluetooth;
import com.simpledraw.bluetooth.ScanBTDeviceActivity;
import com.simpledraw.bluetooth.data.Datagram;
public class MainActivity extends Activity {
private TextView tvDirection1, tvDirection2;
private ScaleAnimation animTemperature, animHumidity;
private RotateAnimation animPressure;
private float currentDirection1 = 0, currentDirection2 = 0, currentTemperature = ConstantsEwins.MIN_TEMPERATURE_Y,
currentHumidity = 0.0f, currentPressure = 0;
DecimalFormat df = new DecimalFormat("0.00");
private ImageButton btnOpenBT = null;
private TextView tvDeviceName = null;
private Datagram datagram = new Datagram();
private BluetoothAdapter btAdapter;
private BluetoothDevice mDevice;
private int[] checked = new int[11];
private long exitTime = 0;// 用于再按一次退出
private String executStr = "";
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getBluetoothAdapter();
findAllControls();
}
private EditText output_edit;
private TextView input_edit;
private Button startTest;
private void findAllControls() {
output_edit = (EditText) findViewById(R.id.output_test);
input_edit = (TextView) findViewById(R.id.input_test);
startTest = (Button) findViewById(R.id.start_test);
((Button)findViewById(R.id.btn1)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
executStr = ((Button)v).getText().toString();
output_edit.setText("");
executStr+="\r\n";
BluetoothEnvironment.service.write(executStr.getBytes());
output_edit.setText(executStr);
}
});
((Button)findViewById(R.id.btn2)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
executStr = ((Button)v).getText().toString();
output_edit.setText(executStr);
output_edit.setText("");
executStr+="\r\n";
BluetoothEnvironment.service.write(executStr.getBytes());
}
});
((Button)findViewById(R.id.btn3)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
executStr = ((Button)v).getText().toString();
output_edit.setText(executStr);
output_edit.setText("");
executStr="log start\r\n";
BluetoothEnvironment.service.write(executStr.getBytes());
executStr="detector pid_fid\r\n";
BluetoothEnvironment.service.write(executStr.getBytes());
}
});
((Button)findViewById(R.id.btn4)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
executStr = ((Button)v).getText().toString();
output_edit.setText(executStr);
output_edit.setText("");
executStr+="\r\n";
BluetoothEnvironment.service.write(executStr.getBytes());
}
});
startTest.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
if(BluetoothEnvironment.service!=null){
output_edit.setText("");
// String outputData = output_edit.getText().toString();
executStr+="\r\n";
// byte[] bytes = outputData.getBytes();
// byte[] bytes2 = new byte[bytes.length+2];
// for(int i = 0;i<bytes.length;i++){
// bytes2[i] = bytes[i];
// }
// bytes2[bytes2.length-2] = 13;
// bytes2[bytes2.length-1] = 10;
BluetoothEnvironment.service.write(executStr.getBytes());
}
}
});
btnOpenBT = (ImageButton) findViewById(R.id.btnOpenBT);
btnOpenBT.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent intent = new Intent(MainActivity.this, ScanBTDeviceActivity.class);
startActivityForResult(intent, ConstantsBluetooth.REQUEST_CONNECT_DEVICE);
}
});
tvDeviceName = (TextView) findViewById(R.id.tvDeviceName);
for (int i = 0; i < 11; i++)
checked[i] = View.VISIBLE;
}
private void getBluetoothAdapter() {
btAdapter = BluetoothAdapter.getDefaultAdapter();
if (btAdapter == null) {
Toast.makeText(MainActivity.this, "本设备不支持蓝牙", Toast.LENGTH_SHORT).show();
finish();
return;
}
while (!btAdapter.isEnabled()) {
if (btAdapter.enable()) {
Toast.makeText(MainActivity.this, "蓝牙已经启动", Toast.LENGTH_SHORT).show();
break;
} else {
Toast.makeText(MainActivity.this, "蓝牙启动失败", Toast.LENGTH_SHORT).show();
return;
}
}
if (btAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(intent);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 1, 0, R.string.tianjiachuanganqi);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getOrder() == 0) {
Intent intent = new Intent(MainActivity.this, AddDeleteSensorsActivity.class);
intent.putExtra("checked", checked);
startActivityForResult(intent, ConstantsEwins.REQUEST_ADDDELETE_SENSORS);
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onResume() {
System.out.println("------- ON RESUME ---------");
super.onResume();
if (BluetoothEnvironment.service != null) {
if (btAdapter.isEnabled() && BluetoothEnvironment.service.getState() == ConstantsBluetooth.STATE_NONE) {
BluetoothEnvironment.service.start();
}
BluetoothEnvironment.service.setHandler(mHandler, null);
} else {
BluetoothEnvironment.service = new BluetoothCommService(this, mHandler, null);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case ConstantsBluetooth.REQUEST_CONNECT_DEVICE:
if (resultCode == RESULT_OK) {
String address = data.getExtras().getString(ConstantsBluetooth.DEVICE_ADDRESS);
mDevice = btAdapter.getRemoteDevice(address);
if (mDevice == null)
return;
if (BluetoothEnvironment.service != null)
BluetoothEnvironment.service.connect(mDevice);
}
break;
case ConstantsEwins.REQUEST_ADDDELETE_SENSORS:
if (resultCode == RESULT_OK) {
}
break;
default:
break;
}
}
@SuppressLint("HandlerLeak")
private final Handler mHandler = new Handler() {
int length = 0;
boolean firstReceived = true;
long lastReadTime = System.currentTimeMillis();
StringBuffer sb = new StringBuffer(ConstantsEwins.DATA_LENGTH);
@Override
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case ConstantsBluetooth.MESSAGE_STATE_CHANGE:
switch (msg.arg1) {
case ConstantsBluetooth.STATE_CONNECTED:
Toast.makeText(MainActivity.this, "已连接至" + msg.obj + "!!fdasfds", Toast.LENGTH_SHORT).show();
tvDeviceName.setText((String) msg.obj);
btnOpenBT.setBackgroundResource(R.drawable.bluetooth_on);
break;
case ConstantsBluetooth.STATE_CONNECTING:
Toast.makeText(MainActivity.this, "正在连接,请稍候", Toast.LENGTH_LONG).show();
break;
case ConstantsBluetooth.STATE_LISTEN:
if (ConstantsBluetooth.CONNECTION_FAILED.equals(msg.obj)) {
Toast.makeText(MainActivity.this, "连接不成功", Toast.LENGTH_SHORT).show();
btnOpenBT.setBackgroundResource(R.drawable.bluetooth_off);
} else if (ConstantsBluetooth.CONNECTION_LOST.equals(msg.obj)) {
Toast.makeText(MainActivity.this, "连接丢失", Toast.LENGTH_SHORT).show();
btnOpenBT.setBackgroundResource(R.drawable.bluetooth_off);
}
break;
case ConstantsBluetooth.STATE_NONE:
btnOpenBT.setBackgroundResource(R.drawable.bluetooth_off);
break;
}
break;
case ConstantsBluetooth.MESSAGE_WRITE:
break;
case ConstantsBluetooth.MESSAGE_READ:
if (firstReceived)
lastReadTime = System.currentTimeMillis();
firstReceived = false;
if (System.currentTimeMillis() - lastReadTime > ConstantsEwins.DATAGRAM_INTERVAL) {
if (length == ConstantsEwins.DATAGRAM_BYTES_LENGTH) {
datagram.parseDatagram(sb.toString());
modifyViews();
}
sb = new StringBuffer(ConstantsEwins.DATA_LENGTH);
length = 0;
}
String data = (String) msg.obj;
System.out.println("接收到的数据:" + data);
Log.e("texts",data);
length += msg.arg1;
sb.append(data);
lastReadTime = System.currentTimeMillis();
input_edit.setText(data);//sb.toString()
break;
}
}
};
@SuppressLint("NewApi")
private void modifyViews() {
tvDirection1.setText("风向1: " + (datagram.getDirection1() - (datagram.getDirection1() / 360) * 360) + "°");
tvDirection2.setText("风向2: " + (datagram.getDirection2() - (datagram.getDirection2() / 360) * 360) + "°");
// 风速改变
long newDuration;
newDuration = calcSpeedDuration(datagram.getSpeed1());
newDuration = calcSpeedDuration(datagram.getSpeed2());
newDuration = calcSpeedDuration(datagram.getSpeed3());
newDuration = calcSpeedDuration(datagram.getSpeed4());
newDuration = calcSpeedDuration(datagram.getSpeed5());
newDuration = calcSpeedDuration(datagram.getSpeed6());
currentDirection1 = datagram.getDirection1();
currentDirection2 = datagram.getDirection2();
// 温度、湿度和气压
float newTemperature = (datagram.getTemperature() - ConstantsEwins.MIN_TEMPERATURE_VALUE)
* ConstantsEwins.TEMPERATURE_STEP + ConstantsEwins.MIN_TEMPERATURE_Y;
float newHumidity = datagram.getHumidity() * ConstantsEwins.HUMIDITY_STEP + ConstantsEwins.MIN_HUMIDITY_Y;
float newPressure = (datagram.getPressure() - ConstantsEwins.MIN_PRESSURE_VALUE) * ConstantsEwins.PRESSURE_STEP;
animTemperature = new ScaleAnimation(1.0f, 1.0f, currentTemperature, newTemperature,
Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0.8f);
animTemperature.setDuration(500);
animTemperature.setFillAfter(true);
animHumidity = new ScaleAnimation(1.0f, 1.0f, currentHumidity, newHumidity, Animation.RELATIVE_TO_SELF, 0,
Animation.RELATIVE_TO_SELF, 0.8f);
animHumidity.setDuration(500);
animHumidity.setFillAfter(true);
animPressure = new RotateAnimation(currentPressure, newPressure, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
animPressure.setDuration(500);
animPressure.setFillAfter(true);
currentTemperature = newTemperature;
currentHumidity = newHumidity;
currentPressure = newPressure;
}
private long calcSpeedDuration(float speed) {
int level;
if (speed < 1.5f)
level = 1;
else if (speed > 1.6 && speed < 5.4)
level = 2;
else if (speed > 5.5 && speed < 7.9)
level = 3;
else if (speed > 8.0 && speed < 10.7)
level = 4;
else if (speed > 10.8 && speed < 13.8)
level = 5;
else if (speed > 13.9 && speed < 17.1)
level = 6;
else if (speed > 17.2 && speed < 20.7)
level = 7;
else if (speed > 20.8 && speed < 24.4)
level = 8;
else if (speed > 24.5 && speed < 28.4)
level = 9;
else if (speed > 28.5 && speed < 32.6)
level = 10;
else
level = 11;
long duration;
duration = (11 - level) * ConstantsEwins.SPEED_DURATION_STEP + ConstantsEwins.MIN_SPEED_DURATION;
return duration;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
if ((System.currentTimeMillis() - exitTime) > 2000) {
Toast.makeText(this, "再按一次退出程序", Toast.LENGTH_SHORT).show();
exitTime = System.currentTimeMillis();
} else {
finish();
System.exit(0);
}
return true;
}
return super.onKeyDown(keyCode, event);
}
}
[java] view
plaincopy
package com.simpledraw.bluetoothservice;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
public class DirectionPointerView extends ImageView {
private float mDirection;
private Drawable compass;
public DirectionPointerView(Context context) {
super(context);
mDirection = 0.0f;
compass = null;
}
public DirectionPointerView(Context context, AttributeSet attrs) {
super(context, attrs);
mDirection = 0.0f;
compass = null;
}
public DirectionPointerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mDirection = 0.0f;
compass = null;
}
@Override
protected void onDraw(Canvas canvas) {
if (compass == null) {
compass = getDrawable();
compass.setBounds(0, 0, getWidth(), getHeight());
}
canvas.save();
canvas.rotate(mDirection, getWidth() / 2, getHeight() / 2);
compass.draw(canvas);
canvas.restore();
}
public void updateDirection(float direction) {
mDirection = direction;
invalidate();
}
}
[java] view
plaincopy
package com.simpledraw.bluetoothservice;
public class ConstantsEwins {
public static final int REQUEST_ADDDELETE_SENSORS = 2;
public static final float MAX_SPEED_VALUE = 100;
public static final float MIN_SPEED_VALUE = 0;
public static final int MIN_SPEED_DURATION = 500;
public static final int SPEED_DURATION_STEP = 500;
public static final float MAX_TEMPERATURE_VALUE = 53;
public static final float MIN_TEMPERATURE_VALUE = -40;
public static final float MIN_TEMPERATURE_Y = 0.02f;
public static final float TEMPERATURE_STEP = 0.01185f;
public static final float MIN_HUMIDITY_Y = 0.0f;
public static final float HUMIDITY_STEP = 0.01118f;
public static final float MAX_PRESSURE_VALUE = 120;
public static final float MIN_PRESSURE_VALUE = 10;
public static final float PRESSURE_STEP = 2.38f;
public static final int DATAGRAM_INTERVAL = 500;
// 报文的字节数
public static final int DATAGRAM_BYTES_LENGTH = 20;
// 需要使用的数据长度,例如将字节变成16进制字符串的长度,0x80变成80
public static final int DATA_LENGTH = 40;
}
[java] view
plaincopy
package com.simpledraw.bluetooth.data;
import android.annotation.SuppressLint;
@SuppressLint("DefaultLocale")
public class DataTypeConverter {
public static String double2Str(double d) {
return String.format("%.1f", d);
}
public static double str2Double(String str) {
return Double.parseDouble(str);
}
public static String getMacAddress(String pStr) {
return pStr.substring(pStr.length() - 17);
}
public static double hexStr2Double(String pStr) {
int i = Integer.parseInt(pStr, 16);
double d;
if (pStr.startsWith("F")) {
d = (double) (i - 65536) / 100;
} else {
d = (double) i / 100;
}
d = ((double) Math.round(d * 10)) / 10;
return d;
}
public static float hexStr2Float(String pStr) {
return (float) (hexStr2Double(pStr));
}
public static int hexStr2Int(String pStr) {
return Integer.parseInt(pStr, 16);
}
}
[java] view
plaincopy
package com.simpledraw.bluetooth.data;
import java.text.DecimalFormat;
import com.simpledraw.bluetoothservice.ConstantsEwins;
public class Datagram {
private float speed1;
private float speed2;
private float speed3;
private float speed4;
private float speed5;
private float speed6;
private int direction1;
private int direction2;
private float temperature;
private int humidity;
private float pressure;
DecimalFormat df = new DecimalFormat(".00");
public float getSpeed1() {
return speed1;
}
public void setSpeed1(float speed1) {
this.speed1 = speed1 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE
: (speed1 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed1);
}
public float getSpeed2() {
return speed2;
}
public void setSpeed2(float speed2) {
this.speed2 = speed2 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE
: (speed2 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed2);
}
public float getSpeed3() {
return speed3;
}
public void setSpeed3(float speed3) {
this.speed3 = speed3 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE
: (speed3 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed3);
}
public float getSpeed4() {
return speed4;
}
public void setSpeed4(float speed4) {
this.speed4 = speed4 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE
: (speed4 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed4);
}
public float getSpeed5() {
return speed5;
}
public void setSpeed5(float speed5) {
this.speed5 = speed5 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE
: (speed5 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed5);
}
public float getSpeed6() {
return speed6;
}
public void setSpeed6(float speed6) {
this.speed6 = speed6 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE
: (speed6 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed6);
}
public int getDirection1() {
return direction1;
}
public void setDirection1(int direction1) {
this.direction1 = direction1;
}
public int getDirection2() {
return direction2;
}
public void setDirection2(int direction2) {
this.direction2 = direction2;
}
public float getTemperature() {
return temperature;
}
public void setTemperature(float temperature) {
this.temperature = temperature > ConstantsEwins.MAX_TEMPERATURE_VALUE ? ConstantsEwins.MAX_TEMPERATURE_VALUE
: (temperature < ConstantsEwins.MIN_TEMPERATURE_VALUE ? ConstantsEwins.MIN_TEMPERATURE_VALUE
: temperature);
}
public int getHumidity() {
return humidity;
}
public void setHumidity(int humidity) {
this.humidity = humidity > 100 ? 100 : (humidity < 0 ? 0 : humidity);
}
public float getPressure() {
return pressure;
}
public void setPressure(float pressure) {
this.pressure = pressure > ConstantsEwins.MAX_PRESSURE_VALUE ? ConstantsEwins.MAX_PRESSURE_VALUE
: (pressure < ConstantsEwins.MIN_PRESSURE_VALUE ? ConstantsEwins.MIN_PRESSURE_VALUE : pressure);
}
public void parseDatagram(String datagram) {
// datagram = "01076954204231804B0A08072102C3046307F209";
if (datagram == null || datagram == "") {
System.out.println("kong");
return;
}
setSpeed1(calcSpeed(datagram.substring(4, 6)));
setSpeed2(calcSpeed(datagram.substring(6, 8)));
setSpeed3(calcSpeed(datagram.substring(8, 10)));
setSpeed4(calcSpeed(datagram.substring(10, 12)));
setSpeed5(calcSpeed(datagram.substring(12, 14)));
setSpeed6(calcSpeed(datagram.substring(14, 16)));
setDirection1(calcDirection(datagram.substring(22, 24) + datagram.substring(20, 22)));
setDirection2(calcDirection(datagram.substring(26, 28) + datagram.substring(24, 26)));
setTemperature(calcTemperature(datagram.substring(30, 32) + datagram.substring(28, 30)));
setHumidity(calcHumidity(datagram.substring(34, 36) + datagram.substring(32, 34)));
setPressure(calcPressure(datagram.substring(38, 40) + datagram.substring(36, 38)));
}
private float calcSpeed(String pStrSpeedHex) {
float speed = DataTypeConverter.hexStr2Int(pStrSpeedHex);
return speed * 0.765f + 0.35f;
}
private int calcDirection(String pStrDirectionHex) {
int direction = DataTypeConverter.hexStr2Int(pStrDirectionHex);
return (int) (direction * 0.094230277);
}
private float calcTemperature(String pStrTempHex) {
float temperature = DataTypeConverter.hexStr2Int(pStrTempHex);
return (float) (temperature * 0.088695557 - 86.38);
}
private int calcHumidity(String pStrHumidityHex) {
int humidity = DataTypeConverter.hexStr2Int(pStrHumidityHex);
return (int) (humidity * 0.031933594);
}
private float calcPressure(String pStrPressureHex) {
float pressure = DataTypeConverter.hexStr2Int(pStrPressureHex);
return (float) (pressure * 0.03479165 + 10.55);
}
}
[html] view
plaincopy
package com.simpledraw.bluetooth;
import java.util.Set;
import android.app.Activity;
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.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import com.simpledraw.bluetooth.data.DataTypeConverter;
import com.simpledraw.bluetoothservice.R;
public class ScanBTDeviceActivity extends Activity {
private Button btnScan = null;
private ListView lvNewDevices, lvPairedDevices;
private ArrayAdapter<String> adapterNewDevices, adapterPairedDevice;
private BluetoothAdapter btAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Setup the window
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.device_list);
findAllViews();
btAdapter = BluetoothAdapter.getDefaultAdapter();
if (btAdapter == null) {
finish();
return;
}
Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();
for (BluetoothDevice device : pairedDevices) {
adapterPairedDevice.add(device.getName() + "\n" + device.getAddress());
}
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mReceiver, filter);
}
private void findAllViews() {
btnScan = (Button) findViewById(R.id.btnScan);
lvNewDevices = (ListView) findViewById(R.id.lvNewDevices);
adapterNewDevices = new ArrayAdapter<String>(ScanBTDeviceActivity.this, android.R.layout.simple_list_item_1);
lvNewDevices.setAdapter(adapterNewDevices);
lvNewDevices.setOnItemClickListener(DeviceListClickListener);
lvPairedDevices = (ListView) findViewById(R.id.lvPairedDevices);
adapterPairedDevice = new ArrayAdapter<String>(ScanBTDeviceActivity.this, android.R.layout.simple_list_item_1);
lvPairedDevices.setAdapter(adapterPairedDevice);
lvPairedDevices.setOnItemClickListener(DeviceListClickListener);
btnScan.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
discoverDevices();
}
});
}
private void discoverDevices() {
btnScan.setEnabled(false);
setTitle(R.string.scanning);
if (btAdapter.isDiscovering()) {
btAdapter.cancelDiscovery();
}
btAdapter.startDiscovery();
}
private OnItemClickListener DeviceListClickListener = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
btAdapter.cancelDiscovery();
String address = DataTypeConverter.getMacAddress(((TextView) arg1).getText().toString());
Intent intent = new Intent();
intent.putExtra(ConstantsBluetooth.DEVICE_ADDRESS, address);
setResult(RESULT_OK, intent);
finish();
}
};
@Override
protected void onDestroy() {
super.onDestroy();
if (btAdapter != null) {
btAdapter.cancelDiscovery();
}
unregisterReceiver(mReceiver);
};
private final BroadcastReceiver mReceiver = 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);
if (device.getBondState() != BluetoothDevice.BOND_BONDED)
adapterNewDevices.add(device.getName() + "\n" + device.getAddress());
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
btnScan.setEnabled(true);
setTitle(R.string.select_device);
}
}
};
}
[java] view
plaincopy
package com.simpledraw.bluetooth;
import java.util.UUID;
public class ConstantsBluetooth {
public static final int REQUEST_CONNECT_DEVICE = 1;
public static final String DEVICE_ADDRESS = "deviceaddress";
public static final String CONNECTED_DEVICE_NAME = "connecteddevicename";
public static final String SERVER_NAME = "BluetoothComm";
public static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
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 STATE_NONE = 0; // do nothing
public static final int STATE_LISTEN = 1; // 监听连接
public static final int STATE_CONNECTING = 2; // now initiating an outgoing
public static final int STATE_CONNECTED = 3; // 已连接上远程设备
public static final String CONNECTION_FAILED = "fail";
public static final String CONNECTION_LOST = "lost";
public static final String CONNECTION_CONNECTED = "connected";
public static final String COMMAND_1 = "uLPCC_0000CD?";
public static final byte[] COMMAND_ACK = new byte[] { (byte) 0x06 };
}
[java] view
plaincopy
package com.simpledraw.bluetooth;
public class BluetoothEnvironment {
public static BluetoothCommService service;
}
[java] view
plaincopy
package com.simpledraw.bluetooth;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.UUID;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;
public class BluetoothCommService implements Serializable {
private static final long serialVersionUID = 1L;
private static final String NAME = "BluetoothComm";
// SPP协议UUID
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
// Member fields
private final BluetoothAdapter mAdapter;
private Handler mHandler, receiveHandler;
private int mState;
private AcceptThread mAcceptThread;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
public BluetoothCommService(Context context, Handler handler, Handler p_receiveHandler) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
mHandler = handler;
receiveHandler = p_receiveHandler;
mState = ConstantsBluetooth.STATE_NONE;
}
public void setHandler(Handler pHandler, Handler p_receiveHandler) {
mHandler = pHandler;
receiveHandler = p_receiveHandler;
}
/**
* Set the current state of the chat connection
*
* @param state
* An integer defining the current connection state
*/
private synchronized void setState(int state) {
mState = state;
mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}
/**
* Return the current connection state.
*/
public synchronized int getState() {
return mState;
}
/**
* 开始服务,主要是开始AcceptThread线程,打开一个监听回话由BaowenActivity的onResume方法调用,
* ***开启监听线程****
*/
public synchronized void start() {
// 取消所有正在尝试连接的线程
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
// 取消所有已经连接上的线程
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
// 打开一个监听BluetoothServerSocket的线程
if (mAcceptThread == null) {
mAcceptThread = new AcceptThread();
mAcceptThread.start();// 开启监听线程
}
setState(ConstantsBluetooth.STATE_LISTEN);
}
/**
* Start the ConnectThread to initiate a connection to a remote device.
*
* @param device
* The BluetoothDevice to connect
*/
public synchronized void connect(BluetoothDevice device) {
// Cancel any thread attempting to make a connection
if (mState == ConstantsBluetooth.STATE_CONNECTING) {// 正在连接状态״̬
if (mConnectThread != null) {// 有ConnectThread,结束
mConnectThread.cancel();
mConnectThread = null;
}
}
// Cancel any thread currently running a connection
if (mConnectedThread != null) {// 有处于连接中的线程,结束
mConnectedThread.cancel();
mConnectedThread = null;
}
// Start the thread to connect with the given device
mConnectThread = new ConnectThread(device);
mConnectThread.start();// 开启新的连接请求线程
setState(ConstantsBluetooth.STATE_CONNECTING);
}
/**
* Start the ConnectedThread to begin managing a Bluetooth connection
*
* @param socket
* The BluetoothSocket on which the connection was made
* @param device
* The BluetoothDevice that has been connected
*/
public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
// Cancel the thread that completed the connection
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
// Cancel any thread currently running a connection
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = 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 = new ConnectedThread(socket);
mConnectedThread.start();// 和客户端开始通信
// 把已连接的设备的名称发给UI线程
Message msg = mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_STATE_CHANGE);
msg.arg1 = ConstantsBluetooth.STATE_CONNECTED;
msg.obj = device.getName();
mHandler.sendMessage(msg);
mState = ConstantsBluetooth.STATE_CONNECTED;
}
/**
* Stop all threads
*/
public synchronized void stop() {
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
if (mAcceptThread != null) {
mAcceptThread.cancel();
mAcceptThread = null;
}
setState(ConstantsBluetooth.STATE_NONE);
}
/**
* Write to the ConnectedThread in an unsynchronized manner
*
* @param out
* The bytes to write
* @see ConnectedThread#write(byte[])
*/
public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != ConstantsBluetooth.STATE_CONNECTED)
return;
r = mConnectedThread;// 得到连接线程
}
// Perform the write unsynchronized
r.write(out);
}
/**
* Indicate that the connection attempt failed and notify the UI Activity.
*/
private void connectionFailed() {
setState(ConstantsBluetooth.STATE_LISTEN);
// // Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_STATE_CHANGE);
msg.obj = "fail";
mHandler.sendMessage(msg);
}
/**
* Indicate that the connection was lost and notify the UI Activity.
*/
@SuppressWarnings("unused")
private void connectionLost() {
setState(ConstantsBluetooth.STATE_LISTEN);
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_STATE_CHANGE);
msg.obj = "lost";
mHandler.sendMessage(msg);
}
/**
* This thread runs while listening for incoming connections. It behaves
* like a server-side client. It runs until a connection is accepted (or
* until cancelled). 监听准备进入的连接,类似于服务端,
*/
private class AcceptThread extends Thread {
// 本地的socket
private final BluetoothServerSocket mmServerSocket;
public AcceptThread() {
BluetoothServerSocket tmp = null;
// 创建一个新的监听服务器socket
try {
// 根据名称,UUID创建并返回BluetoothServerSocket,这是创建BluetoothSocket服务器端的第一步
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, SPP_UUID);
} catch (IOException e) {
}
// 得到BluetoothServerSocket对象
mmServerSocket = tmp;
}
public void run() {
setName("AcceptThread");// set the name of thread
BluetoothSocket socket = null;
// Listen to the server socket if we're not connected
while (mState != ConstantsBluetooth.STATE_CONNECTED) {// 若没有连接,一直执行
try {
// 注意:BluetoothServerSocket的accept是一个阻塞性线程,一直到用户成功的配对,因此不要放在Activity中,
// 远程蓝牙设备请求跟本设备建立连接请求时,
// BluetoothServerSocket会在连接被接收时返回一个被连接的BluetoothSocket对象。
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// 连接建立成功
if (socket != null) {
synchronized (BluetoothCommService.this) {
switch (mState) {
case ConstantsBluetooth.STATE_LISTEN:
case ConstantsBluetooth.STATE_CONNECTING:
// 已经连接上,开始ConnectedThread线程
connected(socket, socket.getRemoteDevice());
break;
case ConstantsBluetooth.STATE_NONE:
case ConstantsBluetooth.STATE_CONNECTED:
// 或者设备没有准备好,或者已经连接,都将这个新的BluetoothSocket关掉
// 释放服务套接字,但不会关闭accept()返回的BluetoothSocket
try {
socket.close();
} catch (IOException e) {
}
break;
}
}
}
}
}
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) {
}
}
}
/**
* This thread runs while attempting to make an outgoing connection with a
* device. It runs straight through; the connection either succeeds or
* fails. 监听准备出去的连接
*/
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;// 远程设备
public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
// 通过远程设备直接创建一个BluetoothSocket,要求该设备已经打开了BluetoothServerSocket获得一个BluetoothSocket对象
tmp = device.createRfcommSocketToServiceRecord(SPP_UUID);
} catch (IOException e) {
}
mmSocket = tmp;
}
public void run() {
setName("ConnectThread");
// 取消搜索
mAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mmSocket.connect();
} catch (IOException e) {
connectionFailed();
// Close the socket
try {
mmSocket.close();
} catch (IOException e2) {
}
// Start the service over to restart listening mode
BluetoothCommService.this.start();
return;
}
// Reset the ConnectThread because we're done
synchronized (BluetoothCommService.this) {
mConnectThread = null;
}
// Start the connected thread,已连接上,管理连接
connected(mmSocket, mmDevice);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
}
/**
* This thread runs during a connection with a remote device. It handles all
* incoming and outgoing transmissions. 监听
*/
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final OutputStream mmOutStream;
private final BufferedInputStream reader;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
}
reader = new BufferedInputStream(tmpIn);
mmOutStream = tmpOut;
}
private String dataStr = "";
@SuppressLint("NewApi")
public void run() {
byte[] buffer = new byte[44], temp = new byte[127];
StringBuffer sb;
String b;
int numReadedBytes;
boolean cleaning = true;
long startTime = System.currentTimeMillis();
// 保持对InputStream的监听
while (true) {
try {
// if (cleaning) {
//// if (System.currentTimeMillis() - startTime < 2000) {
//
//
//
// numReadedBytes = reader.read(temp);
// // System.out.println("cleaning:" + numReadedBytes);
// continue;
//// } else
//// cleaning = false;
// }
numReadedBytes = reader.read(buffer);//temp
String tempStr = new String(buffer);//temp write to log
tempStr.replace("\r\n", "***");
String[] strs = tempStr.split("\r\n");
// System.out.println("numReaded0:" + numReadedBytes);
Log.d("texts",tempStr);
sb = new StringBuffer();
// for (int i = 0; i < numReadedBytes; i++) {
// b = Integer.toHexString(buffer[i] & 0xFF);
// if (b.length() < 2)
// sb.append("0");
// sb.append(b);
// }
mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_READ, numReadedBytes, 0, new String(buffer))
.sendToTarget();
buffer = new byte[44];
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Write to the connected OutStream.
*
* @param buffer
* The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
} catch (IOException e) {
e.printStackTrace();
Log.i("texts", "数据流写入失败");
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
}
}
OK,,,这样我所以项目都贴到上面了,,因为个人原因,不能贴项目源码,,但是改了一个项目,,亲测可用,,
我们要重点注意这里
MainActivity.java:
[java] view
plaincopy
((Button)findViewById(R.id.btn1)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
executStr = ((Button)v).getText().toString();
output_edit.setText("");
executStr+="\r\n";
BluetoothEnvironment.service.write(executStr.getBytes());
output_edit.setText(executStr);
}
});
这段是真实向下位机写数据,,如果你项目非常紧急,建议直接找到此处,修改这里,还有类似位置,然后我们在看看S端Return的值:
MainActivity.java:
[java] view
plaincopy
case ConstantsBluetooth.MESSAGE_READ:
if (firstReceived)
lastReadTime = System.currentTimeMillis();
firstReceived = false;
if (System.currentTimeMillis() - lastReadTime > ConstantsEwins.DATAGRAM_INTERVAL) {
if (length == ConstantsEwins.DATAGRAM_BYTES_LENGTH) {
datagram.parseDatagram(sb.toString());
modifyViews();
}
sb = new StringBuffer(ConstantsEwins.DATA_LENGTH);
length = 0;
}
String data = (String) msg.obj;
System.out.println("接收到的数据:" + data);
Log.e("texts",data);
length += msg.arg1;
sb.append(data);
lastReadTime = System.currentTimeMillis();
input_edit.setText(data);//sb.toString()
break;
以上即可与下位机交互,,,图片资源请自行寻找,,懒得贴了,,不做伸手党!!!
先看看项目的简易通信协议:
协议内容,是一个44位字节的通信命令式协议:
协议格式:
输出格式:pump on + (char)13 + (char)10
返回格式 10PID 9PStatus 10FID 9FStatus <CF><LR>,去掉结尾符共42位,结尾以char[10]char[13];
解释下:
char[13]char[10]就是“\r\n”;
看懂了这些,开始找思路,其实蓝牙无非就是socket通信,下位机当做S端,终端设备是C端,请求连接S端,然后用socket向S端写数据,写过C的都知道,C中没有String的概
念,只有char*[],这样就有个问题,我们java的命令行是拼接的String字符串,如何去转化成char*[]呢,我们知道C接受数据时候的没有byte,但是要理解byte其实就是无属的char
即(C没有这个类型,byte表示一个字节,对应C的unsigned char),java是没有指针概念的,,其实这里非常简单,,char*[]无非就是一个char型的数组,那么有了这条思路,我
们用String.getByteArray()
即可。转化成字节数组,那么对应的就是C中unsigned char[ ],既然数据类型匹配完成,那么就开始从java入手书写代码:
主界面:
[html] view
plaincopy
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageButton
android:id="@+id/btnOpenBT"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/bluetooth_off" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/tvDeviceName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="right"
android:text="Bluetooth"
android:textSize="14sp" />
</LinearLayout>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="写入测试" />
<EditText
android:id="@+id/output_test"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="数据回显测试" />
<TextView
android:id="@+id/input_test"
android:layout_width="fill_parent"
android:textSize="14sp"
android:layout_height="30dp" />
<Button
android:id="@+id/start_test"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="开始测试" />
<Button
android:id="@+id/btn1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="pump on" />
<Button
android:id="@+id/btn2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="pump off" />
<Button
android:id="@+id/btn3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="detector pid_fid" />
<Button
android:id="@+id/btn4"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="ignite" />
</LinearLayout>
</ScrollView>
搜索蓝牙布局界面:
[html] view
plaincopy
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/newdevice" />
<ListView
android:id="@+id/lvNewDevices"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:stackFromBottom="true" >
</ListView>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/paireddevice" />
<ListView
android:id="@+id/lvPairedDevices"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:stackFromBottom="true" >
</ListView>
<Button
android:id="@+id/btnScan"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/scan" />
</LinearLayout>
开始代码:
[java] view
plaincopy
package com.simpledraw.bluetoothservice;
import java.text.DecimalFormat;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.simpledraw.bluetooth.BluetoothCommService;
import com.simpledraw.bluetooth.BluetoothEnvironment;
import com.simpledraw.bluetooth.ConstantsBluetooth;
import com.simpledraw.bluetooth.ScanBTDeviceActivity;
import com.simpledraw.bluetooth.data.Datagram;
public class MainActivity extends Activity {
private TextView tvDirection1, tvDirection2;
private ScaleAnimation animTemperature, animHumidity;
private RotateAnimation animPressure;
private float currentDirection1 = 0, currentDirection2 = 0, currentTemperature = ConstantsEwins.MIN_TEMPERATURE_Y,
currentHumidity = 0.0f, currentPressure = 0;
DecimalFormat df = new DecimalFormat("0.00");
private ImageButton btnOpenBT = null;
private TextView tvDeviceName = null;
private Datagram datagram = new Datagram();
private BluetoothAdapter btAdapter;
private BluetoothDevice mDevice;
private int[] checked = new int[11];
private long exitTime = 0;// 用于再按一次退出
private String executStr = "";
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getBluetoothAdapter();
findAllControls();
}
private EditText output_edit;
private TextView input_edit;
private Button startTest;
private void findAllControls() {
output_edit = (EditText) findViewById(R.id.output_test);
input_edit = (TextView) findViewById(R.id.input_test);
startTest = (Button) findViewById(R.id.start_test);
((Button)findViewById(R.id.btn1)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
executStr = ((Button)v).getText().toString();
output_edit.setText("");
executStr+="\r\n";
BluetoothEnvironment.service.write(executStr.getBytes());
output_edit.setText(executStr);
}
});
((Button)findViewById(R.id.btn2)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
executStr = ((Button)v).getText().toString();
output_edit.setText(executStr);
output_edit.setText("");
executStr+="\r\n";
BluetoothEnvironment.service.write(executStr.getBytes());
}
});
((Button)findViewById(R.id.btn3)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
executStr = ((Button)v).getText().toString();
output_edit.setText(executStr);
output_edit.setText("");
executStr="log start\r\n";
BluetoothEnvironment.service.write(executStr.getBytes());
executStr="detector pid_fid\r\n";
BluetoothEnvironment.service.write(executStr.getBytes());
}
});
((Button)findViewById(R.id.btn4)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
executStr = ((Button)v).getText().toString();
output_edit.setText(executStr);
output_edit.setText("");
executStr+="\r\n";
BluetoothEnvironment.service.write(executStr.getBytes());
}
});
startTest.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
if(BluetoothEnvironment.service!=null){
output_edit.setText("");
// String outputData = output_edit.getText().toString();
executStr+="\r\n";
// byte[] bytes = outputData.getBytes();
// byte[] bytes2 = new byte[bytes.length+2];
// for(int i = 0;i<bytes.length;i++){
// bytes2[i] = bytes[i];
// }
// bytes2[bytes2.length-2] = 13;
// bytes2[bytes2.length-1] = 10;
BluetoothEnvironment.service.write(executStr.getBytes());
}
}
});
btnOpenBT = (ImageButton) findViewById(R.id.btnOpenBT);
btnOpenBT.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent intent = new Intent(MainActivity.this, ScanBTDeviceActivity.class);
startActivityForResult(intent, ConstantsBluetooth.REQUEST_CONNECT_DEVICE);
}
});
tvDeviceName = (TextView) findViewById(R.id.tvDeviceName);
for (int i = 0; i < 11; i++)
checked[i] = View.VISIBLE;
}
private void getBluetoothAdapter() {
btAdapter = BluetoothAdapter.getDefaultAdapter();
if (btAdapter == null) {
Toast.makeText(MainActivity.this, "本设备不支持蓝牙", Toast.LENGTH_SHORT).show();
finish();
return;
}
while (!btAdapter.isEnabled()) {
if (btAdapter.enable()) {
Toast.makeText(MainActivity.this, "蓝牙已经启动", Toast.LENGTH_SHORT).show();
break;
} else {
Toast.makeText(MainActivity.this, "蓝牙启动失败", Toast.LENGTH_SHORT).show();
return;
}
}
if (btAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(intent);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 1, 0, R.string.tianjiachuanganqi);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getOrder() == 0) {
Intent intent = new Intent(MainActivity.this, AddDeleteSensorsActivity.class);
intent.putExtra("checked", checked);
startActivityForResult(intent, ConstantsEwins.REQUEST_ADDDELETE_SENSORS);
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onResume() {
System.out.println("------- ON RESUME ---------");
super.onResume();
if (BluetoothEnvironment.service != null) {
if (btAdapter.isEnabled() && BluetoothEnvironment.service.getState() == ConstantsBluetooth.STATE_NONE) {
BluetoothEnvironment.service.start();
}
BluetoothEnvironment.service.setHandler(mHandler, null);
} else {
BluetoothEnvironment.service = new BluetoothCommService(this, mHandler, null);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case ConstantsBluetooth.REQUEST_CONNECT_DEVICE:
if (resultCode == RESULT_OK) {
String address = data.getExtras().getString(ConstantsBluetooth.DEVICE_ADDRESS);
mDevice = btAdapter.getRemoteDevice(address);
if (mDevice == null)
return;
if (BluetoothEnvironment.service != null)
BluetoothEnvironment.service.connect(mDevice);
}
break;
case ConstantsEwins.REQUEST_ADDDELETE_SENSORS:
if (resultCode == RESULT_OK) {
}
break;
default:
break;
}
}
@SuppressLint("HandlerLeak")
private final Handler mHandler = new Handler() {
int length = 0;
boolean firstReceived = true;
long lastReadTime = System.currentTimeMillis();
StringBuffer sb = new StringBuffer(ConstantsEwins.DATA_LENGTH);
@Override
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case ConstantsBluetooth.MESSAGE_STATE_CHANGE:
switch (msg.arg1) {
case ConstantsBluetooth.STATE_CONNECTED:
Toast.makeText(MainActivity.this, "已连接至" + msg.obj + "!!fdasfds", Toast.LENGTH_SHORT).show();
tvDeviceName.setText((String) msg.obj);
btnOpenBT.setBackgroundResource(R.drawable.bluetooth_on);
break;
case ConstantsBluetooth.STATE_CONNECTING:
Toast.makeText(MainActivity.this, "正在连接,请稍候", Toast.LENGTH_LONG).show();
break;
case ConstantsBluetooth.STATE_LISTEN:
if (ConstantsBluetooth.CONNECTION_FAILED.equals(msg.obj)) {
Toast.makeText(MainActivity.this, "连接不成功", Toast.LENGTH_SHORT).show();
btnOpenBT.setBackgroundResource(R.drawable.bluetooth_off);
} else if (ConstantsBluetooth.CONNECTION_LOST.equals(msg.obj)) {
Toast.makeText(MainActivity.this, "连接丢失", Toast.LENGTH_SHORT).show();
btnOpenBT.setBackgroundResource(R.drawable.bluetooth_off);
}
break;
case ConstantsBluetooth.STATE_NONE:
btnOpenBT.setBackgroundResource(R.drawable.bluetooth_off);
break;
}
break;
case ConstantsBluetooth.MESSAGE_WRITE:
break;
case ConstantsBluetooth.MESSAGE_READ:
if (firstReceived)
lastReadTime = System.currentTimeMillis();
firstReceived = false;
if (System.currentTimeMillis() - lastReadTime > ConstantsEwins.DATAGRAM_INTERVAL) {
if (length == ConstantsEwins.DATAGRAM_BYTES_LENGTH) {
datagram.parseDatagram(sb.toString());
modifyViews();
}
sb = new StringBuffer(ConstantsEwins.DATA_LENGTH);
length = 0;
}
String data = (String) msg.obj;
System.out.println("接收到的数据:" + data);
Log.e("texts",data);
length += msg.arg1;
sb.append(data);
lastReadTime = System.currentTimeMillis();
input_edit.setText(data);//sb.toString()
break;
}
}
};
@SuppressLint("NewApi")
private void modifyViews() {
tvDirection1.setText("风向1: " + (datagram.getDirection1() - (datagram.getDirection1() / 360) * 360) + "°");
tvDirection2.setText("风向2: " + (datagram.getDirection2() - (datagram.getDirection2() / 360) * 360) + "°");
// 风速改变
long newDuration;
newDuration = calcSpeedDuration(datagram.getSpeed1());
newDuration = calcSpeedDuration(datagram.getSpeed2());
newDuration = calcSpeedDuration(datagram.getSpeed3());
newDuration = calcSpeedDuration(datagram.getSpeed4());
newDuration = calcSpeedDuration(datagram.getSpeed5());
newDuration = calcSpeedDuration(datagram.getSpeed6());
currentDirection1 = datagram.getDirection1();
currentDirection2 = datagram.getDirection2();
// 温度、湿度和气压
float newTemperature = (datagram.getTemperature() - ConstantsEwins.MIN_TEMPERATURE_VALUE)
* ConstantsEwins.TEMPERATURE_STEP + ConstantsEwins.MIN_TEMPERATURE_Y;
float newHumidity = datagram.getHumidity() * ConstantsEwins.HUMIDITY_STEP + ConstantsEwins.MIN_HUMIDITY_Y;
float newPressure = (datagram.getPressure() - ConstantsEwins.MIN_PRESSURE_VALUE) * ConstantsEwins.PRESSURE_STEP;
animTemperature = new ScaleAnimation(1.0f, 1.0f, currentTemperature, newTemperature,
Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0.8f);
animTemperature.setDuration(500);
animTemperature.setFillAfter(true);
animHumidity = new ScaleAnimation(1.0f, 1.0f, currentHumidity, newHumidity, Animation.RELATIVE_TO_SELF, 0,
Animation.RELATIVE_TO_SELF, 0.8f);
animHumidity.setDuration(500);
animHumidity.setFillAfter(true);
animPressure = new RotateAnimation(currentPressure, newPressure, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
animPressure.setDuration(500);
animPressure.setFillAfter(true);
currentTemperature = newTemperature;
currentHumidity = newHumidity;
currentPressure = newPressure;
}
private long calcSpeedDuration(float speed) {
int level;
if (speed < 1.5f)
level = 1;
else if (speed > 1.6 && speed < 5.4)
level = 2;
else if (speed > 5.5 && speed < 7.9)
level = 3;
else if (speed > 8.0 && speed < 10.7)
level = 4;
else if (speed > 10.8 && speed < 13.8)
level = 5;
else if (speed > 13.9 && speed < 17.1)
level = 6;
else if (speed > 17.2 && speed < 20.7)
level = 7;
else if (speed > 20.8 && speed < 24.4)
level = 8;
else if (speed > 24.5 && speed < 28.4)
level = 9;
else if (speed > 28.5 && speed < 32.6)
level = 10;
else
level = 11;
long duration;
duration = (11 - level) * ConstantsEwins.SPEED_DURATION_STEP + ConstantsEwins.MIN_SPEED_DURATION;
return duration;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
if ((System.currentTimeMillis() - exitTime) > 2000) {
Toast.makeText(this, "再按一次退出程序", Toast.LENGTH_SHORT).show();
exitTime = System.currentTimeMillis();
} else {
finish();
System.exit(0);
}
return true;
}
return super.onKeyDown(keyCode, event);
}
}
[java] view
plaincopy
package com.simpledraw.bluetoothservice;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
public class DirectionPointerView extends ImageView {
private float mDirection;
private Drawable compass;
public DirectionPointerView(Context context) {
super(context);
mDirection = 0.0f;
compass = null;
}
public DirectionPointerView(Context context, AttributeSet attrs) {
super(context, attrs);
mDirection = 0.0f;
compass = null;
}
public DirectionPointerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mDirection = 0.0f;
compass = null;
}
@Override
protected void onDraw(Canvas canvas) {
if (compass == null) {
compass = getDrawable();
compass.setBounds(0, 0, getWidth(), getHeight());
}
canvas.save();
canvas.rotate(mDirection, getWidth() / 2, getHeight() / 2);
compass.draw(canvas);
canvas.restore();
}
public void updateDirection(float direction) {
mDirection = direction;
invalidate();
}
}
[java] view
plaincopy
package com.simpledraw.bluetoothservice;
public class ConstantsEwins {
public static final int REQUEST_ADDDELETE_SENSORS = 2;
public static final float MAX_SPEED_VALUE = 100;
public static final float MIN_SPEED_VALUE = 0;
public static final int MIN_SPEED_DURATION = 500;
public static final int SPEED_DURATION_STEP = 500;
public static final float MAX_TEMPERATURE_VALUE = 53;
public static final float MIN_TEMPERATURE_VALUE = -40;
public static final float MIN_TEMPERATURE_Y = 0.02f;
public static final float TEMPERATURE_STEP = 0.01185f;
public static final float MIN_HUMIDITY_Y = 0.0f;
public static final float HUMIDITY_STEP = 0.01118f;
public static final float MAX_PRESSURE_VALUE = 120;
public static final float MIN_PRESSURE_VALUE = 10;
public static final float PRESSURE_STEP = 2.38f;
public static final int DATAGRAM_INTERVAL = 500;
// 报文的字节数
public static final int DATAGRAM_BYTES_LENGTH = 20;
// 需要使用的数据长度,例如将字节变成16进制字符串的长度,0x80变成80
public static final int DATA_LENGTH = 40;
}
[java] view
plaincopy
package com.simpledraw.bluetooth.data;
import android.annotation.SuppressLint;
@SuppressLint("DefaultLocale")
public class DataTypeConverter {
public static String double2Str(double d) {
return String.format("%.1f", d);
}
public static double str2Double(String str) {
return Double.parseDouble(str);
}
public static String getMacAddress(String pStr) {
return pStr.substring(pStr.length() - 17);
}
public static double hexStr2Double(String pStr) {
int i = Integer.parseInt(pStr, 16);
double d;
if (pStr.startsWith("F")) {
d = (double) (i - 65536) / 100;
} else {
d = (double) i / 100;
}
d = ((double) Math.round(d * 10)) / 10;
return d;
}
public static float hexStr2Float(String pStr) {
return (float) (hexStr2Double(pStr));
}
public static int hexStr2Int(String pStr) {
return Integer.parseInt(pStr, 16);
}
}
[java] view
plaincopy
package com.simpledraw.bluetooth.data;
import java.text.DecimalFormat;
import com.simpledraw.bluetoothservice.ConstantsEwins;
public class Datagram {
private float speed1;
private float speed2;
private float speed3;
private float speed4;
private float speed5;
private float speed6;
private int direction1;
private int direction2;
private float temperature;
private int humidity;
private float pressure;
DecimalFormat df = new DecimalFormat(".00");
public float getSpeed1() {
return speed1;
}
public void setSpeed1(float speed1) {
this.speed1 = speed1 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE
: (speed1 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed1);
}
public float getSpeed2() {
return speed2;
}
public void setSpeed2(float speed2) {
this.speed2 = speed2 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE
: (speed2 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed2);
}
public float getSpeed3() {
return speed3;
}
public void setSpeed3(float speed3) {
this.speed3 = speed3 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE
: (speed3 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed3);
}
public float getSpeed4() {
return speed4;
}
public void setSpeed4(float speed4) {
this.speed4 = speed4 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE
: (speed4 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed4);
}
public float getSpeed5() {
return speed5;
}
public void setSpeed5(float speed5) {
this.speed5 = speed5 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE
: (speed5 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed5);
}
public float getSpeed6() {
return speed6;
}
public void setSpeed6(float speed6) {
this.speed6 = speed6 > ConstantsEwins.MAX_SPEED_VALUE ? ConstantsEwins.MAX_SPEED_VALUE
: (speed6 < ConstantsEwins.MIN_SPEED_VALUE ? ConstantsEwins.MIN_SPEED_VALUE : speed6);
}
public int getDirection1() {
return direction1;
}
public void setDirection1(int direction1) {
this.direction1 = direction1;
}
public int getDirection2() {
return direction2;
}
public void setDirection2(int direction2) {
this.direction2 = direction2;
}
public float getTemperature() {
return temperature;
}
public void setTemperature(float temperature) {
this.temperature = temperature > ConstantsEwins.MAX_TEMPERATURE_VALUE ? ConstantsEwins.MAX_TEMPERATURE_VALUE
: (temperature < ConstantsEwins.MIN_TEMPERATURE_VALUE ? ConstantsEwins.MIN_TEMPERATURE_VALUE
: temperature);
}
public int getHumidity() {
return humidity;
}
public void setHumidity(int humidity) {
this.humidity = humidity > 100 ? 100 : (humidity < 0 ? 0 : humidity);
}
public float getPressure() {
return pressure;
}
public void setPressure(float pressure) {
this.pressure = pressure > ConstantsEwins.MAX_PRESSURE_VALUE ? ConstantsEwins.MAX_PRESSURE_VALUE
: (pressure < ConstantsEwins.MIN_PRESSURE_VALUE ? ConstantsEwins.MIN_PRESSURE_VALUE : pressure);
}
public void parseDatagram(String datagram) {
// datagram = "01076954204231804B0A08072102C3046307F209";
if (datagram == null || datagram == "") {
System.out.println("kong");
return;
}
setSpeed1(calcSpeed(datagram.substring(4, 6)));
setSpeed2(calcSpeed(datagram.substring(6, 8)));
setSpeed3(calcSpeed(datagram.substring(8, 10)));
setSpeed4(calcSpeed(datagram.substring(10, 12)));
setSpeed5(calcSpeed(datagram.substring(12, 14)));
setSpeed6(calcSpeed(datagram.substring(14, 16)));
setDirection1(calcDirection(datagram.substring(22, 24) + datagram.substring(20, 22)));
setDirection2(calcDirection(datagram.substring(26, 28) + datagram.substring(24, 26)));
setTemperature(calcTemperature(datagram.substring(30, 32) + datagram.substring(28, 30)));
setHumidity(calcHumidity(datagram.substring(34, 36) + datagram.substring(32, 34)));
setPressure(calcPressure(datagram.substring(38, 40) + datagram.substring(36, 38)));
}
private float calcSpeed(String pStrSpeedHex) {
float speed = DataTypeConverter.hexStr2Int(pStrSpeedHex);
return speed * 0.765f + 0.35f;
}
private int calcDirection(String pStrDirectionHex) {
int direction = DataTypeConverter.hexStr2Int(pStrDirectionHex);
return (int) (direction * 0.094230277);
}
private float calcTemperature(String pStrTempHex) {
float temperature = DataTypeConverter.hexStr2Int(pStrTempHex);
return (float) (temperature * 0.088695557 - 86.38);
}
private int calcHumidity(String pStrHumidityHex) {
int humidity = DataTypeConverter.hexStr2Int(pStrHumidityHex);
return (int) (humidity * 0.031933594);
}
private float calcPressure(String pStrPressureHex) {
float pressure = DataTypeConverter.hexStr2Int(pStrPressureHex);
return (float) (pressure * 0.03479165 + 10.55);
}
}
[html] view
plaincopy
package com.simpledraw.bluetooth;
import java.util.Set;
import android.app.Activity;
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.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import com.simpledraw.bluetooth.data.DataTypeConverter;
import com.simpledraw.bluetoothservice.R;
public class ScanBTDeviceActivity extends Activity {
private Button btnScan = null;
private ListView lvNewDevices, lvPairedDevices;
private ArrayAdapter<String> adapterNewDevices, adapterPairedDevice;
private BluetoothAdapter btAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Setup the window
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.device_list);
findAllViews();
btAdapter = BluetoothAdapter.getDefaultAdapter();
if (btAdapter == null) {
finish();
return;
}
Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();
for (BluetoothDevice device : pairedDevices) {
adapterPairedDevice.add(device.getName() + "\n" + device.getAddress());
}
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mReceiver, filter);
}
private void findAllViews() {
btnScan = (Button) findViewById(R.id.btnScan);
lvNewDevices = (ListView) findViewById(R.id.lvNewDevices);
adapterNewDevices = new ArrayAdapter<String>(ScanBTDeviceActivity.this, android.R.layout.simple_list_item_1);
lvNewDevices.setAdapter(adapterNewDevices);
lvNewDevices.setOnItemClickListener(DeviceListClickListener);
lvPairedDevices = (ListView) findViewById(R.id.lvPairedDevices);
adapterPairedDevice = new ArrayAdapter<String>(ScanBTDeviceActivity.this, android.R.layout.simple_list_item_1);
lvPairedDevices.setAdapter(adapterPairedDevice);
lvPairedDevices.setOnItemClickListener(DeviceListClickListener);
btnScan.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
discoverDevices();
}
});
}
private void discoverDevices() {
btnScan.setEnabled(false);
setTitle(R.string.scanning);
if (btAdapter.isDiscovering()) {
btAdapter.cancelDiscovery();
}
btAdapter.startDiscovery();
}
private OnItemClickListener DeviceListClickListener = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
btAdapter.cancelDiscovery();
String address = DataTypeConverter.getMacAddress(((TextView) arg1).getText().toString());
Intent intent = new Intent();
intent.putExtra(ConstantsBluetooth.DEVICE_ADDRESS, address);
setResult(RESULT_OK, intent);
finish();
}
};
@Override
protected void onDestroy() {
super.onDestroy();
if (btAdapter != null) {
btAdapter.cancelDiscovery();
}
unregisterReceiver(mReceiver);
};
private final BroadcastReceiver mReceiver = 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);
if (device.getBondState() != BluetoothDevice.BOND_BONDED)
adapterNewDevices.add(device.getName() + "\n" + device.getAddress());
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
btnScan.setEnabled(true);
setTitle(R.string.select_device);
}
}
};
}
[java] view
plaincopy
package com.simpledraw.bluetooth;
import java.util.UUID;
public class ConstantsBluetooth {
public static final int REQUEST_CONNECT_DEVICE = 1;
public static final String DEVICE_ADDRESS = "deviceaddress";
public static final String CONNECTED_DEVICE_NAME = "connecteddevicename";
public static final String SERVER_NAME = "BluetoothComm";
public static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
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 STATE_NONE = 0; // do nothing
public static final int STATE_LISTEN = 1; // 监听连接
public static final int STATE_CONNECTING = 2; // now initiating an outgoing
public static final int STATE_CONNECTED = 3; // 已连接上远程设备
public static final String CONNECTION_FAILED = "fail";
public static final String CONNECTION_LOST = "lost";
public static final String CONNECTION_CONNECTED = "connected";
public static final String COMMAND_1 = "uLPCC_0000CD?";
public static final byte[] COMMAND_ACK = new byte[] { (byte) 0x06 };
}
[java] view
plaincopy
package com.simpledraw.bluetooth;
public class BluetoothEnvironment {
public static BluetoothCommService service;
}
[java] view
plaincopy
package com.simpledraw.bluetooth;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.UUID;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;
public class BluetoothCommService implements Serializable {
private static final long serialVersionUID = 1L;
private static final String NAME = "BluetoothComm";
// SPP协议UUID
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
// Member fields
private final BluetoothAdapter mAdapter;
private Handler mHandler, receiveHandler;
private int mState;
private AcceptThread mAcceptThread;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
public BluetoothCommService(Context context, Handler handler, Handler p_receiveHandler) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
mHandler = handler;
receiveHandler = p_receiveHandler;
mState = ConstantsBluetooth.STATE_NONE;
}
public void setHandler(Handler pHandler, Handler p_receiveHandler) {
mHandler = pHandler;
receiveHandler = p_receiveHandler;
}
/**
* Set the current state of the chat connection
*
* @param state
* An integer defining the current connection state
*/
private synchronized void setState(int state) {
mState = state;
mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}
/**
* Return the current connection state.
*/
public synchronized int getState() {
return mState;
}
/**
* 开始服务,主要是开始AcceptThread线程,打开一个监听回话由BaowenActivity的onResume方法调用,
* ***开启监听线程****
*/
public synchronized void start() {
// 取消所有正在尝试连接的线程
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
// 取消所有已经连接上的线程
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
// 打开一个监听BluetoothServerSocket的线程
if (mAcceptThread == null) {
mAcceptThread = new AcceptThread();
mAcceptThread.start();// 开启监听线程
}
setState(ConstantsBluetooth.STATE_LISTEN);
}
/**
* Start the ConnectThread to initiate a connection to a remote device.
*
* @param device
* The BluetoothDevice to connect
*/
public synchronized void connect(BluetoothDevice device) {
// Cancel any thread attempting to make a connection
if (mState == ConstantsBluetooth.STATE_CONNECTING) {// 正在连接状态״̬
if (mConnectThread != null) {// 有ConnectThread,结束
mConnectThread.cancel();
mConnectThread = null;
}
}
// Cancel any thread currently running a connection
if (mConnectedThread != null) {// 有处于连接中的线程,结束
mConnectedThread.cancel();
mConnectedThread = null;
}
// Start the thread to connect with the given device
mConnectThread = new ConnectThread(device);
mConnectThread.start();// 开启新的连接请求线程
setState(ConstantsBluetooth.STATE_CONNECTING);
}
/**
* Start the ConnectedThread to begin managing a Bluetooth connection
*
* @param socket
* The BluetoothSocket on which the connection was made
* @param device
* The BluetoothDevice that has been connected
*/
public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
// Cancel the thread that completed the connection
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
// Cancel any thread currently running a connection
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = 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 = new ConnectedThread(socket);
mConnectedThread.start();// 和客户端开始通信
// 把已连接的设备的名称发给UI线程
Message msg = mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_STATE_CHANGE);
msg.arg1 = ConstantsBluetooth.STATE_CONNECTED;
msg.obj = device.getName();
mHandler.sendMessage(msg);
mState = ConstantsBluetooth.STATE_CONNECTED;
}
/**
* Stop all threads
*/
public synchronized void stop() {
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
if (mAcceptThread != null) {
mAcceptThread.cancel();
mAcceptThread = null;
}
setState(ConstantsBluetooth.STATE_NONE);
}
/**
* Write to the ConnectedThread in an unsynchronized manner
*
* @param out
* The bytes to write
* @see ConnectedThread#write(byte[])
*/
public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != ConstantsBluetooth.STATE_CONNECTED)
return;
r = mConnectedThread;// 得到连接线程
}
// Perform the write unsynchronized
r.write(out);
}
/**
* Indicate that the connection attempt failed and notify the UI Activity.
*/
private void connectionFailed() {
setState(ConstantsBluetooth.STATE_LISTEN);
// // Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_STATE_CHANGE);
msg.obj = "fail";
mHandler.sendMessage(msg);
}
/**
* Indicate that the connection was lost and notify the UI Activity.
*/
@SuppressWarnings("unused")
private void connectionLost() {
setState(ConstantsBluetooth.STATE_LISTEN);
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_STATE_CHANGE);
msg.obj = "lost";
mHandler.sendMessage(msg);
}
/**
* This thread runs while listening for incoming connections. It behaves
* like a server-side client. It runs until a connection is accepted (or
* until cancelled). 监听准备进入的连接,类似于服务端,
*/
private class AcceptThread extends Thread {
// 本地的socket
private final BluetoothServerSocket mmServerSocket;
public AcceptThread() {
BluetoothServerSocket tmp = null;
// 创建一个新的监听服务器socket
try {
// 根据名称,UUID创建并返回BluetoothServerSocket,这是创建BluetoothSocket服务器端的第一步
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, SPP_UUID);
} catch (IOException e) {
}
// 得到BluetoothServerSocket对象
mmServerSocket = tmp;
}
public void run() {
setName("AcceptThread");// set the name of thread
BluetoothSocket socket = null;
// Listen to the server socket if we're not connected
while (mState != ConstantsBluetooth.STATE_CONNECTED) {// 若没有连接,一直执行
try {
// 注意:BluetoothServerSocket的accept是一个阻塞性线程,一直到用户成功的配对,因此不要放在Activity中,
// 远程蓝牙设备请求跟本设备建立连接请求时,
// BluetoothServerSocket会在连接被接收时返回一个被连接的BluetoothSocket对象。
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// 连接建立成功
if (socket != null) {
synchronized (BluetoothCommService.this) {
switch (mState) {
case ConstantsBluetooth.STATE_LISTEN:
case ConstantsBluetooth.STATE_CONNECTING:
// 已经连接上,开始ConnectedThread线程
connected(socket, socket.getRemoteDevice());
break;
case ConstantsBluetooth.STATE_NONE:
case ConstantsBluetooth.STATE_CONNECTED:
// 或者设备没有准备好,或者已经连接,都将这个新的BluetoothSocket关掉
// 释放服务套接字,但不会关闭accept()返回的BluetoothSocket
try {
socket.close();
} catch (IOException e) {
}
break;
}
}
}
}
}
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) {
}
}
}
/**
* This thread runs while attempting to make an outgoing connection with a
* device. It runs straight through; the connection either succeeds or
* fails. 监听准备出去的连接
*/
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;// 远程设备
public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
// 通过远程设备直接创建一个BluetoothSocket,要求该设备已经打开了BluetoothServerSocket获得一个BluetoothSocket对象
tmp = device.createRfcommSocketToServiceRecord(SPP_UUID);
} catch (IOException e) {
}
mmSocket = tmp;
}
public void run() {
setName("ConnectThread");
// 取消搜索
mAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mmSocket.connect();
} catch (IOException e) {
connectionFailed();
// Close the socket
try {
mmSocket.close();
} catch (IOException e2) {
}
// Start the service over to restart listening mode
BluetoothCommService.this.start();
return;
}
// Reset the ConnectThread because we're done
synchronized (BluetoothCommService.this) {
mConnectThread = null;
}
// Start the connected thread,已连接上,管理连接
connected(mmSocket, mmDevice);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
}
/**
* This thread runs during a connection with a remote device. It handles all
* incoming and outgoing transmissions. 监听
*/
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final OutputStream mmOutStream;
private final BufferedInputStream reader;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
}
reader = new BufferedInputStream(tmpIn);
mmOutStream = tmpOut;
}
private String dataStr = "";
@SuppressLint("NewApi")
public void run() {
byte[] buffer = new byte[44], temp = new byte[127];
StringBuffer sb;
String b;
int numReadedBytes;
boolean cleaning = true;
long startTime = System.currentTimeMillis();
// 保持对InputStream的监听
while (true) {
try {
// if (cleaning) {
//// if (System.currentTimeMillis() - startTime < 2000) {
//
//
//
// numReadedBytes = reader.read(temp);
// // System.out.println("cleaning:" + numReadedBytes);
// continue;
//// } else
//// cleaning = false;
// }
numReadedBytes = reader.read(buffer);//temp
String tempStr = new String(buffer);//temp write to log
tempStr.replace("\r\n", "***");
String[] strs = tempStr.split("\r\n");
// System.out.println("numReaded0:" + numReadedBytes);
Log.d("texts",tempStr);
sb = new StringBuffer();
// for (int i = 0; i < numReadedBytes; i++) {
// b = Integer.toHexString(buffer[i] & 0xFF);
// if (b.length() < 2)
// sb.append("0");
// sb.append(b);
// }
mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_READ, numReadedBytes, 0, new String(buffer))
.sendToTarget();
buffer = new byte[44];
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Write to the connected OutStream.
*
* @param buffer
* The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
mHandler.obtainMessage(ConstantsBluetooth.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
} catch (IOException e) {
e.printStackTrace();
Log.i("texts", "数据流写入失败");
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
}
}
}
}
OK,,,这样我所以项目都贴到上面了,,因为个人原因,不能贴项目源码,,但是改了一个项目,,亲测可用,,
我们要重点注意这里
MainActivity.java:
[java] view
plaincopy
((Button)findViewById(R.id.btn1)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
executStr = ((Button)v).getText().toString();
output_edit.setText("");
executStr+="\r\n";
BluetoothEnvironment.service.write(executStr.getBytes());
output_edit.setText(executStr);
}
});
这段是真实向下位机写数据,,如果你项目非常紧急,建议直接找到此处,修改这里,还有类似位置,然后我们在看看S端Return的值:
MainActivity.java:
[java] view
plaincopy
case ConstantsBluetooth.MESSAGE_READ:
if (firstReceived)
lastReadTime = System.currentTimeMillis();
firstReceived = false;
if (System.currentTimeMillis() - lastReadTime > ConstantsEwins.DATAGRAM_INTERVAL) {
if (length == ConstantsEwins.DATAGRAM_BYTES_LENGTH) {
datagram.parseDatagram(sb.toString());
modifyViews();
}
sb = new StringBuffer(ConstantsEwins.DATA_LENGTH);
length = 0;
}
String data = (String) msg.obj;
System.out.println("接收到的数据:" + data);
Log.e("texts",data);
length += msg.arg1;
sb.append(data);
lastReadTime = System.currentTimeMillis();
input_edit.setText(data);//sb.toString()
break;
以上即可与下位机交互,,,图片资源请自行寻找,,懒得贴了,,不做伸手党!!!
相关文章推荐
- Android开源项目分类汇总
- android EditText 默认情况下不获取焦点(不弹出输入框)
- Android学习 - 判断手机是否为双卡并发短信
- Android ViewGroup事件分发机制(下)
- Android图片异步加载框架Android-Universal-Image-Loader
- 【转】android权限列表
- Android学习 - 拨号盘dialer定制声音DTMF Tones
- 史上最简单android动画之Tween Animation(渐变动画)
- 介绍一款比Android原生模拟器还要快的模拟器Genymotion(转)
- Android4.2耳机插拔检测实现方法
- android 逆向 去广告
- Android:Listview中嵌套viewpager的实现总结
- Android实战简易教程-第七枪(Activity的启动模式)
- "Selenium for Android"的Robotium 二 概述
- android 代码混淆排除指定内部类
- 使用Adt自带的工具进行Android自动化测试(三)
- Android View 事件分发机制 源码解析 (上)
- Android 屏幕适配
- 使用Adt自带的工具进行Android自动化测试(二)
- android图片缓存策略