How can i comunicate between two devices without cloud server? - flutter

I tried develop an mobile app its share my current geolocate without cloud server between two devices whos install same apps .This devices posible using internet and it have cellphone number.
So i set fullter and add google map flugin. And i marked my current geolocate in google map also. But i stuck in issue.
"How can i send my current gelocate data to another device whitout any cloud server?"
I consider socketio. But i can't find way how can get correct device address
that receive device.
private Socket mSocket;
#Override
protected void onCreate(Bundle savedInstanceState) {
try {
mSocket = IO.socket("How can i get this url");
mSocket.connect();
} catch(URISyntaxException e) {
e.printStackTrace();
}
}
Or what is best way from this issue?

Related

BLE iOS - Failed to encrypt the connection, the connection has timed out unexpectedly

I'm using #capacitor-community/bluetooth-le to connect my Ionic 6 APP to a specific BLE device.
In Android everything works fine.
In iOS, first time connects to BLE successfully but next times (after pairing) gives the following error when try to connects: "Failed to encrypt the connection, the connection has timed out unexpectedly."
I have been tried a lot of different approachs: connects after scan. Connects when is scanning. But nothing works. What is strange is in first time everything works fine (after pairing).
Any help?
Unfortunately this is kind of a known issue in iOS. What I think is happening is that because you have already paired/bonded with the device at the OS level, the connection is being re-established at the OS level when the remote BLE device is discoverable. When you are attempting to reconnect to the remote device from your app, a connection is already in place at the OS level which is why it is failing at the app level. Alternatively, maybe the stored keys from the bonding process is causing the rebonding/pairing process to clash. You can confirm the issue by doing the following:-
Go to the iOS settings, Bluetooth, then unpair the device if it exists.
Attempt to reconnect to the device from your iOS app.
Disconnect the device from your iOS app (do not unpair from the Bluetooth settings this time).
Try to connect to the remote device from your Android app (or any other device that you can use apart from the iOS device). If the connection doesn't succeed, it means that the iOS device is still connected to the remote device.
If the connection succeeds from the Android device, try to disconnect and reconnect from the iOS device. If the connection succeeds, you'll know that the issue is with the OS level connection, and if the connection doesn't succeed, you'll know that the issue is with the stored bonding/pairing keys clashing.
As for the solution, I don't think there's a simple and straight-forward one unfortunately. Below is one suggested solution which I found useful in the past (you may need to modify this for your ionic app):-
In some cases, like for HID devices, once a peripheral is bonded, iOS
will automatically connect to it whenever it sees the peripheral
advertising. This behavior occurs independently of any app, and a
peripheral can be connected to an iOS device, but not connected to the
app that originally established the bond. If a bonded peripheral
disconnects from an iOS device and then reconnects at the iOS level,
the app will need to retrieve the peripheral object
(retrieveConnectedPeripherals(with[Services/Identifiers]:) and
explicitly connect again through a CBCentralManager to establish an
app-level connection. To retrieve your device with this method, you
must specify either the Apple-assigned device identifier from the
previously-returned CBPeripheral object or at least one service it
contains.
iOS does not allow developer apps to clear a peripheral’s bonding
status from the cache. To clear a bond, the user must go to the
Bluetooth section of iOS Settings and explicitly “Forget” the
peripheral. It may be helpful to include this information in your
app’s UI if it’ll affect user experience, as most users will not know
this.
You can find more information about this in the links below:-
The ultimate guide to Apple's CoreBluetooth
CoreBluetooth iOS pairing issue
CoreBluetooth pairing/forgetting
Unable to reconnect after cancelling BLE peripheral
In my case after iPhone pairs with peripheral, never connects anymore. What is strange, in my iPhone 6s with iOS 15.5 everythings works fine.
The pugin has this code (it's possible to some is wrong?)
https://github.com/capacitor-community/bluetooth-le/blob/main/ios/Plugin/Plugin.swift
let CONNECTION_TIMEOUT: Double = 10
let DEFAULT_TIMEOUT: Double = 5
#objc func connect(_ call: CAPPluginCall) {
guard self.getDeviceManager(call) != nil else { return }
guard let device = self.getDevice(call, checkConnection: false) else { return }
let timeout = self.getTimeout(call, defaultTimeout: CONNECTION_TIMEOUT)
device.setOnConnected(timeout, {(success, message) -> Void in
if success {
// only resolve after service discovery
call.resolve()
} else {
call.reject(message)
}
})
self.deviceManager?.setOnDisconnected(device, {(_, _) -> Void in
let key = "disconnected|\(device.getId())"
self.notifyListeners(key, data: nil)
})
self.deviceManager?.connect(device, timeout, {(success, message) -> Void in
if success {
log("Connected to peripheral. Waiting for service discovery.")
} else {
call.reject(message)
}
})
}
I already tried another plugins, and the result is the same.

How to connect to Ble device without rescan and manual device selection

I'm creating an Ionic react (TypeScript) app which uses the Community Bluetooth-le plugin.
When I try to connect to a device using requestDevice this shows the available devices and I can then pair/connect with that device and all is good.
await BleClient.initialize();
if (isAndroid) {
await BleClient.disconnect(devices.deviceId);
}
const device = await BleClient.requestDevice({
services: services ? services : [],
optionalServices: optionalServices ? optionalServices : [],
namePrefix: prefixFilter ? prefixFilter : "",
});
await BleClient.connect(device.deviceId, (deviceId) => onDisconnect(deviceId));
await BleClient.getServices(device.deviceId).then(
(services) => {
if (services[0]) {
//....
} else {
//....
}
}
)
However, if I save the device ID and then try to directly connect with that device using getDevices (rather than scanning and manually connecting) it always fails with the following console output:
Uncaught (in promise) Error: Device not found. Call "requestDevice", "requestLEScan" or "getDevices" first.
The code I use is this:
await BleClient.initialize();
if (isAndroid) {
await BleClient.disconnect(devices.deviceId);
}
await BleClient.getDevices(devices.deviceId);
await BleClient.connect(devices.deviceId, (deviceId) => onDisconnect(deviceId));
For clarification: I want to be able to search for available devices and connect to the device the first time the app is opened. Then, save the device ID and use this ID to connect to the device directly using getDevices from that point onwards. Likewise if the app is closed and re-opened I need to be able to take the stored device data and connect with that device directly without the whole scan and manual selection process.
I don't understand what I'm missing.
I assume Device-1 (app) is scanning and Device-2 is advertising. Try to bond the devices after first time connection. This allow you to connect it automatically without scanning next time.
Make sure the Device-2 is in connectable mode after getting disconnected from Device-1.
EDIT-1
For example I am using a generic app called nRF connect and a smart watch. In this app we can scan and connect with any BLE device. I am following below steps:
Scan
Connect
Bond (option available under 3 dots at top right corner, refer image)
After third step, device get bonded and later whenever the device is in vicinity you can connect with it, without advertising and scanning. PFA image.
This is the overview of process to be followed, in regards to code you can get many ready examples related to android or iOS. Hope this is helpful!!

How to register an app listener in flutter for an internet connectivity event?

I have an app flutter that runs in Android and iOS.
This app is used in areas without any internet connection. When the user arrives at some place with internet connection, all the offline data must be sent to the servers.
Have an background task running and checking in loop for internet connections, or even a recurrent scheduled task, is not an option because:
The moment between the use of the app in the field and the moment that the user will be in place with internet connection might take many hours.
Running threads in background will consume resources and draw the mobile battery.
Android/iOS might finish the background process and the data not be sent unless the user open the app.
I'm wondering how to register a kind of listener, listening for "internet connectivity events" broadcasted by operating system when they happen and that will awake my app and trigger callback.
Then, I don't have to keep an unnecessary background task running infinitely but I can still do the job when the mobile get connected in the internet, even having my app closed/sleeping.
How can I do it in flutter ?
There's a package that listens to connectivity status called connectivity_plus, you can subscribe to a stream like so:
import 'package:connectivity_plus/connectivity_plus.dart';
#override
initState() {
super.initState();
subscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
// Got a new connectivity status!
})
}
// Be sure to cancel subscription after you are done
#override
dispose() {
super.dispose();
subscription.cancel();
}
However in the documentation, it states clearly that connectivity changes are no longer communicated to Android apps in the background starting with Android O. You should always check for connectivity status when your app is resumed. The broadcast is only useful when your application is in the foreground.
You might wanna research that and see if it's possible to do so in the background. Here's a similar question which might help you out

How can i access cross-platform(android/iOS) bluetooth detection for flutter?

Newbie here. I am trying to make a hybrid mobile app in flutter that will detect nearby Bluetooth devices based on some unique ID. I want to read that unique ID from the endpoint and compare it onto the DBMS. I want this for both android as well as iOS.
For reference following code is from nearby_connections plugin but is only for android. https://pub.dev/packages/nearby_connections
bool a = await Nearby().startDiscovery(loggedInUser.email, strategy,
onEndpointFound: (id, name, serviceId) async {
print('I saw id:$id with name:$name');
This flutter package seems compatible with Android and iOS, mayb you can try it : https://pub.dev/packages/flutter_nearby_connections

Open video call flutter

Is there a solution yet for opening the video call function on the native phone in flutter? I have looked at Agora and others and none of them work the way we need them to.
That was rather annoying to research and come up with, here it goes. This is the best I can come up with while keeping high complexity and paid SDK's outside the solution.
First of all, you have to differentiate between the two platforms (iOS/Android) before initiating the video call. Since there's no uniform solution for both platforms AFAIK.
import 'dart:io';
if (Platform.isAndroid) {
// Android Video Call
} else if (Platform.isIOS) {
// iOS Video Call
}
iOS
Install the infamous url_launcher pub.
You'll need to use FaceTime Links (see full iOS URL Scheme Reference here or here)
Text example: facetime:14085551234 this initiates FaceTime video call to 14085551234 (you use email instead of phone number too)
import 'package:url_launcher/url_launcher.dart';
final String url = 'facetime:$phoneNumber';
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
This works surprisingly well. In this case you can replace $phoneNumber variable with something like $userEmail variable.
Android
Install android_intent pub
Add CALL_PHONE permission and show its prompt to user if you're using android.intent.action.CALL, or just use android.intent.action.DIAL without the permission.
This is where the problem lies... I tried the following solution and it only worked for regular calls not video calls
import 'package:android_intent/android_intent.dart';
/// This acton calls the user directly via native phone app but requires `CALL_PHONE` permission in _AndroidManifest_.
final callIntentAction = 'android.intent.action.CALL';
/// This action displays native phone app with dial pad open showing the passed phone number intent's argument/extra. Does not require permissions as of Jan2020.
final dialIntentAction = 'android.intent.action.DIAL';
final intentAction = callIntentAction;
AndroidIntent intent = AndroidIntent(
action: intentAction,
data: Uri.encodeFull('tel:$phoneNumber'),
arguments: {
/// KEY: actual phone number to call [source](https://developer.android.com/reference/android/content/Intent.html#EXTRA_PHONE_NUMBER)
/// VALUE: phoneNumber
'android.intent.extra.PHONE_NUMBER': phoneNumber,
/// KEY: [START_CALL_WITH_VIDEO_STATE](https://developer.android.com/reference/android/telecom/TelecomManager.html#EXTRA_START_CALL_WITH_VIDEO_STATE)
/// VALUE: `3` implies [STATE_BIDIRECTIONAL](https://developer.android.com/reference/android/telecom/VideoProfile.html#STATE_BIDIRECTIONAL)
'android.telecom.extra.START_CALL_WITH_VIDEO_STATE': '3',
},
);
await intent.launch();
Error-handling side-note: unfortunately with android_intent pub there's no error handling or "canOpen" method like url_launcher.
Your problem still lies with Android as there's no native general-purpose video-call app.
You have a couple of options:
A. You can link with your app a video-calling SDK/capability either third-party or your own. (like flutter_webrtc, agora_flutter_webrtc, SightCall, quickblox). This has the downside that the callee has to be using the same software i.e. your app has to be installed on callee's device. This approach is more future-proof. Note I'm not affiliated with any of the libraries I mentioned.
B. You can make a platform method for Android to go over a defined set of intents and check the package name of known video-calling apps with the extra/arguments they require. You'd have to check the list of intents one by one and see which applies and resolves correctly. For apps like Google Duo, Whatsapp, Skype, etc.... This is EXTREMELY prone to errors. As explained here.