Files
nearby/sharing/linux/README.md

349 lines
9.7 KiB
Markdown

# Nearby Sharing Linux Implementation
This directory contains the Linux-specific implementation of Nearby Sharing and a sample application demonstrating its usage.
## Overview
Nearby Sharing is a feature that allows users to share files, text, and other content between nearby devices using Bluetooth Low Energy (BLE) and Wi-Fi Direct. This implementation provides a simplified Linux interface built on top of the Nearby Connections API.
## Components
### NearbySharingServiceLinux
The main service class that provides nearby sharing functionality:
- **Discovery & Advertising**: Find nearby devices and advertise your device's availability
- **File Transfer**: Send and receive files
- **Text Transfer**: Send and receive text messages
- **Connection Management**: Handle connection lifecycle (accept, reject, cancel)
### Key Concepts
#### 1. Send Surface
Represents the sending side of a transfer:
- **Foreground**: Actively scans for nearby devices
- **Background**: Only listens for transfer updates without scanning
#### 2. Receive Surface
Represents the receiving side of a transfer:
- **Foreground**: Advertises to everyone, visible to all nearby devices
- **Background**: Advertises only to contacts (limited visibility)
#### 3. Callbacks
**TransferUpdateCallback**: Receives updates about ongoing transfers
- Status changes (connecting, in progress, complete, failed)
- Progress updates
- Transfer metadata (speed, bytes transferred, etc.)
**ShareTargetDiscoveredCallback**: Receives notifications about discovered devices
- Device discovered
- Device lost (out of range)
- Device updated
#### 4. Attachments
**FileAttachment**: Represents a file to be transferred
- Requires a file path
- Automatically determines MIME type and size
**TextAttachment**: Represents text content to be transferred
- Supports plain text, URLs, addresses, and phone numbers
- Includes optional title and MIME type
## Sample Application
The `nearby_sharing_app.cc` demonstrates how to use the service:
### Building
```bash
# Build the sample application
bazel build //sharing/linux:nearby_sharing_app
```
### Running
```bash
# Run with default device name
./bazel-bin/sharing/linux/nearby_sharing_app
# Run with custom device name
./bazel-bin/sharing/linux/nearby_sharing_app "MyCustomName"
```
### Features
1. **Start as Receiver**: Advertise your device to receive files
2. **Start as Sender**: Discover nearby devices to send files
3. **List Discovered Devices**: View all devices found during scanning
4. **Send File**: Transfer a file to a discovered device
5. **Send Text**: Send text content to a discovered device
6. **Accept/Reject**: Handle incoming transfer requests
7. **Cancel Transfer**: Cancel an ongoing transfer
8. **Status Info**: View Bluetooth and service status
## Usage Examples
### Example 1: Send a File
**Device A (Sender)**:
```cpp
NearbySharingApp app("Sender-Device");
// Start scanning for devices
app.StartAsSender();
// Wait for discovery...
std::this_thread::sleep_for(std::chrono::seconds(3));
// List discovered devices
app.ListDiscoveredDevices();
// Send file to target with ID 1
app.SendFile(1, "/path/to/file.txt");
```
**Device B (Receiver)**:
```cpp
NearbySharingApp app("Receiver-Device");
// Start advertising
app.StartAsReceiver();
// When connection is initiated (via callback), accept it
// This happens automatically when you see OnTransferUpdate with
// Status::kAwaitingLocalConfirmation
app.AcceptIncomingShare(target_id);
```
### Example 2: Send Text
```cpp
NearbySharingApp app("Text-Sender");
// Start as sender
app.StartAsSender();
// Wait for device discovery
std::this_thread::sleep_for(std::chrono::seconds(2));
// Send text to discovered device
app.SendText(1, "Hello from Nearby Sharing!");
```
### Example 3: Custom Callbacks
```cpp
class CustomTransferCallback : public TransferUpdateCallback {
public:
void OnTransferUpdate(const ShareTarget& share_target,
const AttachmentContainer& attachment_container,
const TransferMetadata& transfer_metadata) override {
switch (transfer_metadata.status()) {
case TransferMetadata::Status::kAwaitingLocalConfirmation:
// Auto-accept incoming transfers
service_->Accept(share_target.id, [](auto status) {
std::cout << "Auto-accepted" << std::endl;
});
break;
case TransferMetadata::Status::kComplete:
std::cout << "Transfer completed!" << std::endl;
// Handle completed files from attachment_container
break;
case TransferMetadata::Status::kFailed:
std::cout << "Transfer failed!" << std::endl;
break;
default:
break;
}
}
};
```
## Architecture
### Service Initialization
```cpp
NearbySharingServiceLinux service("DeviceName");
```
The service initializes:
1. **Device Info**: Gets OS device name and type
2. **Bluetooth Adapter**: Checks BT availability
3. **Connections Core**: Sets up the Nearby Connections layer
4. **Service Controller Router**: Manages connection routing
### Discovery Flow
1. **Register Send Surface** (Foreground)
2. Service starts **scanning** for nearby devices
3. When device found: **OnShareTargetDiscovered** callback
4. Advertisement is **parsed** to extract device info
5. **ShareTarget** created with device details
6. User can **select target** and initiate transfer
### Advertising Flow
1. **Register Receive Surface** (Foreground/Background)
2. Service **builds advertisement** with device info
3. Service starts **advertising** via Bluetooth/Wi-Fi
4. When connection requested: **OnTransferUpdate** callback
5. User can **accept/reject** the incoming transfer
### Transfer Flow
#### Sending:
1. **SendAttachments()** with target ID and attachments
2. Service creates **connection request**
3. **Connection initiated** → Status: kConnecting
4. Connection **accepted** → Sends file/text payloads
5. **Payload transfer** → Status: kInProgress
6. **Transfer complete** → Status: kComplete
#### Receiving:
1. **Incoming connection** → Status: kAwaitingLocalConfirmation
2. **Accept()** called → Connection accepted
3. **Receive payloads** → Status: kInProgress
4. **Payloads saved** to local storage
5. **Transfer complete** → Status: kComplete
## Implementation Details
### Advertisement Format
The service uses a custom advertisement format:
- **Header byte**: Version, visibility, device type
- **Salt**: 2 random bytes
- **Metadata key**: 14 bytes (for encryption)
- **TLV fields**: Vendor ID, QR code, etc.
- **Device name** (optional): UTF-8 device name
### Connection Strategy
Uses `P2P_POINT_TO_POINT` strategy:
- Direct peer-to-peer connections
- Supports Bluetooth and Wi-Fi Direct
- Automatic medium selection based on availability
### Medium Selection
The service attempts to use available media:
1. **Bluetooth LE**: For discovery and initial connection
2. **Wi-Fi Direct**: For high-speed file transfer
3. **Wi-Fi LAN**: If devices on same network
### Payload Types
1. **BYTES**: For text content and metadata
2. **FILE**: For file transfers
3. **STREAM**: For real-time data
## API Reference
### Core Methods
#### RegisterSendSurface
```cpp
void RegisterSendSurface(
TransferUpdateCallback* transfer_callback,
ShareTargetDiscoveredCallback* discovery_callback,
SendSurfaceState state,
Advertisement::BlockedVendorId blocked_vendor_id,
bool disable_wifi_hotspot,
std::function<void(StatusCodes)> status_codes_callback);
```
#### RegisterReceiveSurface
```cpp
void RegisterReceiveSurface(
TransferUpdateCallback* transfer_callback,
ReceiveSurfaceState state,
Advertisement::BlockedVendorId vendor_id,
std::function<void(StatusCodes)> status_codes_callback);
```
#### SendAttachments
```cpp
void SendAttachments(
int64_t share_target_id,
std::unique_ptr<AttachmentContainer> attachment_container,
std::function<void(StatusCodes)> status_codes_callback);
```
#### Accept/Reject/Cancel
```cpp
void Accept(int64_t share_target_id,
std::function<void(StatusCodes)> status_codes_callback);
void Reject(int64_t share_target_id,
std::function<void(StatusCodes)> status_codes_callback);
void Cancel(int64_t share_target_id,
std::function<void(StatusCodes)> status_codes_callback);
```
### Status Codes
- **kOk**: Operation successful
- **kError**: General error
- **kOutOfOrderApiCall**: API called in wrong order
- **kTransferAlreadyInProgress**: Transfer already active
- **kNoAvailableConnectionMedium**: No BT/Wi-Fi available
- **kInvalidArgument**: Invalid parameter provided
## Limitations
Current implementation limitations:
- No settings persistence
- No contact management
- No certificate management
- No account integration
- Limited visibility control
- No Wi-Fi LAN detection
- No extended advertising support
## Future Enhancements
Potential improvements:
1. Add settings persistence (device name, visibility)
2. Implement contact management
3. Add certificate-based authentication
4. Support visibility time limits
5. Add Wi-Fi LAN connectivity detection
6. Implement file path updates during transfer
7. Add QR code generation for pairing
8. Support for extended advertising
## Troubleshooting
### Bluetooth Issues
```cpp
if (!service.IsBluetoothPresent()) {
std::cout << "Bluetooth adapter not found" << std::endl;
}
if (!service.IsBluetoothPowered()) {
std::cout << "Bluetooth is disabled" << std::endl;
}
```
### Discovery Not Working
- Ensure Bluetooth is enabled
- Check that sender is in foreground mode
- Verify receiver is advertising
- Check for Bluetooth permissions
### Transfer Failures
- Verify file paths are accessible
- Check available disk space
- Ensure stable Bluetooth connection
- Monitor transfer callbacks for errors
## License
Copyright 2025 Google LLC. Licensed under Apache 2.0.