Fix: Android native connection errors are not displayed (#5)
* fix(android, lib): add error logging, handle running jobs exception * doc(app_service): add comment * fix(exampl_full, utils): move getCurrentDevice info and fix logs * doc: add comments, update changelog * doc: update changelog * version: 0.0.7 * doc: update readme * doc: update readme
This commit is contained in:
@@ -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
|
## 0.0.6
|
||||||
|
|
||||||
- Update README: add a Feedback form
|
- Update README: add a Feedback form
|
||||||
|
|||||||
@@ -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,
|
The plugin supports sending text messages and files. With it,
|
||||||
you can easily create any kind of information sharing application **without Internet connection**.
|
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
|
## Table of Contents
|
||||||
|
|
||||||
@@ -26,6 +30,7 @@ Your feedback and suggestions would be greatly appreciated! [You can leave your
|
|||||||
- [Data sharing](#data-sharing)
|
- [Data sharing](#data-sharing)
|
||||||
- [Text messages](#text-messages)
|
- [Text messages](#text-messages)
|
||||||
- [Resource messages](#resource-messages)
|
- [Resource messages](#resource-messages)
|
||||||
|
- [Exceptions](#exceptions)
|
||||||
- [Additional options](#additional-options)
|
- [Additional options](#additional-options)
|
||||||
- [Demo](#demo)
|
- [Demo](#demo)
|
||||||
## About
|
## 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
|
## Additional options
|
||||||
|
|
||||||
- Each `NearbyDevice` contains `NearbyDeviceInfo` that presents different meanings depending on the platform. For
|
- Each `NearbyDevice` contains `NearbyDeviceInfo` that presents different meanings depending on the platform. For
|
||||||
|
|||||||
@@ -19,19 +19,19 @@ class Logger {
|
|||||||
var level = LogLevel.DEBUG
|
var level = LogLevel.DEBUG
|
||||||
fun d(message: String) {
|
fun d(message: String) {
|
||||||
if (level.value <= LogLevel.DEBUG.value) {
|
if (level.value <= LogLevel.DEBUG.value) {
|
||||||
Log.d(TAG, message)
|
Log.d(TAG, "\u001B[37m$message\u001B[0m")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun i(message: String) {
|
fun i(message: String) {
|
||||||
if (level.value <= LogLevel.INFO.value) {
|
if (level.value <= LogLevel.INFO.value) {
|
||||||
Log.i(TAG, message)
|
Log.i(TAG, "\u001B[32m$message\u001B[0m")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun e(message: String) {
|
fun e(message: String) {
|
||||||
if (level.value <= LogLevel.ERROR.value) {
|
if (level.value <= LogLevel.ERROR.value) {
|
||||||
Log.e(TAG, message)
|
Log.e(TAG, "\u001B[31m$message\u001B[0m")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,11 @@ class NearbyServiceBroadcastReceiver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun init() {
|
||||||
|
writeDevices()
|
||||||
|
writeConnectionInfo()
|
||||||
|
}
|
||||||
|
|
||||||
private fun logState(intent: Intent) {
|
private fun logState(intent: Intent) {
|
||||||
when (intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1)) {
|
when (intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1)) {
|
||||||
WifiP2pManager.WIFI_P2P_STATE_ENABLED -> {
|
WifiP2pManager.WIFI_P2P_STATE_ENABLED -> {
|
||||||
|
|||||||
@@ -121,7 +121,11 @@ class NearbyServiceManager(private var context: Context) {
|
|||||||
fun discover(result: Result) {
|
fun discover(result: Result) {
|
||||||
try {
|
try {
|
||||||
wifiManager.discoverPeers(
|
wifiManager.discoverPeers(
|
||||||
wifiChannel, getActionListener(result)
|
wifiChannel, getActionListener(
|
||||||
|
result,
|
||||||
|
"Discovery has started successfully!",
|
||||||
|
"Discovery starting failed"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
} catch (e: SecurityException) {
|
} catch (e: SecurityException) {
|
||||||
if (!permissionsHandler.checkPermissions()) {
|
if (!permissionsHandler.checkPermissions()) {
|
||||||
@@ -136,7 +140,11 @@ class NearbyServiceManager(private var context: Context) {
|
|||||||
*/
|
*/
|
||||||
fun stopDiscovery(result: Result) {
|
fun stopDiscovery(result: Result) {
|
||||||
wifiManager.stopPeerDiscovery(
|
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(
|
val actionListener = getActionListener(
|
||||||
result,
|
result,
|
||||||
"Connected to device $deviceAddress",
|
"Connection request sent to device $deviceAddress",
|
||||||
"Connecting to device $deviceAddress failed"
|
"Connecting to device $deviceAddress failed"
|
||||||
)
|
)
|
||||||
config.deviceAddress = deviceAddress
|
config.deviceAddress = deviceAddress
|
||||||
@@ -216,12 +224,17 @@ class NearbyServiceManager(private var context: Context) {
|
|||||||
permissionsHandler,
|
permissionsHandler,
|
||||||
)
|
)
|
||||||
context.registerReceiver(receiver, intentFilter)
|
context.registerReceiver(receiver, intentFilter)
|
||||||
|
try {
|
||||||
|
receiver.init()
|
||||||
|
} catch (error: Throwable) {
|
||||||
|
Logger.e("Failed to write initial info, error=${error.message}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getActionListener(
|
private fun getActionListener(
|
||||||
result: Result?,
|
result: Result?,
|
||||||
successMessage: String? = null,
|
successMessage: String? = null,
|
||||||
errorMessage: String? = null,
|
errorMessage: String
|
||||||
): WifiP2pManager.ActionListener {
|
): WifiP2pManager.ActionListener {
|
||||||
return object : WifiP2pManager.ActionListener {
|
return object : WifiP2pManager.ActionListener {
|
||||||
override fun onSuccess() {
|
override fun onSuccess() {
|
||||||
@@ -232,10 +245,22 @@ class NearbyServiceManager(private var context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(reasonCode: Int) {
|
override fun onFailure(reasonCode: Int) {
|
||||||
if (errorMessage != null) {
|
val reason = when (reasonCode) {
|
||||||
Logger.e("ERROR: $errorMessage Reason code: $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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ class _AppBodyState extends State<AppBody> {
|
|||||||
children: [
|
children: [
|
||||||
if (Platform.isIOS)
|
if (Platform.isIOS)
|
||||||
Text('You are ${_isIosBrowser ? 'Browser' : 'Advertiser'}'),
|
Text('You are ${_isIosBrowser ? 'Browser' : 'Advertiser'}'),
|
||||||
|
if (_peers.isEmpty) const Text('Searching for peers...'),
|
||||||
..._peers.map(
|
..._peers.map(
|
||||||
(e) => PeerWidget(
|
(e) => PeerWidget(
|
||||||
device: e,
|
device: e,
|
||||||
|
|||||||
@@ -50,10 +50,8 @@ class AppService extends ChangeNotifier {
|
|||||||
updateState(
|
updateState(
|
||||||
Platform.isAndroid ? AppState.permissions : AppState.selectClientType,
|
Platform.isAndroid ? AppState.permissions : AppState.selectClientType,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e, s) {
|
||||||
if (kDebugMode) {
|
_log(e, s);
|
||||||
print(e);
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
@@ -62,10 +60,8 @@ class AppService extends ChangeNotifier {
|
|||||||
Future<void> getCurrentDeviceInfo() async {
|
Future<void> getCurrentDeviceInfo() async {
|
||||||
try {
|
try {
|
||||||
currentDeviceInfo = await _nearbyService.getCurrentDeviceInfo();
|
currentDeviceInfo = await _nearbyService.getCurrentDeviceInfo();
|
||||||
} catch (e) {
|
} catch (e, s) {
|
||||||
if (kDebugMode) {
|
_log(e, s);
|
||||||
print(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,10 +71,8 @@ class AppService extends ChangeNotifier {
|
|||||||
if (result ?? false) {
|
if (result ?? false) {
|
||||||
updateState(AppState.checkServices);
|
updateState(AppState.checkServices);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e, s) {
|
||||||
if (kDebugMode) {
|
_log(e, s);
|
||||||
print(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,17 +95,41 @@ class AppService extends ChangeNotifier {
|
|||||||
updateState(AppState.readyToDiscover);
|
updateState(AppState.readyToDiscover);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> 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<void> discover() async {
|
Future<void> discover() async {
|
||||||
try {
|
try {
|
||||||
await getCurrentDeviceInfo();
|
await getCurrentDeviceInfo();
|
||||||
final result = await _nearbyService.discover();
|
final hasRunning = await hasRunningJobs();
|
||||||
if (result) {
|
if (hasRunning) {
|
||||||
updateState(AppState.discoveringPeers);
|
updateState(AppState.discoveringPeers);
|
||||||
|
} else {
|
||||||
|
final result = await _nearbyService.discover();
|
||||||
|
if (result) {
|
||||||
|
updateState(AppState.discoveringPeers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} on NearbyServiceBusyException catch (_) {
|
||||||
if (kDebugMode) {
|
_logBusyException();
|
||||||
print(e);
|
} catch (e, s) {
|
||||||
}
|
_log(e, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,20 +139,20 @@ class AppService extends ChangeNotifier {
|
|||||||
if (result) {
|
if (result) {
|
||||||
updateState(AppState.readyToDiscover);
|
updateState(AppState.readyToDiscover);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} on NearbyServiceBusyException catch (_) {
|
||||||
if (kDebugMode) {
|
_logBusyException();
|
||||||
print(e);
|
} catch (e, s) {
|
||||||
}
|
_log(e, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> connect(NearbyDevice device) async {
|
Future<void> connect(NearbyDevice device) async {
|
||||||
try {
|
try {
|
||||||
await _nearbyService.connect(device);
|
await _nearbyService.connect(device);
|
||||||
} catch (e) {
|
} on NearbyServiceBusyException catch (_) {
|
||||||
if (kDebugMode) {
|
_logBusyException();
|
||||||
print(e);
|
} catch (e, s) {
|
||||||
}
|
_log(e, s);
|
||||||
}
|
}
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
@@ -142,10 +160,10 @@ class AppService extends ChangeNotifier {
|
|||||||
Future<void> disconnect([NearbyDevice? device]) async {
|
Future<void> disconnect([NearbyDevice? device]) async {
|
||||||
try {
|
try {
|
||||||
await _nearbyService.disconnect(device);
|
await _nearbyService.disconnect(device);
|
||||||
} catch (e) {
|
} on NearbyServiceBusyException catch (_) {
|
||||||
if (kDebugMode) {
|
_logBusyException();
|
||||||
print(e);
|
} catch (e, s) {
|
||||||
}
|
_log(e, s);
|
||||||
} finally {
|
} finally {
|
||||||
await stopListeningAll();
|
await stopListeningAll();
|
||||||
}
|
}
|
||||||
@@ -194,10 +212,8 @@ extension ConnectionInfoExtension on AppService {
|
|||||||
_notify();
|
_notify();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e, s) {
|
||||||
if (kDebugMode) {
|
_log(e, s);
|
||||||
print(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_notify();
|
_notify();
|
||||||
}
|
}
|
||||||
@@ -218,10 +234,8 @@ extension PeersExtension on AppService {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
updateState(AppState.streamingPeers);
|
updateState(AppState.streamingPeers);
|
||||||
} catch (e) {
|
} catch (e, s) {
|
||||||
if (kDebugMode) {
|
_log(e, s);
|
||||||
print(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,10 +324,8 @@ extension CommunicationChannelExtension on AppService {
|
|||||||
Future<void> endCommunicationChannel() async {
|
Future<void> endCommunicationChannel() async {
|
||||||
try {
|
try {
|
||||||
await _nearbyService.endCommunicationChannel();
|
await _nearbyService.endCommunicationChannel();
|
||||||
} catch (e) {
|
} catch (e, s) {
|
||||||
if (kDebugMode) {
|
_log(e, s);
|
||||||
print(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_notify();
|
_notify();
|
||||||
}
|
}
|
||||||
@@ -384,3 +396,19 @@ extension MessagingExtension on AppService {
|
|||||||
_notify();
|
_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)',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -168,6 +168,13 @@ abstract class NearbyService {
|
|||||||
/// Note that the [NearbyIOSService] implementation starts **browsing** or
|
/// Note that the [NearbyIOSService] implementation starts **browsing** or
|
||||||
/// **advertising** depending on the [NearbyIOSService.isBrowser].
|
/// **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<bool> discover();
|
Future<bool> discover();
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -176,6 +183,13 @@ abstract class NearbyService {
|
|||||||
/// Note that the [NearbyIOSService] implementation stops **browsing** or
|
/// Note that the [NearbyIOSService] implementation stops **browsing** or
|
||||||
/// **advertising** depending on the [NearbyIOSService.isBrowser].
|
/// **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<bool> stopDiscovery();
|
Future<bool> stopDiscovery();
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -187,6 +201,13 @@ abstract class NearbyService {
|
|||||||
/// Note that if [Platform.isIOS] == true, [NearbyIOSDevice] should be passed.
|
/// Note that if [Platform.isIOS] == true, [NearbyIOSDevice] should be passed.
|
||||||
/// If [Platform.isAndroid] == true, [NearbyAndroidDevice] 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<bool> connect(NearbyDevice device);
|
Future<bool> connect(NearbyDevice device);
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -196,6 +217,14 @@ abstract class NearbyService {
|
|||||||
/// If [Platform.isAndroid] == true, [NearbyAndroidDevice] should be passed.
|
/// If [Platform.isAndroid] == true, [NearbyAndroidDevice] should be passed.
|
||||||
///
|
///
|
||||||
/// **For IOS [device] is required!!!**
|
/// **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<bool> disconnect([NearbyDevice? device]);
|
Future<bool> disconnect([NearbyDevice? device]);
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class MethodChannelNearbyService extends NearbyServicePlatform {
|
|||||||
@override
|
@override
|
||||||
Future<List<NearbyDevice>> getPeers() async {
|
Future<List<NearbyDevice>> getPeers() async {
|
||||||
return NearbyDeviceMapper.instance.mapToDeviceList(
|
return NearbyDeviceMapper.instance.mapToDeviceList(
|
||||||
await methodChannel.invokeMethod('fetchPeers'),
|
await methodChannel.invokeMethod('getPeers'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import 'package:nearby_service/nearby_service.dart';
|
|||||||
/// Contains [value] - the message to be sent or received.
|
/// Contains [value] - the message to be sent or received.
|
||||||
///
|
///
|
||||||
final class NearbyMessageTextRequest extends NearbyMessageContent {
|
final class NearbyMessageTextRequest extends NearbyMessageContent {
|
||||||
const NearbyMessageTextRequest._({
|
const NearbyMessageTextRequest.createManually({
|
||||||
required this.value,
|
required this.value,
|
||||||
required super.id,
|
required super.id,
|
||||||
});
|
});
|
||||||
@@ -17,7 +17,7 @@ final class NearbyMessageTextRequest extends NearbyMessageContent {
|
|||||||
/// Gets [NearbyMessageTextRequest] from [json]
|
/// Gets [NearbyMessageTextRequest] from [json]
|
||||||
///
|
///
|
||||||
factory NearbyMessageTextRequest.fromJson(Map<String, dynamic>? json) {
|
factory NearbyMessageTextRequest.fromJson(Map<String, dynamic>? json) {
|
||||||
return NearbyMessageTextRequest._(
|
return NearbyMessageTextRequest.createManually(
|
||||||
id: json?['id'],
|
id: json?['id'],
|
||||||
value: json?['value'],
|
value: json?['value'],
|
||||||
);
|
);
|
||||||
@@ -76,7 +76,7 @@ final class NearbyMessageFilesRequest extends NearbyMessageContent {
|
|||||||
///
|
///
|
||||||
/// Adds a [NearbyFileInfo] list to [id] to identify files.
|
/// Adds a [NearbyFileInfo] list to [id] to identify files.
|
||||||
///
|
///
|
||||||
const NearbyMessageFilesRequest._({
|
const NearbyMessageFilesRequest.createManually({
|
||||||
required super.id,
|
required super.id,
|
||||||
required this.files,
|
required this.files,
|
||||||
});
|
});
|
||||||
@@ -91,7 +91,7 @@ final class NearbyMessageFilesRequest extends NearbyMessageContent {
|
|||||||
/// Gets [NearbyMessageFilesRequest] from [json].
|
/// Gets [NearbyMessageFilesRequest] from [json].
|
||||||
///
|
///
|
||||||
factory NearbyMessageFilesRequest.fromJson(Map<String, dynamic>? json) {
|
factory NearbyMessageFilesRequest.fromJson(Map<String, dynamic>? json) {
|
||||||
return NearbyMessageFilesRequest._(
|
return NearbyMessageFilesRequest.createManually(
|
||||||
id: json?['id'],
|
id: json?['id'],
|
||||||
files: [
|
files: [
|
||||||
...?(json?['files'] as List?)?.map(
|
...?(json?['files'] as List?)?.map(
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ export 'nearby_android_service.dart';
|
|||||||
export 'nearby_service_android_interface.dart';
|
export 'nearby_service_android_interface.dart';
|
||||||
export 'model/nearby_connection_info.dart';
|
export 'model/nearby_connection_info.dart';
|
||||||
export 'model/nearby_device.dart';
|
export 'model/nearby_device.dart';
|
||||||
|
export 'utils/exception.dart';
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ class NearbyAndroidMapper implements NearbyDeviceMapper {
|
|||||||
final decoded = JSONDecoder.decodeList(value);
|
final decoded = JSONDecoder.decodeList(value);
|
||||||
return [
|
return [
|
||||||
...?decoded?.map(
|
...?decoded?.map(
|
||||||
(e) => NearbyAndroidDevice.fromJson(e as Map<String, dynamic>?),
|
(e) => NearbyAndroidDevice.fromJson(JSONDecoder.decodeMap(e)),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:nearby_service/nearby_service.dart';
|
import 'package:nearby_service/nearby_service.dart';
|
||||||
import 'package:nearby_service/src/utils/logger.dart';
|
import 'package:nearby_service/src/utils/logger.dart';
|
||||||
|
|
||||||
|
import 'utils/mapper.dart';
|
||||||
|
|
||||||
/// An implementation of [NearbyServiceAndroidPlatform] that uses method channels.
|
/// An implementation of [NearbyServiceAndroidPlatform] that uses method channels.
|
||||||
class MethodChannelAndroidNearbyService extends NearbyServiceAndroidPlatform {
|
class MethodChannelAndroidNearbyService extends NearbyServiceAndroidPlatform {
|
||||||
/// The method channel used to interact with the native platform.
|
/// The method channel used to interact with the native platform.
|
||||||
@@ -39,26 +41,29 @@ class MethodChannelAndroidNearbyService extends NearbyServiceAndroidPlatform {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> discover() async {
|
Future<bool> discover() async {
|
||||||
return (await methodChannel.invokeMethod<bool>('discover')) ?? false;
|
final result = await methodChannel.invokeMethod('discover');
|
||||||
|
return _handleBooleanResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> stopDiscovery() async {
|
Future<bool> stopDiscovery() async {
|
||||||
return (await methodChannel.invokeMethod<bool>('stopDiscovery')) ?? false;
|
final result = await methodChannel.invokeMethod('stopDiscovery');
|
||||||
|
return _handleBooleanResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> connect(String deviceAddress) async {
|
Future<bool> connect(String deviceAddress) async {
|
||||||
return (await methodChannel.invokeMethod<bool?>(
|
final result = await methodChannel.invokeMethod(
|
||||||
"connect",
|
"connect",
|
||||||
{"deviceAddress": deviceAddress},
|
{"deviceAddress": deviceAddress},
|
||||||
)) ??
|
);
|
||||||
false;
|
return _handleBooleanResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> disconnect() async {
|
Future<bool> disconnect() async {
|
||||||
return (await methodChannel.invokeMethod<bool?>("disconnect")) ?? false;
|
final result = await methodChannel.invokeMethod("disconnect");
|
||||||
|
return _handleBooleanResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -70,4 +75,16 @@ class MethodChannelAndroidNearbyService extends NearbyServiceAndroidPlatform {
|
|||||||
(e) => NearbyConnectionInfoMapper.mapToInfo(e),
|
(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',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 }
|
||||||
@@ -78,7 +78,7 @@ class NearbyIOSMapper implements NearbyDeviceMapper {
|
|||||||
final decoded = JSONDecoder.decodeList(value);
|
final decoded = JSONDecoder.decodeList(value);
|
||||||
return [
|
return [
|
||||||
...?decoded?.map(
|
...?decoded?.map(
|
||||||
(e) => NearbyIOSDevice.fromJson(e as Map<String, dynamic>?),
|
(e) => NearbyIOSDevice.fromJson(JSONDecoder.decodeMap(e)),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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}) {
|
factory NearbyServiceException.unsupportedPlatform({
|
||||||
return NearbyServiceException(
|
required String caller,
|
||||||
'$caller is not supported for platform ${Platform.operatingSystem}',
|
}) =>
|
||||||
);
|
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) {
|
factory NearbyServiceException.unsupportedDecoding(dynamic value) =>
|
||||||
return NearbyServiceException(
|
NearbyServiceUnsupportedDecodingException(value);
|
||||||
'Got unknown value=$value with runtimeType=${value.runtimeType}',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
factory NearbyServiceException.invalidMessage(NearbyMessageContent content) {
|
///
|
||||||
return NearbyServiceException(
|
/// An attempt to send an invalid message on the sender's side. Add content
|
||||||
'The message="$content" is not valid',
|
/// validation to your messages
|
||||||
);
|
///
|
||||||
}
|
factory NearbyServiceException.invalidMessage(NearbyMessageContent content) =>
|
||||||
|
NearbyServiceInvalidMessageException(content);
|
||||||
|
|
||||||
final Object? error;
|
final Object? error;
|
||||||
|
|
||||||
@@ -44,3 +42,59 @@ class NearbyServiceException implements Exception {
|
|||||||
return 'NearbyServiceException{error: $error}';
|
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}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -62,10 +62,10 @@ class FilesSocket {
|
|||||||
addChunk(event);
|
addChunk(event);
|
||||||
} else if (event == separateCommandOf(_currentFileIndex)) {
|
} else if (event == separateCommandOf(_currentFileIndex)) {
|
||||||
_futures.add(_createFile(_currentFileIndex));
|
_futures.add(_createFile(_currentFileIndex));
|
||||||
|
Logger.info('Completed receiving file №${_currentFileIndex + 1}');
|
||||||
_currentFileIndex = _currentFileIndex + 1;
|
_currentFileIndex = _currentFileIndex + 1;
|
||||||
_chunksCount = 0;
|
_chunksCount = 0;
|
||||||
_bytesTable['$_currentFileIndex'] = [];
|
_bytesTable['$_currentFileIndex'] = [];
|
||||||
Logger.info('Completed receiving file №${_currentFileIndex - 1}');
|
|
||||||
} else if (event == finishCommand) {
|
} else if (event == finishCommand) {
|
||||||
await Future.wait(_futures);
|
await Future.wait(_futures);
|
||||||
Logger.info('Files pack ${filesRequest.id} was created');
|
Logger.info('Files pack ${filesRequest.id} was created');
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
name: nearby_service
|
name: nearby_service
|
||||||
description: Nearby Service Flutter Plugin is used to create connections in a P2P network. Supports sending text messages and files.
|
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
|
homepage: https://github.com/ksenia312/nearby_service
|
||||||
repository: https://github.com/ksenia312/nearby_service
|
repository: https://github.com/ksenia312/nearby_service
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user