Files
nearby_service/example_full/lib/domain/app_service.dart
T

387 lines
9.4 KiB
Dart

import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:nearby_service/nearby_service.dart';
import 'package:nearby_service_example_full/utils/files_saver.dart';
import 'app_state.dart';
class AppService extends ChangeNotifier {
late final _nearbyService = NearbyService.getInstance()
..communicationChannelState.addListener(notifyListeners);
AppState state = AppState.idle;
List<NearbyDevice>? peers;
NearbyDevice? connectedDevice;
NearbyDeviceInfo? currentDeviceInfo;
NearbyConnectionAndroidInfo? _connectionAndroidInfo;
String platformVersion = 'Unknown';
String platformModel = 'Unknown';
StreamSubscription? _peersSubscription;
StreamSubscription? _connectedDeviceSubscription;
StreamSubscription? _connectionInfoSubscription;
final filesLoadings = <String, int>{};
@override
void dispose() {
stopListeningAll();
super.dispose();
}
Future<void> getPlatformInfo() async {
platformVersion = await _nearbyService.getPlatformVersion() ?? 'Unknown';
platformModel = await _nearbyService.getPlatformModel() ?? 'Unknown';
notifyListeners();
}
Future<String> getSavedIOSDeviceName() async {
return (await _nearbyService.ios?.getSavedDeviceName()) ?? platformModel;
}
Future<void> initialize(String? iosDeviceName) async {
try {
await _nearbyService.initialize(
data: NearbyInitializeData(iosDeviceName: iosDeviceName),
);
updateState(
Platform.isAndroid ? AppState.permissions : AppState.selectClientType,
);
} catch (e) {
if (kDebugMode) {
print(e);
}
} finally {
notifyListeners();
}
}
Future<void> getCurrentDeviceInfo() async {
try {
currentDeviceInfo = await _nearbyService.getCurrentDeviceInfo();
} catch (e) {
if (kDebugMode) {
print(e);
}
}
}
Future<void> requestPermissions() async {
try {
final result = await _nearbyService.android?.requestPermissions();
if (result ?? false) {
updateState(AppState.checkServices);
}
} catch (e) {
if (kDebugMode) {
print(e);
}
}
}
Future<bool> checkWifiService() async {
final result = await _nearbyService.android?.checkWifiService();
if (result ?? false) {
updateState(AppState.readyToDiscover);
startListeningConnectionInfo();
return true;
}
return false;
}
Future<void> openServicesSettings() async {
await _nearbyService.openServicesSettings();
}
void setIsBrowser({required bool value}) {
_nearbyService.ios?.setIsBrowser(value: value);
updateState(AppState.readyToDiscover);
}
Future<void> discover() async {
try {
await getCurrentDeviceInfo();
final result = await _nearbyService.discover();
if (result) {
updateState(AppState.discoveringPeers);
}
} catch (e) {
if (kDebugMode) {
print(e);
}
}
}
Future<void> stopDiscovery() async {
try {
final result = await _nearbyService.stopDiscovery();
if (result) {
updateState(AppState.readyToDiscover);
}
} catch (e) {
if (kDebugMode) {
print(e);
}
}
}
Future<void> connect(NearbyDevice device) async {
try {
await _nearbyService.connect(device);
} catch (e) {
if (kDebugMode) {
print(e);
}
}
notifyListeners();
}
Future<void> disconnect([NearbyDevice? device]) async {
try {
await _nearbyService.disconnect(device);
} catch (e) {
if (kDebugMode) {
print(e);
}
} finally {
await stopListeningAll();
}
notifyListeners();
}
Future<void> stopListeningAll() async {
await endCommunicationChannel();
await stopListeningConnectedDevice();
await stopListeningPeers();
await stopListeningConnectionInfo();
await stopDiscovery();
}
void updateState(AppState state, {bool shouldNotify = true}) {
this.state = state;
if (shouldNotify) {
notifyListeners();
}
}
void _notify() => notifyListeners();
}
extension GettersExtension on AppService {
CommunicationChannelState get communicationChannelState {
return _nearbyService.communicationChannelState.value;
}
bool get isIOSBrowser {
return _nearbyService.ios?.isBrowser.value ?? false;
}
bool? get isAndroidGroupOwner {
return _connectionAndroidInfo?.isGroupOwner;
}
}
extension ConnectionInfoExtension on AppService {
void startListeningConnectionInfo() {
try {
_connectionInfoSubscription =
_nearbyService.android?.getConnectionInfoStream().listen(
(event) async {
_connectionAndroidInfo = event;
_notify();
},
);
} catch (e) {
if (kDebugMode) {
print(e);
}
}
_notify();
}
Future<void> stopListeningConnectionInfo() async {
await _connectionInfoSubscription?.cancel();
_connectionInfoSubscription = null;
}
}
extension PeersExtension on AppService {
Future<void> startListeningPeers() async {
try {
_peersSubscription = _nearbyService.getPeersStream().listen(
(event) {
peers = event;
_notify();
},
);
updateState(AppState.streamingPeers);
} catch (e) {
if (kDebugMode) {
print(e);
}
}
}
Future<void> stopListeningPeers() async {
await _peersSubscription?.cancel();
peers = null;
updateState(AppState.discoveringPeers);
}
}
extension ConnectedDeviceExtension on AppService {
Future<void> startListeningConnectedDevice(NearbyDevice device) async {
updateState(AppState.loadingConnection);
try {
_connectedDeviceSubscription =
_nearbyService.getConnectedDeviceStream(device).listen(
(event) async {
final wasConnected = connectedDevice?.status.isConnected ?? false;
final nowConnected = event?.status.isConnected ?? false;
if (wasConnected && !nowConnected) {
stopListeningAll();
return;
}
connectedDevice = event;
if (connectedDevice != null &&
state != AppState.connected &&
state != AppState.communicationChannelCreated) {
updateState(AppState.connected);
}
_notify();
},
);
} catch (e) {
updateState(AppState.streamingPeers, shouldNotify: false);
}
_notify();
}
Future<void> stopListeningConnectedDevice() async {
await _connectedDeviceSubscription?.cancel();
await _nearbyService.endCommunicationChannel();
_connectedDeviceSubscription = null;
connectedDevice = null;
_notify();
}
}
extension CommunicationChannelExtension on AppService {
Future<void> startCommunicationChannel({
ValueChanged<ReceivedNearbyMessage>? listener,
ValueChanged<ReceivedNearbyFilesPack>? onFilesSaved,
}) async {
final messagesListener = NearbyServiceMessagesListener(
onCreated: () {
updateState(AppState.communicationChannelCreated);
},
onData: (event) {
listener?.call(event);
},
onError: (e, [StackTrace? s]) {
stopListeningAll();
},
);
final filesListener = NearbyServiceFilesListener(
onData: (event) async {
final files = await FilesSaver.savePack(event);
onFilesSaved?.call(
ReceivedNearbyFilesPack(
id: event.id,
sender: event.sender,
files: files,
),
);
},
);
await _nearbyService.startCommunicationChannel(
NearbyCommunicationChannelData(
connectedDevice!.info.id,
messagesListener: messagesListener,
filesListener: filesListener,
),
);
}
Future<void> endCommunicationChannel() async {
try {
await _nearbyService.endCommunicationChannel();
} catch (e) {
if (kDebugMode) {
print(e);
}
}
_notify();
}
}
extension MessagingExtension on AppService {
void sendTextRequest(String message) {
if (connectedDevice == null) return;
_nearbyService.send(
OutgoingNearbyMessage(
content: NearbyMessageTextRequest.create(value: message),
receiver: connectedDevice!.info,
),
);
}
void sendFilesRequest(List<String> paths) {
if (connectedDevice == null) return;
_nearbyService.send(
OutgoingNearbyMessage(
content: NearbyMessageFilesRequest.create(
files: [
...paths.map((e) => NearbyFileInfo(path: e)),
],
),
receiver: connectedDevice!.info,
),
);
}
void sendTextResponse(String requestId) {
if (connectedDevice == null) return;
_nearbyService.send(
OutgoingNearbyMessage(
receiver: connectedDevice!.info,
content: NearbyMessageTextResponse(id: requestId),
),
);
}
void sendFilesResponse(
NearbyMessageFilesRequest request, {
required bool isAccepted,
}) {
if (connectedDevice == null) return;
_nearbyService.send(
OutgoingNearbyMessage(
receiver: connectedDevice!.info,
content: NearbyMessageFilesResponse(
id: request.id,
isAccepted: isAccepted,
),
),
);
if (isAccepted) {
setFilesLoading(request);
}
}
void setFilesLoading(NearbyMessageFilesRequest request) {
filesLoadings[request.id] = request.files.length;
_notify();
}
void endFilesLoading(ReceivedNearbyFilesPack pack) {
filesLoadings.remove(pack.id);
_notify();
}
}