android蓝牙可以进行短距离的数据传输(10m内),所以可用于智能控制。
研究了几天,mark一下具体的操作;
1、蓝牙相关的类
1)BluetoothAdapter :操作本机的蓝牙
1.1)获取本机蓝牙:BluetoothAdapter.getDefaultAdapter(); 如果返回null,则表示此手机不支持蓝牙。
1.2)开启蓝牙:
Intent intent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivity(intent);
1.3)获取已配对的设备:bluetoothAdapter.getBondedDevices();返回Set<BluetoothDevice>;
1.4)根据物理地址获取蓝牙设备:bluetoothAdapter.getRemoteDevice(device.getAddress());返回BluetoothDevice;
1.5)根据bluetoothDevice.createInsecureRfcommSocketToServiceRecord(UUID);获取BluetoothSocket;
2)BluetoothSocket/BluetoothServerSocket:用于蓝牙间的数据通信;用法类似于Socket/ServerSocket;具体可参见API。
2、代码实现
写了一个简单的蓝牙通信程序,代码如下:
1)权限设置:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />//作为服务器端时的权限
2)扫描所有可用设备:
bluetoothAdapter.getBondedDevices();获取已配对的设备;
bluetoothAdapter.startDiscovery();获取可配对的设备。注册一个广播接收器捕获设备发现其他蓝牙设备的时候发出的广播;
点击蓝牙设备,进入通信界面;
package com.dream.bluetoothcontrol;
import java.util.ArrayList;
import java.util.Set;
import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
public class MainActivity extends Activity {
private ListView listview;
private Button btnSearch;
private BluetoothAdapter bluetoothAdapter;
private ArrayList<Device> deviceList=new ArrayList<Device>();
private DeviceAdapter deviceAdapter;
private DeviceSearchBroadcastReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.device_found_fragment);
init();
}
private void init() {
bluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
// no blueTooth
if(bluetoothAdapter==null){
showPromptDialog(getResources().getString(R.string.msg_no_support_bluetooth));
}
receiver=new DeviceSearchBroadcastReceiver();
IntentFilter filter=new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(receiver,filter);
initView();
}
private void initView() {
listview=(ListView)findViewById(R.id.lv_devicefound_devicelist);
deviceAdapter=new DeviceAdapter(deviceList, this);
listview.setAdapter(deviceAdapter);
listview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
if(deviceAdapter.getItem(arg2).getType()
==DeviceAdapter.VIEW_TYPE_DEVICE)
clickItem(deviceAdapter.getItem(arg2));
}
});
btnSearch=(Button)findViewById(R.id.btn_devicefound_search);
btnSearch.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
searchBoundedDevice();
}
});
}
protected void searchBoundedDevice() {
if(bluetoothAdapter.isDiscovering()){
}else{
deviceList.clear();
Set<BluetoothDevice> btdSet=bluetoothAdapter.getBondedDevices();
deviceList.add(new Device("Bounded Device",null,true,DeviceAdapter.VIEW_TYPE_HEADER));
if(btdSet.size()>0){
for(BluetoothDevice btd : btdSet){
Device device=new Device();
device.setName(btd.getName());
device.setAddress(btd.getAddress());
device.setSiri(true);
device.setType(deviceAdapter.VIEW_TYPE_DEVICE);
deviceList.add(device);
}
deviceAdapter.dataChanged(deviceList);
listview.setSelection(listview.getCount()-1);
}
deviceList.add(new Device("Avaliable Device",null,false,DeviceAdapter.VIEW_TYPE_HEADER));
bluetoothAdapter.startDiscovery();
}
}
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
// open bluetooth
if(!bluetoothAdapter.isEnabled()){
Intent intent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivity(intent);
}
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
this.unregisterReceiver(receiver);
}
private void showPromptDialog(String msg){
AlertDialog.Builder builder=new AlertDialog.Builder(this);
builder.setTitle("Tips");
builder.setMessage(msg);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.show();
}
private void clickItem(Device device) {
Intent intent=new Intent(MainActivity.this,ChatActivity.class);
intent.putExtra("device", device);
startActivity(intent);
}
class DeviceSearchBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String action=intent.getAction();
Device boundedDevice=new Device();
// find a new device add into the devicelist
if(BluetoothDevice.ACTION_FOUND.equals(action)){
BluetoothDevice device=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(device.getBondState()!=BluetoothDevice.BOND_BONDED){
boundedDevice.setName(device.getName());
boundedDevice.setAddress(device.getAddress());
boundedDevice.setSiri(false);
boundedDevice.setType(DeviceAdapter.VIEW_TYPE_DEVICE);
}
}else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
if(listview.getCount()==0){
boundedDevice.setName("no device to bound");
boundedDevice.setAddress("");
boundedDevice.setSiri(false);
boundedDevice.setType(DeviceAdapter.VIEW_TYPE_DEVICE);
deviceList.add(boundedDevice);
}
}
deviceList.add(boundedDevice);
deviceAdapter.dataChanged(deviceList);
listview.setSelection(listview.getCount()-1);
}
}
}
3)与其他蓝牙设备进行通信:
获取BluetoothSocket来进行通信;使用Handler进行UI操作;
package com.dream.bluetoothcontrol;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.UUID;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
public class ChatActivity extends Activity {
private ListView listView;
private Button btnSend;
private EditText etSend;
private ArrayList<SiriMessage> msgList = new ArrayList<ChatActivity.SiriMessage>();
private ChatMsgAdapter adapter;
private Device device;
private BluetoothAdapter bluetoothAdapter;
private BluetoothDevice btd;
private BluetoothSocket socket;
private ConnectionThread connectionThread;
private ReceiveThread receiveThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.chat_fragment);
device = (Device) this.getIntent().getSerializableExtra("device");
initView();
initSocket();
}
private void initView() {
listView = (ListView) findViewById(R.id.lv_chatFragment_chatlist);
adapter = new ChatMsgAdapter(msgList, this);
listView.setAdapter(adapter);
etSend = (EditText) findViewById(R.id.et_chatfragment_sendmsg);
btnSend = (Button) findViewById(R.id.btn_chatfragment_send);
btnSend.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
sendMessage();
}
});
}
protected void sendMessage() {
String msgToSend = etSend.getText().toString();
if (msgToSend.length() > 0) {
sendMessage(msgToSend);
etSend.getText().clear();
InputMethodManager manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
manager.hideSoftInputFromWindow(etSend.getWindowToken(), 0);
} else {
Toast.makeText(ChatActivity.this,
"the messge to send cannot be null", Toast.LENGTH_LONG)
.show();
}
}
@SuppressLint("NewApi")
public void sendMessage(final String msg) {
if (socket == null) {
Toast.makeText(ChatActivity.this, "no connection",
Toast.LENGTH_SHORT).show();
return;
}
try {
OutputStream os = socket.getOutputStream();
os.write(msg.getBytes());
handler.obtainMessage(1, msg).sendToTarget();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@SuppressLint("NewApi")
private void initSocket() {
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
btd = bluetoothAdapter.getRemoteDevice(device.getAddress());
connectionThread = new ConnectionThread();
connectionThread.start();
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
}
protected void onDestroy() {
super.onDestroy();
new Thread() {
@Override
public void run() {
try {
if (connectionThread != null) {
connectionThread.interrupt();
connectionThread = null;
}
if (receiveThread != null) {
receiveThread.interrupt();
receiveThread = null;
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
socket = null;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
};
class ConnectionThread extends Thread {
@SuppressLint("NewApi")
@Override
public void run() {
try {
socket = btd.createInsecureRfcommSocketToServiceRecord(UUID
.fromString(Const.uuid));
handler.obtainMessage(0, "connecting,please wait a second")
.sendToTarget();
socket.connect();
handler.obtainMessage(0, "connected success").sendToTarget();
receiveThread = new ReceiveThread();
receiveThread.start();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
handler.obtainMessage(0, "there are some mistake please try again").sendToTarget();
}
}
}
class ReceiveThread extends Thread {
@Override
public void run() {
InputStream is = null;
try {
is = socket.getInputStream();
} catch (Exception e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
byte[] buffer = new byte[1024];
int len;
while (true) {
try {
if ((len = is.read(buffer)) > 0) {
byte[] data = new byte[len];
for (int i = 0; i < len; i++) {
data[i] = buffer[i];
}
String msg = new String(data);
handler.obtainMessage(0, msg).sendToTarget();
}
} catch (Exception e) {
try {
is.close();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
}
class SendThread extends Thread {
private String msg;
public SendThread(String msg) {
this.msg = msg;
}
@Override
public void run() {
try {
OutputStream os = socket.getOutputStream();
os.write(msg.getBytes());
handler.obtainMessage(1, msg).sendToTarget();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
String sms = (String) msg.obj;
SiriMessage sm = null;
switch (msg.what) {
case 0:
sm = new SiriMessage(sms, false);
break;
case 1:
sm = new SiriMessage(sms, true);
break;
}
msgList.add(sm);
adapter.dataChanged(msgList);
};
};
class SiriMessage {
private String msg;
private boolean isSiri;
public SiriMessage(String msg, boolean isSiri) {
super();
this.msg = msg;
this.isSiri = isSiri;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public boolean isSiri() {
return isSiri;
}
public void setSiri(boolean isSiri) {
this.isSiri = isSiri;
}
}
}
4)效果图
在进行测试的过程中,如果没有两台手机,可以使用串口小助手,在PC端设置一个蓝牙接收器,就可以很方便的进行测试了
其他相关的蓝牙开发资料:
常用API:http://blog.csdn.net/xingfuyusheng/article/details/6745560