Nearby Sharing Linux Implementation
This directory contains the Linux-specific implementation of Nearby Sharing and a sample application demonstrating its usage.
⚠️ Important Compatibility Notice
This is a simplified implementation for Linux-to-Linux transfers only.
- ✅ Works: Linux ↔ Linux device transfers
- ❌ Does NOT work: Linux ↔ Android/ChromeOS (authentication failure)
Reason: The full Nearby Sharing protocol requires certificate-based authentication, introduction frame exchange, and protocol frame handling which are not implemented in this simplified version.
For Android/ChromeOS compatibility, you need the full implementation in sharing/nearby_sharing_service_impl.{h,cc} which requires additional platform support. See ANDROID_COMPATIBILITY.md for details.
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)
NearbySharingApi
For external/Linux app consumers (for example Qt/CMake apps), use
nearby::sharing::linux::NearbySharingApi from:
sharing/linux/nearby_sharing_api.hlibnearby_sharing_api_shared.so
Install artifacts with:
./sharing/linux/install_nearby_sharing_service.sh
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
# Build the sample application
bazel build //sharing/linux:nearby_sharing_app
Running
# 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
- Start as Receiver: Advertise your device to receive files
- Start as Sender: Discover nearby devices to send files
- List Discovered Devices: View all devices found during scanning
- Send File: Transfer a file to a discovered device
- Send Text: Send text content to a discovered device
- Accept/Reject: Handle incoming transfer requests
- Cancel Transfer: Cancel an ongoing transfer
- Status Info: View Bluetooth and service status
Usage Examples
Example 1: Send a File
Device A (Sender):
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):
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
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
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
NearbySharingServiceLinux service("DeviceName");
The service initializes:
- Device Info: Gets OS device name and type
- Bluetooth Adapter: Checks BT availability
- Connections Core: Sets up the Nearby Connections layer
- Service Controller Router: Manages connection routing
Discovery Flow
- Register Send Surface (Foreground)
- Service starts scanning for nearby devices
- When device found: OnShareTargetDiscovered callback
- Advertisement is parsed to extract device info
- ShareTarget created with device details
- User can select target and initiate transfer
Advertising Flow
- Register Receive Surface (Foreground/Background)
- Service builds advertisement with device info
- Service starts advertising via Bluetooth/Wi-Fi
- When connection requested: OnTransferUpdate callback
- User can accept/reject the incoming transfer
Transfer Flow
Sending:
- SendAttachments() with target ID and attachments
- Service creates connection request
- Connection initiated → Status: kConnecting
- Connection accepted → Sends file/text payloads
- Payload transfer → Status: kInProgress
- Transfer complete → Status: kComplete
Receiving:
- Incoming connection → Status: kAwaitingLocalConfirmation
- Accept() called → Connection accepted
- Receive payloads → Status: kInProgress
- Payloads saved to local storage
- 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:
- Bluetooth LE: For discovery and initial connection
- Wi-Fi Direct: For high-speed file transfer
- Wi-Fi LAN: If devices on same network
Payload Types
- BYTES: For text content and metadata
- FILE: For file transfers
- STREAM: For real-time data
API Reference
Core Methods
RegisterSendSurface
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
void RegisterReceiveSurface(
TransferUpdateCallback* transfer_callback,
ReceiveSurfaceState state,
Advertisement::BlockedVendorId vendor_id,
std::function<void(StatusCodes)> status_codes_callback);
SendAttachments
void SendAttachments(
int64_t share_target_id,
std::unique_ptr<AttachmentContainer> attachment_container,
std::function<void(StatusCodes)> status_codes_callback);
Accept/Reject/Cancel
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:
- Add settings persistence (device name, visibility)
- Implement contact management
- Add certificate-based authentication
- Support visibility time limits
- Add Wi-Fi LAN connectivity detection
- Implement file path updates during transfer
- Add QR code generation for pairing
- Support for extended advertising
Troubleshooting
Bluetooth Issues
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.