简介了Android Bluetooth蓝牙设备之间的连接建立,和Java网络编程的socket套接字连接建立一样,Android不同的Bluetooth蓝牙设备间的socket连接建立后,就可以进行数据传输了。

Android Bluetooth蓝牙的socket编程模型和Java网络编程模型类似,数据传输模型也是基于流的模型。在Java网络编程中,从一个socket套接字获得输入(InputStream)、输出流(OutputStream),进而进行服务器端和客户端的点到点的数据传输(读和写)。而Android Bluetooth蓝牙数据传输基本可以认为就是仿照Java的流模型。
附录文章3完成了两个不同蓝牙设备的socket套接字的连接,本文在附录文章3的基础上更进一步,从已经建立socket套接字的基础上获取输入输出流,从而完成一个简单的数据传输,实现一个简单的功能:Android Bluetooth蓝牙设备服务端等待客户连接请求,当外部的一个Android Bluetooth蓝牙设备传入一个连接请求并与服务器端建立连接后,服务器端就发给客户端一个简单的字符串数据比如经典的hello,world!
为了完成上述简单的字符串传输,其实就是在附录文章3的基础上、从已有的socket像Java网络编程中的socket一样获取InputStream进行数据的读、获取OutputStream进行数据的写。
还是先简单描述一下编程模型的逻辑思路划分:
(A)还是在一个蓝牙设备上部署服务器端代码,然后在一个while循环里面等待客户端连接请求。当有客户端请求进来并且建立socket连接后,服务器端就从这个socket获取OutputStream,至此,问题就简化成一般的Java流的写,然后在这个OutputStream写入hello,world!即可。
(B)在另外一个蓝牙设备上部署客户端代码。客户端代码扫描获得服务器端Android Bluetooth设备后,就发起对服务器端蓝牙设备的连接(这部分过程在我写的附录文章1中已有简介)。获得服务器端蓝牙设备后,就像我写的附录文章3那样,和服务器端建立socket连接,然后从这个socket获得InputStream,到这个阶段,问题就简化成一般的Java流的读,从这个InputStream把hello,world!读出来即可。

上述功能过程的完整代码(Android Bluetooth蓝牙服务器端):

package zhangphil.bluetooth; 
 
import java.io.OutputStream; 
import java.util.UUID; 
 
import android.app.ListActivity; 
import android.bluetooth.BluetoothAdapter; 
import android.bluetooth.BluetoothDevice; 
import android.bluetooth.BluetoothServerSocket; 
import android.bluetooth.BluetoothSocket; 
import android.os.Bundle; 
import android.util.Log; 
 
public class MainActivity extends ListActivity { 
 
	private BluetoothAdapter mBluetoothAdapter; 
 
	private final String tag = "zhangphil"; 
	private final String MY_UUID = "00001101-0000-1000-8000-00805F9B34FB"; 
 
	private class ServerThread extends Thread { 
 
		private BluetoothServerSocket serverSocket; 
 
		@Override 
		public void run() { 
 
			try { 
				serverSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(tag, UUID.fromString(MY_UUID)); 
			} catch (Exception e) { 
				e.printStackTrace(); 
			} 
 
			Log.d(tag, "等待客户连接..."); 
			while (true) { 
				try { 
					BluetoothSocket socket = serverSocket.accept(); 
 
					BluetoothDevice device = socket.getRemoteDevice(); 
					Log.d(tag, "接受客户连接 , 远端设备名字:" + device.getName() + " , 远端设备地址:" + device.getAddress()); 
 
					if (socket.isConnected()) { 
						Log.d(tag, "已建立与客户连接."); 
 
						// 写数据 
						sendDataToClient(socket); 
					} 
 
				} catch (Exception e) { 
					e.printStackTrace(); 
				} 
			} 
		} 
 
		// 蓝牙服务端发送简单的一个字符串:hello,world!给连接的客户 
		private void sendDataToClient(BluetoothSocket socket) { 
			String s = "hello,world ! by zhangphil"; 
			byte[] buffer = s.getBytes(); 
 
			try { 
				OutputStream os = socket.getOutputStream(); 
 
				os.write(buffer); 
				os.flush(); 
 
				// os.close(); 
				// socket.close(); 
 
				Log.d(tag, "服务器端数据发送完毕!"); 
			} catch (Exception e) { 
				e.printStackTrace(); 
			} 
		} 
	} 
 
	@Override 
	protected void onCreate(Bundle savedInstanceState) { 
		super.onCreate(savedInstanceState); 
 
		mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
		if (mBluetoothAdapter != null) 
			new Thread(new ServerThread()).start(); 
	} 
}

相应的,完整的Android Bluetooth蓝牙客户端代码:

package zhangphil.client; 
 
import java.io.InputStream; 
import java.util.UUID; 
 
import android.app.Activity; 
import android.bluetooth.BluetoothAdapter; 
import android.bluetooth.BluetoothDevice; 
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.util.Log; 
 
public class MainActivity extends Activity { 
 
	private BluetoothAdapter mBluetoothAdapter; 
 
	private final String tag = "zhangphil"; 
	private final String MY_UUID = "00001101-0000-1000-8000-00805F9B34FB"; 
 
	// 广播接收发现蓝牙设备 
	private 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); 
 
				String name = device.getName(); 
				if (name != null) 
					Log.d(tag, "发现设备:" + name); 
 
				if (name != null && name.equals("zhangphil_pad")) { 
					Log.d(tag, "发现目标设备,开始线程连接!"); 
 
					// 蓝牙搜索是非常消耗系统资源开销的过程,一旦发现了目标感兴趣的设备,可以考虑关闭扫描。 
					mBluetoothAdapter.cancelDiscovery(); 
 
					new Thread(new ClientThread(device)).start(); 
				} 
			} 
		} 
	}; 
 
	private class ClientThread extends Thread { 
 
		private BluetoothDevice device; 
 
		public ClientThread(BluetoothDevice device) { 
			this.device = device; 
		} 
 
		@Override 
		public void run() { 
 
			BluetoothSocket socket = null; 
 
			try { 
				socket = device.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID)); 
 
				Log.d(tag, "连接服务端..."); 
				socket.connect(); 
				Log.d(tag, "连接建立."); 
 
				// 读数据 
				readDataFromServer(socket); 
			} catch (Exception e) { 
				e.printStackTrace(); 
			} 
		} 
 
		private void readDataFromServer(BluetoothSocket socket) { 
			byte[] buffer = new byte[64]; 
			try { 
				InputStream is = socket.getInputStream(); 
 
				int cnt = is.read(buffer); 
				is.close(); 
 
				String s = new String(buffer, 0, cnt); 
				Log.d(tag, "收到服务端发来数据:" + s); 
			} catch (Exception e) { 
				e.printStackTrace(); 
			} 
		} 
	} 
 
	@Override 
	protected void onCreate(Bundle savedInstanceState) { 
		super.onCreate(savedInstanceState); 
 
		mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
 
		// 注册广播接收器。接收蓝牙发现讯息 
		IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); 
		registerReceiver(mReceiver, filter); 
 
		if (mBluetoothAdapter.startDiscovery()) { 
			Log.d(tag, "启动蓝牙扫描设备..."); 
		} 
	} 
 
	@Override 
	protected void onDestroy() { 
		super.onDestroy(); 
		unregisterReceiver(mReceiver); 
	} 
}

注意在连接阶段设备名的区分设置,我写的这个例子,在蓝牙互相并连接阶段,是根据蓝牙设备的名字进行过滤和配对的。在我写的这个例子中,服务端的Android Bluetooth蓝牙设备名字设置成:zhangphil_pad。服务器端代码和客户端代码分别部署在不同的Android Bluetooth蓝牙设备终端。


发布评论

分享到:

IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

Android桌面小部件AppWidget(1)详解
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。