stops getting Geolocation after a while in MAUI (android ) - maui

I have a foreground service that gets the device's location every 5 seconds and sends it to a server, but after a while, the foreground service stops getting the geolocation data.
public async Task RunLocation(CancellationToken token)
{
await Task.Run(async () =>
{
if (token.IsCancellationRequested)
_stopping = true;
while (!_stopping)
{
token.ThrowIfCancellationRequested();
try
{
await Task.Delay(5000, token);
var request = new GeolocationRequest(GeolocationAccuracy.Best, TimeSpan.FromSeconds(5));
var location = await Geolocation.Default.GetLocationAsync(request, token);
Console.WriteLine("Got location: " + location);
}}}}

Related

How to access android Accessibility Service events from background service?

I am trying to access Accessibility from my background service app which uses flutter_background_service plugin. But I can't listen to the Accessibility events. I am also receiving an error:
Tried to send a platform message to Flutter, but FlutterJNI was detached from native C++. Could not send. Channel: x-slayer/accessibility_event. Response ID: 34
But when the app is open(in recent app) the service is working fine. How do I fix it?
Here is my code. I am trying to fix this for a day, but cant find a way out:
Future<void> initializeService() async {
final service = FlutterBackgroundService();
await service.configure(
androidConfiguration: AndroidConfiguration(
// this will be executed when app is in foreground or background in separated isolate
onStart: onStart,
// auto start service
autoStart: true,
isForegroundMode: true,
),
iosConfiguration: IosConfiguration(
// auto start service
autoStart: true,
// this will be executed when app is in foreground in separated isolate
onForeground: onStart,
// you have to enable background fetch capability on xcode project
onBackground: onIosBackground,
),
);
service.startService();
}
bool onIosBackground(ServiceInstance service) {
WidgetsFlutterBinding.ensureInitialized();
print('FLUTTER BACKGROUND FETCH');
return true;
}
void onStart(ServiceInstance service) async {
// Only available for flutter 3.0.0 and later
DartPluginRegistrant.ensureInitialized();
// For flutter prior to version 3.0.0
// We have to register the plugin manually
if (service is AndroidServiceInstance) {
service.on('setAsForeground').listen((event) {
service.setAsForegroundService();
});
service.on('setAsBackground').listen((event) {
service.setAsBackgroundService();
});
}
service.on('stopService').listen((event) {
service.stopSelf();
});
// bring to foreground
Timer.periodic(const Duration(seconds: 1), (timer) async {
if (service is AndroidServiceInstance) {
service.setForegroundNotificationInfo(
title: "My App Service",
content: "Updated at ${DateTime.now()}",
);
}
/// you can see this log in logcat
print('FLUTTER BACKGROUND SERVICE: ${DateTime.now()}');
void PeaceBox() {
StreamSubscription<AccessibilityEvent>? _subscription;
List<AccessibilityEvent?> events = [];
overlayRequest();
print("Started listening");
// FlutterOverlayWindow.overlayListener.listen((event) {
// print("$event");
// });
String text = "";
// print(text.split(" "));
FlutterAccessibilityService.accessStream.listen((event) {
});
}
PeaceBox();
// test using external plugin
final deviceInfo = DeviceInfoPlugin();
String? device;
if (Platform.isAndroid) {
final androidInfo = await deviceInfo.androidInfo;
device = androidInfo.model;
}
if (Platform.isIOS) {
final iosInfo = await deviceInfo.iosInfo;
device = iosInfo.model;
}
service.invoke(
'update',
{
"current_date": DateTime.now().toIso8601String(),
"device": device,
},
);
});
}

Out of memory, flutter stream

the below stream method is triggered every frame
stream() async {
_isStreaming=true;
var counter=0;
channel = WebSocketChannel.connect(
Uri.parse('ws://192.168.11.8:8000/real-time/')
) as IOWebSocketChannel?;
_cameraController?.startImageStream((CameraImage img) async{
final imageBytes= await convertYUV420toImageColor(img);
if(_isStreaming) {
channel?.sink.add(imageBytes);
}
});
channel?.stream.listen((message) {
print(message);
var jsonDecodex = jsonDecode(message);
var prediction = jsonDecodex['prediction'];
var predictProba = jsonDecodex['predict_proba'];
_prediction = prediction;
_accuracy =predictProba+"%";
if(mounted) {
setState(() {});
}
},
);}
I'm working on a flutter app that opens a stream and sends every frame to a Django server via WebSockets, However, nearly after 1 minute of streaming 'out of memory' error happens.

Flutter await for another method complete

I want to check if new update is available for my application or not. if update is available redirect user to UpdateScreen and if update is not available get the user info and redirect to HomeScreen
_check() async {
await _checkForUpdate();
await _getUserData(token);
}
_checkForUpdate() async {
print('check for update');
var url = Uri.parse(Endpoints.mainData);
var response = await http.get(url);
var jsonResponse = convert.jsonDecode(response.body);
var data = jsonResponse['data'];
int lastVersionCode = data['lastVersionCode'];
if(lastVersionCode > Data.versionCode){
redirectToScreen(context, UpdateScreen());
}
}
_getUserData(String token) async {
print('get user data');
var url = Uri.parse(Endpoints.accountInfo + '/?token=' + token);
var response = await http.get(url);
var jsonResponse = convert.jsonDecode(response.body);
var data = jsonResponse['data'];
//setup user data in my app
redirectToScreen(context, HomeScreen());
When I run my application two methods( _checkForUpdate, _getUserData) get fired and in output I the get following message that i printed:
check for update
get user data
and i see Update screen for 1 second and then user is redirect to HomeScreen.
i want to skip running the other codes after _checkForUpdate redirect user to UpdateScreen
return a bool whether there is an update available and use it to skip other methods:
_check() async {
bool needsUpdate = await _checkForUpdate();
if (!needsUpdate)
await _getUserData(token);
}
Future<bool> _checkForUpdate() async {
print('check for update');
var url = Uri.parse(Endpoints.mainData);
var response = await http.get(url);
var jsonResponse = convert.jsonDecode(response.body);
var data = jsonResponse['data'];
int lastVersionCode = data['lastVersionCode'];
if (lastVersionCode > Data.versionCode) {
redirectToScreen(context, UpdateScreen());
return true;
}
return false;
}

how to handle a loop in flutter? need can be canceled?

I want to use flutter fulfilled a mqtt client. the client need send message to serve for loop.
I used "while" keyword for loop. but the flutter UI is pending during the while function.
if use isolate to work it, sending the cancel flag failed.
Does there anybody have the experience on it?
----------code------
onpressed -----> Future Function ----> use while loop---->the app pending cannot press anywhere---> the loop stop, the app recovery
I want start a mqtt client to send mqtt message for loop.
but when pressed the function, the while loop pended the app.
Expected results: the loop works in an async work, and the app can work rightly.
Actual results: the app is pending.
###UI
children: [
SizedBox(width: 200),
MaterialButton(
child: Text('发送'),
onPressed: () {
BtnsendMsg();
},
####onpressed function
mc = new MqttClient(false);
BtnsendMsg() async {
mc.MsgSend(clientid, topic, msgname, '3');
print("back");
}
####loop function
class MqttClient {
bool isStop;
MqttClient(this.isStop);
Future MsgSend(clientid, topic, msgname, interval) async {
isStop = false;
var cc = await clientGet(clientid);
var msg = await msgGet(msgname);
String host = "1.1.1.1";
String msgdata = "1111";
if (cc != null) {
host = cc.host!;
}
if (msg != null) {
msgdata = msg.msgdata!;
}
Future future = Future(() {
while (isStop == false) {
SendMsgOnce(host, clientid, topic, msgdata);
sleep(Duration(seconds: 3));
}
});
sleep(Duration(seconds: 30));
isStop = true;
}
This is because you are putting load on main thread by not using async and await while sending request to the server. Do the following changes to your code then it should get work.
class MqttClient {
bool isStop;
MqttClient(this.isStop);
Future MsgSend(clientid, topic, msgname, interval) async {
isStop = false;
var cc = await clientGet(clientid);
var msg = await msgGet(msgname);
String host = "1.1.1.1";
String msgdata = "1111";
if (cc != null) {
host = cc.host!;
}
if (msg != null) {
msgdata = msg.msgdata!;
}
Future future = Future(() async {
while (isStop == false) {
await SendMsgOnce(host, clientid, topic, msgdata);
sleep(Duration(seconds: 3));
}
});
sleep(Duration(seconds: 30));
isStop = true;
}
In your on pressed function you are using async but now awaiting for that
mc = new MqttClient(false);
BtnsendMsg() async {
await mc.MsgSend(clientid, topic, msgname, '3');
print("back");
}

Unable to get the Onesignal userid when the user install the app first time in Flutter

I want to store the onesignal User Id in the database when the user install my app first time. I wrote the following code which is not allowing me to do so.
However when the user Logged out from the app and re-login then I am able to retrieve the onesignal user ID and able to save in the Database.
Future<void> initPlatformState(username) async {
if (!mounted) return;
OneSignal.shared.setLogLevel(OSLogLevel.verbose, OSLogLevel.none);
OneSignal.shared.setRequiresUserPrivacyConsent(_requireConsent);
var settings = {
OSiOSSettings.autoPrompt: false,
OSiOSSettings.promptBeforeOpeningPushUrl: true
};
OneSignal.shared
.setSubscriptionObserver((OSSubscriptionStateChanges changes) {
print("SUBSCRIPTION STATE CHANGED: ${changes.jsonRepresentation()}");
});
OneSignal.shared.setPermissionObserver((OSPermissionStateChanges changes) {
print("PERMISSION STATE CHANGED: ${changes.jsonRepresentation()}");
});
OneSignal.shared.setEmailSubscriptionObserver(
(OSEmailSubscriptionStateChanges changes) {
print("EMAIL SUBSCRIPTION STATE CHANGED ${changes.jsonRepresentation()}");
});
await OneSignal.shared
.init("MY Onesignal APP ID", iOSSettings: settings);
OneSignal.shared
.setInFocusDisplayType(OSNotificationDisplayType.notification);
var status = await OneSignal.shared.getPermissionSubscriptionState();
onesignalUserId = status.subscriptionStatus.userId;
print("player ID: "+ onesignalUserId.toString()); // printing only in re-login
_saveOneSignalId(onesignalUserId,username); // my save funtion into the DB
}
You can call the below function inside your main.dart file when initialising the One Signal to get playerId/userId. The below function is called when user opend the app for first time or when the userId (playerId) changes.
OneSignal.shared.setSubscriptionObserver((OSSubscriptionStateChanges changes) async {
String onesignalUserId = changes.to.userId;
print('Player ID: ' + onesignalUserId);
}
The playerId/userId can be used to send test notification or notifications to particular user.
Please try this.
OneSignal.shared.setSubscriptionObserver((OSSubscriptionStateChanges changes)
async{
var status = await OneSignal.shared.getPermissionSubscriptionState();
if (status.subscriptionStatus.subscribed){
String onesignalUserId = status.subscriptionStatus.userId;
print('Player ID: ' + onesignalUserId);
}