diff --git a/CHANGELOG.md b/CHANGELOG.md index fd76382..b81de3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.0.7 + +- Log all errors on the Android platform +- Add mapping for native Android exceptions in methods: discover(), stopDiscovery(), connect(), disconnect() +- Fix getPeers() method: correct decoding from JSON +- Update example: show empty peers state +- Update example_full: show variant of checking running jobs + ## 0.0.6 - Update README: add a Feedback form diff --git a/README.md b/README.md index f47f66f..f2eede0 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,11 @@ Nearby Service Flutter Plugin is used to create connections in a P2P network. The plugin supports sending text messages and files. With it, you can easily create any kind of information sharing application **without Internet connection**. -Your feedback and suggestions would be greatly appreciated! [You can leave your opinion here](https://forms.gle/FbAtW2dG5RYCxb1DA) +The package does not support communication between Android and IOS devices, the connection is available for +**Android-Android** and **IOS-IOS** relations. + +Your feedback and suggestions would be greatly +appreciated! [You can leave your opinion here](https://forms.gle/FbAtW2dG5RYCxb1DA) ## Table of Contents @@ -26,6 +30,7 @@ Your feedback and suggestions would be greatly appreciated! [You can leave your - [Data sharing](#data-sharing) - [Text messages](#text-messages) - [Resource messages](#resource-messages) +- [Exceptions](#exceptions) - [Additional options](#additional-options) - [Demo](#demo) ## About @@ -446,6 +451,32 @@ final filesListener = NearbyServiceFilesListener( ); ``` +## Exceptions + +**NearbyService** includes custom errors that you can catch in your implementation. + +**Common exceptions [See here](https://github.com/ksenia312/nearby_service/blob/main/lib/src/utils/exception.dart):** + +- `NearbyServiceUnsupportedPlatformException`: Usage of the plugin on an unsupported platform +- `NearbyServiceUnsupportedDecodingException`: Error decoding messages from native platform to Dart (open an issue if + this happens) +- `NearbyServiceInvalidMessageException`: An attempt to send an invalid message on the sender's side. Add content + validation to your messages + +**Exceptions that can be caught from the `discover()`, `stopDiscovery()`, `connect()`, and `disconnect()` methods for +the Android platform +[See here](https://github.com/ksenia312/nearby_service/blob/main/lib/src/platforms/android/utils/exception.dart):** + +- `NearbyServiceBusyException`: The Wi-Fi P2P framework is currently busy. Usually this means that you have sent a + request to some device and now one of the peers is **CONNECTING** +- `NearbyServiceP2PPUnsupportedException`: Wi-Fi P2P is not supported on this device +- `NearbyServiceNoServiceRequestsException`: No service discovery requests have been made. Ensure that you have + initiated a service discovery request before attempting to connect +- `NearbyServiceGenericErrorException`: A generic error occurred. This could be due to various reasons such as hardware + issues, Wi-Fi being turned off, or temporary issues with the Wi-Fi P2P framework +- `NearbyServiceUnknownException`: An unknown error occurred. Please check the device's Wi-Fi P2P settings and ensure + the device supports Wi-Fi P2P + ## Additional options - Each `NearbyDevice` contains `NearbyDeviceInfo` that presents different meanings depending on the platform. For diff --git a/android/src/main/kotlin/com/xenikii/nearby_service/Logger.kt b/android/src/main/kotlin/com/xenikii/nearby_service/Logger.kt index d775b1d..d5be33a 100644 --- a/android/src/main/kotlin/com/xenikii/nearby_service/Logger.kt +++ b/android/src/main/kotlin/com/xenikii/nearby_service/Logger.kt @@ -19,19 +19,19 @@ class Logger { var level = LogLevel.DEBUG fun d(message: String) { if (level.value <= LogLevel.DEBUG.value) { - Log.d(TAG, message) + Log.d(TAG, "\u001B[37m$message\u001B[0m") } } fun i(message: String) { if (level.value <= LogLevel.INFO.value) { - Log.i(TAG, message) + Log.i(TAG, "\u001B[32m$message\u001B[0m") } } fun e(message: String) { if (level.value <= LogLevel.ERROR.value) { - Log.e(TAG, message) + Log.e(TAG, "\u001B[31m$message\u001B[0m") } } } diff --git a/android/src/main/kotlin/com/xenikii/nearby_service/NearbyServiceBroadcastReceiver.kt b/android/src/main/kotlin/com/xenikii/nearby_service/NearbyServiceBroadcastReceiver.kt index 1542b4a..30246d2 100644 --- a/android/src/main/kotlin/com/xenikii/nearby_service/NearbyServiceBroadcastReceiver.kt +++ b/android/src/main/kotlin/com/xenikii/nearby_service/NearbyServiceBroadcastReceiver.kt @@ -51,6 +51,11 @@ class NearbyServiceBroadcastReceiver( } } + fun init() { + writeDevices() + writeConnectionInfo() + } + private fun logState(intent: Intent) { when (intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1)) { WifiP2pManager.WIFI_P2P_STATE_ENABLED -> { diff --git a/android/src/main/kotlin/com/xenikii/nearby_service/NearbyServiceManager.kt b/android/src/main/kotlin/com/xenikii/nearby_service/NearbyServiceManager.kt index 7c6a185..493107f 100644 --- a/android/src/main/kotlin/com/xenikii/nearby_service/NearbyServiceManager.kt +++ b/android/src/main/kotlin/com/xenikii/nearby_service/NearbyServiceManager.kt @@ -121,7 +121,11 @@ class NearbyServiceManager(private var context: Context) { fun discover(result: Result) { try { wifiManager.discoverPeers( - wifiChannel, getActionListener(result) + wifiChannel, getActionListener( + result, + "Discovery has started successfully!", + "Discovery starting failed" + ) ) } catch (e: SecurityException) { if (!permissionsHandler.checkPermissions()) { @@ -136,7 +140,11 @@ class NearbyServiceManager(private var context: Context) { */ fun stopDiscovery(result: Result) { wifiManager.stopPeerDiscovery( - wifiChannel, getActionListener(result) + wifiChannel, getActionListener( + result, + "Discovery has successfully stopped", + "Discovery stopping failed" + ) ) } @@ -167,7 +175,7 @@ class NearbyServiceManager(private var context: Context) { } val actionListener = getActionListener( result, - "Connected to device $deviceAddress", + "Connection request sent to device $deviceAddress", "Connecting to device $deviceAddress failed" ) config.deviceAddress = deviceAddress @@ -216,12 +224,17 @@ class NearbyServiceManager(private var context: Context) { permissionsHandler, ) context.registerReceiver(receiver, intentFilter) + try { + receiver.init() + } catch (error: Throwable) { + Logger.e("Failed to write initial info, error=${error.message}") + } } private fun getActionListener( result: Result?, successMessage: String? = null, - errorMessage: String? = null, + errorMessage: String ): WifiP2pManager.ActionListener { return object : WifiP2pManager.ActionListener { override fun onSuccess() { @@ -232,10 +245,22 @@ class NearbyServiceManager(private var context: Context) { } override fun onFailure(reasonCode: Int) { - if (errorMessage != null) { - Logger.e("ERROR: $errorMessage Reason code: $reasonCode") + val reason = when (reasonCode) { + WifiP2pManager.P2P_UNSUPPORTED -> "Wi-Fi P2P is not supported on this device. Please ensure your device supports Wi-Fi P2P." + WifiP2pManager.ERROR -> "A generic error occurred. This could be due to various reasons such as hardware issues, Wi-Fi being turned off, or temporary issues with the Wi-Fi P2P framework." + WifiP2pManager.BUSY -> "The Wi-Fi P2P framework is currently busy. Please wait for the current operation to complete before initiating another. Usually this means that you have sent a request to some device and now one of the peers is CONNECTING." + WifiP2pManager.NO_SERVICE_REQUESTS -> "No service discovery requests have been made. Ensure that you have initiated a service discovery request before attempting to connect." + else -> "An unknown error occurred. Please check the device's Wi-Fi P2P settings and ensure the device supports Wi-Fi P2P." } - result?.success(false) + val stringifyReasonCode = when (reasonCode) { + WifiP2pManager.P2P_UNSUPPORTED -> "P2P_UNSUPPORTED" + WifiP2pManager.ERROR -> "ERROR" + WifiP2pManager.BUSY -> "BUSY" + WifiP2pManager.NO_SERVICE_REQUESTS -> "NO_SERVICE_REQUESTS" + else -> "UNKNOWN" + } + Logger.e("$errorMessage, Reason code: $reasonCode, Reason: $reason") + result?.success(stringifyReasonCode) } } } diff --git a/example/lib/main.dart b/example/lib/main.dart index e4846d1..2a38916 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -112,6 +112,7 @@ class _AppBodyState extends State { children: [ if (Platform.isIOS) Text('You are ${_isIosBrowser ? 'Browser' : 'Advertiser'}'), + if (_peers.isEmpty) const Text('Searching for peers...'), ..._peers.map( (e) => PeerWidget( device: e, diff --git a/example_full/lib/domain/app_service.dart b/example_full/lib/domain/app_service.dart index c55a4e9..e098e46 100644 --- a/example_full/lib/domain/app_service.dart +++ b/example_full/lib/domain/app_service.dart @@ -50,10 +50,8 @@ class AppService extends ChangeNotifier { updateState( Platform.isAndroid ? AppState.permissions : AppState.selectClientType, ); - } catch (e) { - if (kDebugMode) { - print(e); - } + } catch (e, s) { + _log(e, s); } finally { notifyListeners(); } @@ -62,10 +60,8 @@ class AppService extends ChangeNotifier { Future getCurrentDeviceInfo() async { try { currentDeviceInfo = await _nearbyService.getCurrentDeviceInfo(); - } catch (e) { - if (kDebugMode) { - print(e); - } + } catch (e, s) { + _log(e, s); } } @@ -75,10 +71,8 @@ class AppService extends ChangeNotifier { if (result ?? false) { updateState(AppState.checkServices); } - } catch (e) { - if (kDebugMode) { - print(e); - } + } catch (e, s) { + _log(e, s); } } @@ -101,17 +95,41 @@ class AppService extends ChangeNotifier { updateState(AppState.readyToDiscover); } + Future hasRunningJobs() async { + try { + final result = await _nearbyService.getPeers(); + // if one of devices is connecting, service is busy (android only) + if (result.any( + (element) => element.status == NearbyDeviceStatus.connecting, + )) { + if (kDebugMode) { + print('Service has already running jobs'); + } + return true; + } + return false; + } catch (e, s) { + _log(e, s); + return false; + } + } + Future discover() async { try { await getCurrentDeviceInfo(); - final result = await _nearbyService.discover(); - if (result) { + final hasRunning = await hasRunningJobs(); + if (hasRunning) { updateState(AppState.discoveringPeers); + } else { + final result = await _nearbyService.discover(); + if (result) { + updateState(AppState.discoveringPeers); + } } - } catch (e) { - if (kDebugMode) { - print(e); - } + } on NearbyServiceBusyException catch (_) { + _logBusyException(); + } catch (e, s) { + _log(e, s); } } @@ -121,20 +139,20 @@ class AppService extends ChangeNotifier { if (result) { updateState(AppState.readyToDiscover); } - } catch (e) { - if (kDebugMode) { - print(e); - } + } on NearbyServiceBusyException catch (_) { + _logBusyException(); + } catch (e, s) { + _log(e, s); } } Future connect(NearbyDevice device) async { try { await _nearbyService.connect(device); - } catch (e) { - if (kDebugMode) { - print(e); - } + } on NearbyServiceBusyException catch (_) { + _logBusyException(); + } catch (e, s) { + _log(e, s); } notifyListeners(); } @@ -142,10 +160,10 @@ class AppService extends ChangeNotifier { Future disconnect([NearbyDevice? device]) async { try { await _nearbyService.disconnect(device); - } catch (e) { - if (kDebugMode) { - print(e); - } + } on NearbyServiceBusyException catch (_) { + _logBusyException(); + } catch (e, s) { + _log(e, s); } finally { await stopListeningAll(); } @@ -194,10 +212,8 @@ extension ConnectionInfoExtension on AppService { _notify(); }, ); - } catch (e) { - if (kDebugMode) { - print(e); - } + } catch (e, s) { + _log(e, s); } _notify(); } @@ -218,10 +234,8 @@ extension PeersExtension on AppService { }, ); updateState(AppState.streamingPeers); - } catch (e) { - if (kDebugMode) { - print(e); - } + } catch (e, s) { + _log(e, s); } } @@ -310,10 +324,8 @@ extension CommunicationChannelExtension on AppService { Future endCommunicationChannel() async { try { await _nearbyService.endCommunicationChannel(); - } catch (e) { - if (kDebugMode) { - print(e); - } + } catch (e, s) { + _log(e, s); } _notify(); } @@ -384,3 +396,19 @@ extension MessagingExtension on AppService { _notify(); } } + +extension LoggingExtension on AppService { + void _log(e, StackTrace s) { + if (kDebugMode) { + print('$e, \nStacktrace: $s'); + } + } + + void _logBusyException() { + if (kDebugMode) { + print( + 'Nearby service is busy, wait a little and retry (You can implement retry in your code)', + ); + } + } +} diff --git a/lib/nearby_service.dart b/lib/nearby_service.dart index 009cbdd..27577c8 100644 --- a/lib/nearby_service.dart +++ b/lib/nearby_service.dart @@ -168,6 +168,13 @@ abstract class NearbyService { /// Note that the [NearbyIOSService] implementation starts **browsing** or /// **advertising** depending on the [NearbyIOSService.isBrowser]. /// + /// On Android can throw mapped from native platform exceptions: + /// 1. [NearbyServiceBusyException] + /// 2. [NearbyServiceP2PUnsupportedException] + /// 3. [NearbyServiceNoServiceRequestsException] + /// 4. [NearbyServiceGenericErrorException] + /// 5. [NearbyServiceUnknownException] + /// Future discover(); /// @@ -176,6 +183,13 @@ abstract class NearbyService { /// Note that the [NearbyIOSService] implementation stops **browsing** or /// **advertising** depending on the [NearbyIOSService.isBrowser]. /// + /// On Android can throw mapped from native platform exceptions: + /// 1. [NearbyServiceBusyException] + /// 2. [NearbyServiceP2PUnsupportedException] + /// 3. [NearbyServiceNoServiceRequestsException] + /// 4. [NearbyServiceGenericErrorException] + /// 5. [NearbyServiceUnknownException] + /// Future stopDiscovery(); /// @@ -187,6 +201,13 @@ abstract class NearbyService { /// Note that if [Platform.isIOS] == true, [NearbyIOSDevice] should be passed. /// If [Platform.isAndroid] == true, [NearbyAndroidDevice] should be passed. /// + /// On Android can throw mapped from native platform exceptions: + /// 1. [NearbyServiceBusyException] + /// 2. [NearbyServiceP2PUnsupportedException] + /// 3. [NearbyServiceNoServiceRequestsException] + /// 4. [NearbyServiceGenericErrorException] + /// 5. [NearbyServiceUnknownException] + /// Future connect(NearbyDevice device); /// @@ -196,6 +217,14 @@ abstract class NearbyService { /// If [Platform.isAndroid] == true, [NearbyAndroidDevice] should be passed. /// /// **For IOS [device] is required!!!** + /// + /// On Android can throw mapped from native platform exceptions: + /// 1. [NearbyServiceBusyException] + /// 2. [NearbyServiceP2PUnsupportedException] + /// 3. [NearbyServiceNoServiceRequestsException] + /// 4. [NearbyServiceGenericErrorException] + /// 5. [NearbyServiceUnknownException] + /// Future disconnect([NearbyDevice? device]); /// diff --git a/lib/nearby_service_method_channel.dart b/lib/nearby_service_method_channel.dart index b904cd6..eaf11b9 100644 --- a/lib/nearby_service_method_channel.dart +++ b/lib/nearby_service_method_channel.dart @@ -37,7 +37,7 @@ class MethodChannelNearbyService extends NearbyServicePlatform { @override Future> getPeers() async { return NearbyDeviceMapper.instance.mapToDeviceList( - await methodChannel.invokeMethod('fetchPeers'), + await methodChannel.invokeMethod('getPeers'), ); } diff --git a/lib/src/model/nearby_message_content.dart b/lib/src/model/nearby_message_content.dart index deaf102..3bcbd26 100644 --- a/lib/src/model/nearby_message_content.dart +++ b/lib/src/model/nearby_message_content.dart @@ -6,7 +6,7 @@ import 'package:nearby_service/nearby_service.dart'; /// Contains [value] - the message to be sent or received. /// final class NearbyMessageTextRequest extends NearbyMessageContent { - const NearbyMessageTextRequest._({ + const NearbyMessageTextRequest.createManually({ required this.value, required super.id, }); @@ -17,7 +17,7 @@ final class NearbyMessageTextRequest extends NearbyMessageContent { /// Gets [NearbyMessageTextRequest] from [json] /// factory NearbyMessageTextRequest.fromJson(Map? json) { - return NearbyMessageTextRequest._( + return NearbyMessageTextRequest.createManually( id: json?['id'], value: json?['value'], ); @@ -76,7 +76,7 @@ final class NearbyMessageFilesRequest extends NearbyMessageContent { /// /// Adds a [NearbyFileInfo] list to [id] to identify files. /// - const NearbyMessageFilesRequest._({ + const NearbyMessageFilesRequest.createManually({ required super.id, required this.files, }); @@ -91,7 +91,7 @@ final class NearbyMessageFilesRequest extends NearbyMessageContent { /// Gets [NearbyMessageFilesRequest] from [json]. /// factory NearbyMessageFilesRequest.fromJson(Map? json) { - return NearbyMessageFilesRequest._( + return NearbyMessageFilesRequest.createManually( id: json?['id'], files: [ ...?(json?['files'] as List?)?.map( diff --git a/lib/src/platforms/android/android.dart b/lib/src/platforms/android/android.dart index 73a754f..e56cf5f 100644 --- a/lib/src/platforms/android/android.dart +++ b/lib/src/platforms/android/android.dart @@ -2,3 +2,4 @@ export 'nearby_android_service.dart'; export 'nearby_service_android_interface.dart'; export 'model/nearby_connection_info.dart'; export 'model/nearby_device.dart'; +export 'utils/exception.dart'; diff --git a/lib/src/platforms/android/model/nearby_device.dart b/lib/src/platforms/android/model/nearby_device.dart index 1e22ef4..4697c3b 100644 --- a/lib/src/platforms/android/model/nearby_device.dart +++ b/lib/src/platforms/android/model/nearby_device.dart @@ -143,7 +143,7 @@ class NearbyAndroidMapper implements NearbyDeviceMapper { final decoded = JSONDecoder.decodeList(value); return [ ...?decoded?.map( - (e) => NearbyAndroidDevice.fromJson(e as Map?), + (e) => NearbyAndroidDevice.fromJson(JSONDecoder.decodeMap(e)), ), ]; } diff --git a/lib/src/platforms/android/nearby_service_android_method_channel.dart b/lib/src/platforms/android/nearby_service_android_method_channel.dart index b760580..2d9dc22 100644 --- a/lib/src/platforms/android/nearby_service_android_method_channel.dart +++ b/lib/src/platforms/android/nearby_service_android_method_channel.dart @@ -3,6 +3,8 @@ import 'package:flutter/services.dart'; import 'package:nearby_service/nearby_service.dart'; import 'package:nearby_service/src/utils/logger.dart'; +import 'utils/mapper.dart'; + /// An implementation of [NearbyServiceAndroidPlatform] that uses method channels. class MethodChannelAndroidNearbyService extends NearbyServiceAndroidPlatform { /// The method channel used to interact with the native platform. @@ -39,26 +41,29 @@ class MethodChannelAndroidNearbyService extends NearbyServiceAndroidPlatform { @override Future discover() async { - return (await methodChannel.invokeMethod('discover')) ?? false; + final result = await methodChannel.invokeMethod('discover'); + return _handleBooleanResult(result); } @override Future stopDiscovery() async { - return (await methodChannel.invokeMethod('stopDiscovery')) ?? false; + final result = await methodChannel.invokeMethod('stopDiscovery'); + return _handleBooleanResult(result); } @override Future connect(String deviceAddress) async { - return (await methodChannel.invokeMethod( - "connect", - {"deviceAddress": deviceAddress}, - )) ?? - false; + final result = await methodChannel.invokeMethod( + "connect", + {"deviceAddress": deviceAddress}, + ); + return _handleBooleanResult(result); } @override Future disconnect() async { - return (await methodChannel.invokeMethod("disconnect")) ?? false; + final result = await methodChannel.invokeMethod("disconnect"); + return _handleBooleanResult(result); } @override @@ -70,4 +75,16 @@ class MethodChannelAndroidNearbyService extends NearbyServiceAndroidPlatform { (e) => NearbyConnectionInfoMapper.mapToInfo(e), ); } + + bool _handleBooleanResult(dynamic result) { + if (result is bool) { + return result; + } else if (result is String) { + throw NearbyServiceAndroidExceptionMapper.map(result); + } else { + throw NearbyServiceException( + 'Got unknown value from native platform: $result', + ); + } + } } diff --git a/lib/src/platforms/android/utils/exception.dart b/lib/src/platforms/android/utils/exception.dart new file mode 100644 index 0000000..8e1a740 --- /dev/null +++ b/lib/src/platforms/android/utils/exception.dart @@ -0,0 +1,86 @@ +import 'package:nearby_service/nearby_service.dart'; + +const _kNearbyServiceMessage = 'Got error from native platform with status='; + +/// +/// Wi-Fi P2P is not supported on this device +/// +class NearbyServiceP2PUnsupportedException extends NearbyServiceException { + NearbyServiceP2PUnsupportedException() + : super( + '${_kNearbyServiceMessage}P2P_UNSUPPORTED', + ); + + @override + String toString() { + return 'NearbyServiceP2PUnsupportedException{error: $error}'; + } +} + +/// +/// The Wi-Fi P2P framework is currently busy. +/// Please wait for the current operation to complete before initiating another. +/// +/// Usually this means that you have sent a request to some device and +/// now one of the peers is CONNECTING. +/// +class NearbyServiceBusyException extends NearbyServiceException { + NearbyServiceBusyException() + : super( + '${_kNearbyServiceMessage}BUSY', + ); + + @override + String toString() { + return 'NearbyServiceBusyException{error: $error}'; + } +} + +/// +/// No service discovery requests have been made. Ensure that you have +/// initiated a service discovery request before attempting to connect. +/// +class NearbyServiceNoServiceRequestsException extends NearbyServiceException { + NearbyServiceNoServiceRequestsException() + : super( + '${_kNearbyServiceMessage}NO_SERVICE_REQUESTS', + ); + + @override + String toString() { + return 'NearbyServiceNoServiceRequestsException{error: $error}'; + } +} + +/// +/// A generic error occurred. This could be due to various reasons such as +/// hardware issues, Wi-Fi being turned off, or temporary issues with the +/// Wi-Fi P2P framework. +/// +class NearbyServiceGenericErrorException extends NearbyServiceException { + NearbyServiceGenericErrorException() + : super( + '${_kNearbyServiceMessage}ERROR', + ); + + @override + String toString() { + return 'NearbyServiceGenericErrorException{error: $error}'; + } +} + +/// +/// An unknown error occurred. Please check the device's Wi-Fi +/// P2P settings and ensure the device supports Wi-Fi P2P. +/// +class NearbyServiceUnknownException extends NearbyServiceException { + NearbyServiceUnknownException() + : super( + '${_kNearbyServiceMessage}UNKNOWN', + ); + + @override + String toString() { + return 'NearbyServiceUnknownException{error: $error}'; + } +} diff --git a/lib/src/platforms/android/utils/mapper.dart b/lib/src/platforms/android/utils/mapper.dart new file mode 100644 index 0000000..b4fc183 --- /dev/null +++ b/lib/src/platforms/android/utils/mapper.dart @@ -0,0 +1,26 @@ +import 'package:nearby_service/nearby_service.dart'; + +class NearbyServiceAndroidExceptionMapper { + NearbyServiceAndroidExceptionMapper._(); + + static NearbyServiceException map(String error) { + AndroidFailureCodes? enumValue; + try { + enumValue = AndroidFailureCodes.values.firstWhere( + (element) => element.name == error, + ); + } catch (_) {} + return switch (enumValue) { + AndroidFailureCodes.BUSY => NearbyServiceBusyException(), + AndroidFailureCodes.ERROR => NearbyServiceGenericErrorException(), + AndroidFailureCodes.P2P_UNSUPPORTED => + NearbyServiceP2PUnsupportedException(), + AndroidFailureCodes.NO_SERVICE_REQUESTS => + NearbyServiceNoServiceRequestsException(), + _ => NearbyServiceUnknownException(), + }; + } +} + +// ignore: constant_identifier_names +enum AndroidFailureCodes { P2P_UNSUPPORTED, BUSY, NO_SERVICE_REQUESTS, ERROR } diff --git a/lib/src/platforms/ios/model/nearby_device.dart b/lib/src/platforms/ios/model/nearby_device.dart index 5aa44f5..bddd647 100644 --- a/lib/src/platforms/ios/model/nearby_device.dart +++ b/lib/src/platforms/ios/model/nearby_device.dart @@ -78,7 +78,7 @@ class NearbyIOSMapper implements NearbyDeviceMapper { final decoded = JSONDecoder.decodeList(value); return [ ...?decoded?.map( - (e) => NearbyIOSDevice.fromJson(e as Map?), + (e) => NearbyIOSDevice.fromJson(JSONDecoder.decodeMap(e)), ), ]; } diff --git a/lib/src/utils/exception.dart b/lib/src/utils/exception.dart index c6fa622..3a00808 100644 --- a/lib/src/utils/exception.dart +++ b/lib/src/utils/exception.dart @@ -14,28 +14,26 @@ class NearbyServiceException implements Exception { } /// - /// A call from an unsupported platform. + /// Usage of the plugin on an unsupported platform /// - factory NearbyServiceException.unsupportedPlatform({required String caller}) { - return NearbyServiceException( - '$caller is not supported for platform ${Platform.operatingSystem}', - ); - } + factory NearbyServiceException.unsupportedPlatform({ + required String caller, + }) => + NearbyServiceUnsupportedPlatformException(caller: caller); /// - /// A decoding error. + /// Error decoding messages from native platform to Dart (open an issue if + /// this happens!) /// - factory NearbyServiceException.unsupportedDecoding(dynamic value) { - return NearbyServiceException( - 'Got unknown value=$value with runtimeType=${value.runtimeType}', - ); - } + factory NearbyServiceException.unsupportedDecoding(dynamic value) => + NearbyServiceUnsupportedDecodingException(value); - factory NearbyServiceException.invalidMessage(NearbyMessageContent content) { - return NearbyServiceException( - 'The message="$content" is not valid', - ); - } + /// + /// An attempt to send an invalid message on the sender's side. Add content + /// validation to your messages + /// + factory NearbyServiceException.invalidMessage(NearbyMessageContent content) => + NearbyServiceInvalidMessageException(content); final Object? error; @@ -44,3 +42,59 @@ class NearbyServiceException implements Exception { return 'NearbyServiceException{error: $error}'; } } + +/// +/// Usage of the plugin on an unsupported platform +/// +class NearbyServiceUnsupportedPlatformException extends NearbyServiceException { + /// + /// Usage of the plugin on an unsupported platform - default constructor + /// + NearbyServiceUnsupportedPlatformException({required String caller}) + : super( + '$caller is not supported for platform ${Platform.operatingSystem}', + ); + + @override + String toString() { + return 'NearbyServiceUnsupportedPlatformException{error: $error}'; + } +} + +/// +/// Error decoding messages from native platform to Dart (open an issue if +/// this happens!) +/// +class NearbyServiceUnsupportedDecodingException extends NearbyServiceException { + /// + /// A decoding error - default constructor + /// + NearbyServiceUnsupportedDecodingException(dynamic value) + : super( + 'Got unknown value=$value with runtimeType=${value.runtimeType}', + ); + + @override + String toString() { + return 'NearbyServiceUnsupportedDecodingException{error: $error}'; + } +} + +/// +/// An attempt to send an invalid message on the sender's side. Add content +/// validation to your messages +/// +class NearbyServiceInvalidMessageException extends NearbyServiceException { + /// + /// Invalid message error - default constructor + /// + NearbyServiceInvalidMessageException(NearbyMessageContent content) + : super( + 'The message="$content" is not valid', + ); + + @override + String toString() { + return 'NearbyServiceInvalidMessageException{error: $error}'; + } +} diff --git a/lib/src/utils/file_socket.dart b/lib/src/utils/file_socket.dart index 0c57a50..52fe27f 100644 --- a/lib/src/utils/file_socket.dart +++ b/lib/src/utils/file_socket.dart @@ -62,10 +62,10 @@ class FilesSocket { addChunk(event); } else if (event == separateCommandOf(_currentFileIndex)) { _futures.add(_createFile(_currentFileIndex)); + Logger.info('Completed receiving file №${_currentFileIndex + 1}'); _currentFileIndex = _currentFileIndex + 1; _chunksCount = 0; _bytesTable['$_currentFileIndex'] = []; - Logger.info('Completed receiving file №${_currentFileIndex - 1}'); } else if (event == finishCommand) { await Future.wait(_futures); Logger.info('Files pack ${filesRequest.id} was created'); diff --git a/pubspec.yaml b/pubspec.yaml index 49dcf22..9123822 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: nearby_service description: Nearby Service Flutter Plugin is used to create connections in a P2P network. Supports sending text messages and files. -version: 0.0.6 +version: 0.0.7 homepage: https://github.com/ksenia312/nearby_service repository: https://github.com/ksenia312/nearby_service