android蓝牙调了几天,终于可以收发数据了,尽管还没有完全排除异常,至少在通信过程上算是已经打通了。下面就来总结一下,希望对于没有接触过蓝牙,和刚开始android编程的朋友有帮助。
首先我们先说一下,在android操作系统中可对蓝牙做得工作。
对蓝牙的操作分两种,一种是系统操作,一种是应用操作。
系统可对蓝牙做所有外部操作,包括开启,关闭,设置可见性,扫描周围设备,匹配及取消等等;应用可以对蓝牙做以上大部分操作,除了匹配操作不能在应用中使用代码完成。换句话说,如果您的应用程序中使用到蓝牙,则要保证使用前,手动在android操作系统中完成目标机之间的匹配工作。
接下来说一下,介绍一下两部android手机,使用蓝牙通信的过程。
两部手机通过蓝牙通信,则一定要其中一台是服务器端,另一台是客户端。蓝牙设备在本地叫BluetoothAdapter,本地获取到的其他蓝牙设备叫BluetoothDevice。下面分别介绍在服务器端和客户端上程序的操作过程。为方便理解两者分开介绍,但在具体实现过程中有些代码可以融合。具体代码可下载http://download.csdn.net/detail/eric41050808/6614225,参阅。
在服务器端,注意如下几点:
1.一定要保证通信双方已经手动完成匹配;
2.服务端要开启可见性,以便客户端搜索到;
3.使用BluetoothServerSocket的方法listenUsingRfcommWithServiceRecord()获取ServerSocket对象,再使用ServerSocket的accept()方法阻塞接收请求者的连接请求,成功后该方法返回BluetoothSocket对象;
4.使用获取到的socket对象的输入输出流方法操作数据通信,接收到的数据一定要通过handler处理显示。
在客户端,注意如下几点:
1.同样,一定要保证蓝牙开启,且通信双方已经手动完成匹配;
2.通过广播扫描周围可用设备,并确定该设备已与本机完成匹配;
3.使用上步扫描到的device对象,调用createRfcommSocketToServiceRecord()方法,获取BluetoothSocket对象,并用该对象调用connect()方法想服务器提出连接请求。注意此连接请求过程要循环请求,直至完成连接。
首先我们先说一下,在android操作系统中可对蓝牙做得工作。
对蓝牙的操作分两种,一种是系统操作,一种是应用操作。
系统可对蓝牙做所有外部操作,包括开启,关闭,设置可见性,扫描周围设备,匹配及取消等等;应用可以对蓝牙做以上大部分操作,除了匹配操作不能在应用中使用代码完成。换句话说,如果您的应用程序中使用到蓝牙,则要保证使用前,手动在android操作系统中完成目标机之间的匹配工作。
接下来说一下,介绍一下两部android手机,使用蓝牙通信的过程。
两部手机通过蓝牙通信,则一定要其中一台是服务器端,另一台是客户端。蓝牙设备在本地叫BluetoothAdapter,本地获取到的其他蓝牙设备叫BluetoothDevice。下面分别介绍在服务器端和客户端上程序的操作过程。为方便理解两者分开介绍,但在具体实现过程中有些代码可以融合。具体代码可下载http://download.csdn.net/detail/eric41050808/6614225,参阅。
在服务器端,注意如下几点:
1.一定要保证通信双方已经手动完成匹配;
2.服务端要开启可见性,以便客户端搜索到;
3.使用BluetoothServerSocket的方法listenUsingRfcommWithServiceRecord()获取ServerSocket对象,再使用ServerSocket的accept()方法阻塞接收请求者的连接请求,成功后该方法返回BluetoothSocket对象;
4.使用获取到的socket对象的输入输出流方法操作数据通信,接收到的数据一定要通过handler处理显示。
在客户端,注意如下几点:
1.同样,一定要保证蓝牙开启,且通信双方已经手动完成匹配;
2.通过广播扫描周围可用设备,并确定该设备已与本机完成匹配;
3.使用上步扫描到的device对象,调用createRfcommSocketToServiceRecord()方法,获取BluetoothSocket对象,并用该对象调用connect()方法想服务器提出连接请求。注意此连接请求过程要循环请求,直至完成连接。
4.使用此连接的socket对象的输入输出流方法操作数据通信,接收到的数据一定要通过handler处理显示。
程序界面:
文件名Bluetooth_MainActivity.java:
package thu.wolf.bluetooth;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class Bluetooth_MainActivity extends Activity {
private Button conn = null;
private Button server = null;
private Button client = null;
private Button send = null;
private EditText msg = null;
private BluetoothRev bluetoothRev = null;
private BluetoothAdapter adapter = null;
private BluetoothDevice device = null;
private static final String S_NAME = "BluetoothChat";
private static final UUID S_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private InputStream m_InputStream = null;
private OutputStream m_OutputStream = null;
private String address = null;
boolean serverflag ;
private String TAG = "catch";
private static final String MESSAGE_READ = "Message_Read";
private ArrayList<String> blueToothNames = null;
private ArrayList<BluetoothDevice> blutToothDevices = null;
private HandlerThread handlerThread = null;
private MyHandler transHandler = null;
boolean isfound = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bluetooth__main);
conn = (Button)findViewById(R.id.conn);
server = (Button)findViewById(R.id.server);
client = (Button)findViewById(R.id.client);
// client.setEnabled(false);
send = (Button)findViewById(R.id.send);
msg = (EditText)findViewById(R.id.msg);
conn.setOnClickListener(new connOnClickListener());
server.setOnClickListener(new serverOnClickListener());
client.setOnClickListener(new clientOnClickListener());
send.setOnClickListener(new sendOnClickListener());
blueToothNames = new ArrayList<String>();
blutToothDevices = new ArrayList<BluetoothDevice>();
//获取一个蓝牙适配器
adapter = BluetoothAdapter.getDefaultAdapter();
if( adapter != null)//判断是否为空
{
System.out.println("本机拥有蓝牙设备。");
if(!adapter.isEnabled())//判断当前蓝牙设备是否可用
{
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);//创建一个Intent对象,用于启动一个activity,来提示用户开启蓝牙
startActivity(intent);//开启一个activity提醒有应用要开启蓝牙
}
else
Toast.makeText(this, "蓝牙已开启,可以启动服务", 50).show();
}
else
System.out.println("没有蓝牙设备!");
//生成一个HandlerThread对象,实现了使用Looper来处理消息队列的功能,这个类由Android应用程序框架提供
handlerThread = new HandlerThread("handler_thread");
//在使用HandlerThread的getLooper()方法之前,必须先调用该类的start();
handlerThread.start();//只能在主线程中开启此线程
transHandler = new MyHandler(handlerThread.getLooper());
}
class MyHandler extends Handler {
public MyHandler() {
}
public MyHandler(Looper L) {
super(L);
}
// 子类必须重写此方法,接受数据
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
Log.d("MyHandler", "handleMessage......");
super.handleMessage(msg);
// 此处可以更新UI
byte[] buffer = new byte[1024];
buffer = (byte[])msg.obj;
String str = new String(buffer, 0, msg.arg1);
System.out.println(str);
}
}
class serverOnClickListener implements OnClickListener{
@Override
public void onClick(View v) {
serverflag = true;
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 350);
startActivity(intent);
client.setEnabled(false);
conn.setEnabled(false);
RequestAcceptThread ServerThread = new RequestAcceptThread();
ServerThread.start();
}
}
class clientOnClickListener implements OnClickListener{
@Override
public void onClick(View v) {
bluetoothRev = new BluetoothRev();
//创建intentfilter及广播接收函数
IntentFilter discoveryfilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(bluetoothRev, discoveryfilter);
IntentFilter foundfilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(bluetoothRev, foundfilter);
adapter.startDiscovery();
msg.setText("正在扫描");
server.setEnabled(false);
}
}
private class BluetoothRev extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action))
{
// Get the BluetoothDevice object from the Intent
//BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//blutToothDevices.add(device);
//blueToothNames.add(device.getName());
isfound = true;
Toast.makeText(Bluetooth_MainActivity.this, "已获取设备,可连接", 50).show();
// When discovery is finished, change the Activity title
}
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action))
{
if(isfound == false)
msg.setText("未发现设备,重新搜索");//此action只表示发现结束,可以是发现了设备,也可以是没有发现到设备
else
{
msg.setText("发现设备");
}
adapter.cancelDiscovery();
Bluetooth_MainActivity.this.unregisterReceiver(this);
}
}
}
//获取bluetoothAdapter适配器
class connOnClickListener implements OnClickListener{
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
RequestThread ClientThread = new RequestThread( device );
ClientThread.start();
}
}
class sendOnClickListener implements OnClickListener{
@Override
public void onClick(View v) {
String data = "hello world!";
try {
m_OutputStream.write(data.getBytes());
System.out.println(data);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("数据发送失败!");
}
System.out.println("数据已发出");
}
}
/*作为服务端应答socket请求,得到socket */
public class RequestAcceptThread extends Thread{
private BluetoothServerSocket m_BluetoothServersocket = null;
public RequestAcceptThread(){
BluetoothServerSocket tmpBluetoothServersocket = null;
try{
tmpBluetoothServersocket = adapter.listenUsingRfcommWithServiceRecord(S_NAME, S_UUID);
}catch(IOException e){}
m_BluetoothServersocket = tmpBluetoothServersocket;
System.out.println("服务已开启");
msg.setText("服务已开启");
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
//阻塞监听直到异常出现或者有socket返回
BluetoothSocket socket = null;
while(true)
{
try{
//System.out.println("waiting。。。。");
//msg.setText("等待请求");
socket = m_BluetoothServersocket.accept();
if(socket != null) break;
}catch(IOException e){
System.out.println("exception while waiting");
break;
}
}
System.out.println("接收到请求!");
if(socket != null){
System.out.println("连接已建立");
ConnectedThread readthread = new ConnectedThread(socket);
readthread.start();
}
}
//取消socket监听,关闭线程
public void cancel(){
try{
m_BluetoothServersocket.close();
}catch(IOException e){}
}
}
private class RequestThread extends Thread {
private BluetoothSocket mmSocket = null;
private BluetoothDevice mmDevice = null;
public RequestThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
//mmDevice = device;
msg.setText("开始申请连接");
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
//System.out.println("ask for connection");
tmp = device.createRfcommSocketToServiceRecord(S_UUID);
} catch (IOException e) { }
if( tmp != null){
mmSocket = tmp;
Toast.makeText(Bluetooth_MainActivity.this, "socket is ok!", 100);
}
}
public void run() {
// Cancel discovery because it will slow down the connection
while(true){//必须多次连接以保证成功连接
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
System.out.println("try to connection");
mmSocket.connect();
if(mmSocket != null)
{
//mSocketManage(mmSocket);
ConnectedThread readthread = new ConnectedThread(mmSocket);
readthread.start();
break;
}
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
System.out.println("unable to connection");
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
}
}
System.out.println("连接成功,可发送数据");
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.bluetooth__main, menu);
return true;
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
unregisterReceiver(bluetoothRev);
super.onDestroy();
}
//
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
Message msg = transHandler.obtainMessage();
public ConnectedThread(BluetoothSocket socket) {
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) { }
m_InputStream = tmpIn;
m_OutputStream= 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 = m_InputStream.read(buffer);
msg.obj = buffer;
msg.arg1 = bytes;
transHandler.sendMessage(msg);
// Send the obtained bytes to the UI Activity
//transHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();
} 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);
m_OutputStream.write(bytes);
} catch (IOException e) { }
}
/* Call this from the main Activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
}
此程序仅供测试使用,还有异常没有调试,且操作不太方便,不建议直接运行,可下载源码参阅http://download.csdn.net/detail/eric41050808/6614225