我已经尝试过RFCOMM API将图像(jpeg(从UWP(在Windows平板电脑上(发送到其他移动设备(任何移动Android/Windows(。
在我的应用程序中,套接字创建是成功的,写入套接字输出流给出了文件大小的值作为返回值(认为这也是成功(。
但是在接收器端,它不显示任何接受/接收,并且看不到该设备中的文件。
我还在应用清单中添加了功能。
<DeviceCapability Name="bluetooth.rfcomm">
<Device Id="any">
<Function Type="serviceId:00001101-0000-1000-8000-00805F9B34FB" />
</Device>
</DeviceCapability>
C# 代码:
async void Initialize()
{
var services = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(
RfcommDeviceService.GetDeviceSelector(
RfcommServiceId.ObexObjectPush));
if (services.Count > 0)
{
var service = await RfcommDeviceService.FromIdAsync(services[0].Id);
if (SupportsProtection(service))
{
_service = service;
Windows.Devices.Enumeration.DeviceAccessStatus accessStatus = await _service.Device.RequestAccessAsync();
if (accessStatus.Equals(Windows.Devices.Enumeration.DeviceAccessStatus.DeniedByUser))
{
await dialog.ShowAsync();
return;
}
dialog = new MessageDialog(_service.Device.Name);
await dialog.ShowAsync();
_socket = new StreamSocket();
await _socket.ConnectAsync(_service.ConnectionHostName, _service.ConnectionServiceName, SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication);
var picker = new FileOpenPicker();
picker.ViewMode = PickerViewMode.Thumbnail;
picker.SuggestedStartLocation =
PickerLocationId.PicturesLibrary;
picker.FileTypeFilter.Add(".jpeg");
picker.FileTypeFilter.Add(".jpg");
picker.FileTypeFilter.Add(".png");
var file = await picker.PickSingleFileAsync();
if (file != null)
{
var stream = await file.OpenStreamForReadAsync();
byte[] bytes = new byte[(int)stream.Length];
stream.Read(bytes, 0, (int)stream.Length);
IBuffer buffer = bytes.AsBuffer();
uint test = await _socket.OutputStream.WriteAsync(buffer);
await _socket.OutputStream.FlushAsync();
_socket.Dispose();
dialog = new MessageDialog("Result :" + test.ToString());
await dialog.ShowAsync();
}
}
}
}
由于我没有看到您的接收器端的代码,因此很难说为什么您无法接收图像文件。要发送和接收图像,您可以参考蓝牙射频通信。本文档包含有关如何使用蓝牙射频通信发送或接收文件的示例代码。虽然示例代码中有一些小错误,但我们可以轻松修复它们。下面是使用示例代码的简单示例,并演示了如何发送和接收图像文件。
将图像文件作为客户端发送
private RfcommDeviceService _service;
private StreamSocket _socket;
private async void Initialize()
{
// Enumerate devices with the object push service
var services =
await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(
RfcommDeviceService.GetDeviceSelector(
RfcommServiceId.ObexObjectPush));
if (services.Count > 0)
{
// Initialize the target Bluetooth BR device
var service = await RfcommDeviceService.FromIdAsync(services[0].Id);
// Check that the service meets this App's minimum requirement
if (SupportsProtection(service) && await IsCompatibleVersion(service))
{
_service = service;
// Create a socket and connect to the target
_socket = new StreamSocket();
await _socket.ConnectAsync(
_service.ConnectionHostName,
_service.ConnectionServiceName,
SocketProtectionLevel
.BluetoothEncryptionAllowNullAuthentication);
// The socket is connected. At this point the App can wait for
// the user to take some action, e.g. click a button to send a
// file to the device, which could invoke the Picker and then
// send the picked file. The transfer itself would use the
// Sockets API and not the Rfcomm API, and so is omitted here for
// brevity.
}
}
}
// This App requires a connection that is encrypted but does not care about
// whether its authenticated.
private bool SupportsProtection(RfcommDeviceService service)
{
switch (service.ProtectionLevel)
{
case SocketProtectionLevel.PlainSocket:
if ((service.MaxProtectionLevel == SocketProtectionLevel
.BluetoothEncryptionWithAuthentication)
|| (service.MaxProtectionLevel == SocketProtectionLevel
.BluetoothEncryptionAllowNullAuthentication))
{
// The connection can be upgraded when opening the socket so the
// App may offer UI here to notify the user that Windows may
// prompt for a PIN exchange.
return true;
}
else
{
// The connection cannot be upgraded so an App may offer UI here
// to explain why a connection won't be made.
return false;
}
case SocketProtectionLevel.BluetoothEncryptionWithAuthentication:
return true;
case SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication:
return true;
}
return false;
}
// This App relies on CRC32 checking available in version 2.0 of the service.
private const uint SERVICE_VERSION_ATTRIBUTE_ID = 0x0300;
private const byte SERVICE_VERSION_ATTRIBUTE_TYPE = 0x0A; // UINT32
private const uint MINIMUM_SERVICE_VERSION = 200;
private async System.Threading.Tasks.Task<bool> IsCompatibleVersion(RfcommDeviceService service)
{
var attributes = await service.GetSdpRawAttributesAsync(Windows.Devices.Bluetooth.BluetoothCacheMode.Uncached);
var attribute = attributes[SERVICE_VERSION_ATTRIBUTE_ID];
var reader = DataReader.FromBuffer(attribute);
// The first byte contains the attribute' s type
byte attributeType = reader.ReadByte();
if (attributeType == SERVICE_VERSION_ATTRIBUTE_TYPE)
{
// The remainder is the data
uint version = reader.ReadUInt32();
return version >= MINIMUM_SERVICE_VERSION;
}
return false;
}
// Click a button to send a image file to the device
private async void Button_Click(object sender, RoutedEventArgs e)
{
var picker = new FileOpenPicker();
picker.ViewMode = PickerViewMode.Thumbnail;
picker.SuggestedStartLocation =
PickerLocationId.PicturesLibrary;
picker.FileTypeFilter.Add(".jpeg");
picker.FileTypeFilter.Add(".jpg");
picker.FileTypeFilter.Add(".png");
var file = await picker.PickSingleFileAsync();
if (file != null)
{
DataWriter writer = null;
try
{
writer = new DataWriter(_socket.OutputStream);
writer.WriteUInt32((uint)file.Name.Length);
writer.WriteString(file.Name);
var buffer = await FileIO.ReadBufferAsync(file);
writer.WriteUInt32(buffer.Length);
writer.WriteBuffer(buffer);
await writer.StoreAsync();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
writer.DetachStream();
writer.Dispose();
}
}
将图像文件作为服务器接收
private StreamSocket _socket;
private RfcommServiceProvider _provider;
private async void Initialize()
{
// Initialize the provider for the hosted RFCOMM service
_provider = await RfcommServiceProvider.CreateAsync(RfcommServiceId.ObexObjectPush);
// Create a listener for this service and start listening
StreamSocketListener listener = new StreamSocketListener();
listener.ConnectionReceived += OnConnectionReceivedAsync;
await listener.BindServiceNameAsync(
_provider.ServiceId.AsString(),
SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication);
// Set the SDP attributes and start advertising
InitializeServiceSdpAttributes(_provider);
_provider.StartAdvertising(listener);
}
private const uint SERVICE_VERSION_ATTRIBUTE_ID = 0x0300;
private const byte SERVICE_VERSION_ATTRIBUTE_TYPE = 0x0A; // UINT32
private const uint SERVICE_VERSION = 200;
private void InitializeServiceSdpAttributes(RfcommServiceProvider provider)
{
var writer = new Windows.Storage.Streams.DataWriter();
// First write the attribute type
writer.WriteByte(SERVICE_VERSION_ATTRIBUTE_TYPE);
// Then write the data
writer.WriteUInt32(SERVICE_VERSION);
var data = writer.DetachBuffer();
provider.SdpRawAttributes.Add(SERVICE_VERSION_ATTRIBUTE_ID, data);
}
private async void OnConnectionReceivedAsync(
StreamSocketListener listener,
StreamSocketListenerConnectionReceivedEventArgs args)
{
// Stop advertising/listening so that we're only serving one client
_provider.StopAdvertising();
listener.Dispose();
_socket = args.Socket;
// The client socket is connected. At this point the App can wait for
// the user to take some action, e.g. click a button to receive a file
// from the device, which could invoke the Picker and then save the
// received file to the picked location. The transfer itself would use
// the Sockets API and not the Rfcomm API, and so is omitted here for
// brevity.
var reader = new DataReader(_socket.InputStream);
bool remoteDisconnection = false;
// Infinite read buffer loop
while (true)
{
try
{
// Based on the protocol we've defined, the first uint is the size of the file name
uint readLength = await reader.LoadAsync(sizeof(uint));
// Check if the size of the data is expected (otherwise the remote has already terminated the connection)
if (readLength < sizeof(uint))
{
remoteDisconnection = true;
break;
}
var nameLength = reader.ReadUInt32();
readLength = await reader.LoadAsync(nameLength);
// Check if the size of the data is expected (otherwise the remote has already terminated the connection)
if (readLength < nameLength)
{
remoteDisconnection = true;
break;
}
var fileName = reader.ReadString(nameLength);
// The second uint is the size of the file
readLength = await reader.LoadAsync(sizeof(uint));
// Check if the size of the data is expected (otherwise the remote has already terminated the connection)
if (readLength < sizeof(uint))
{
remoteDisconnection = true;
break;
}
var fileLength = reader.ReadUInt32();
readLength = await reader.LoadAsync(fileLength);
// Check if the size of the data is expected (otherwise the remote has already terminated the connection)
if (readLength < fileLength)
{
remoteDisconnection = true;
break;
}
var buffer = reader.ReadBuffer(fileLength);
// Save the received image file to local folder
var file = await ApplicationData.Current.LocalFolder.CreateFileAsync(fileName, CreationCollisionOption.GenerateUniqueName);
await FileIO.WriteBufferAsync(file, buffer);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
break;
}
}
reader.DetachStream();
reader.Dispose();
if (remoteDisconnection)
{
_socket.Dispose();
}
}
请注意,上面的示例仅用于演示,它可能具有未处理的异常。有关更多信息,请参阅蓝牙射频通信聊天示例。