I have to increase the call time of setLocation() because I spend so much on google APIs (in 2 days 100€ and I am only testing the app). I have tried timers and debounce functions but have not yet been able to come up with a solution.
updateDriversLocationAtRealTime()
{
streamSubscriptionPosition = Geolocator.getPositionStream()
.listen((Position position)
{
driverCurrentPosition = position;
if(isDriverActive == true)
{
Geofire.setLocation(
currentFirebaseUser!.uid,
driverCurrentPosition!.latitude,
driverCurrentPosition!.longitude
);
}
LatLng latLng = LatLng(
driverCurrentPosition!.latitude,
driverCurrentPosition!.longitude,
);
newGoogleMapController!.animateCamera(CameraUpdate.newLatLng(latLng));
});
}
Related
I'm using the explore Edition of here SDK to to truck location updates. I want that the map rotate and the indicator to move with my physical location changes. Unfortunately the indication is always in my current location.
This is my code :
CameraExample(HereMapController hereMapController)
: _hereMapController = hereMapController {
_initializeMap();
}
Future<void> _initializeMap() async {
// Get current position
final position = await Geolocator.getCurrentPosition();
GeoCoordinates currentLocation =
GeoCoordinates(position.latitude, position.longitude);
// Look at current position with tilt and bearing
var bearingInDegrees = 0.0;
var tiltInDegrees = 45.0;
var orientation = GeoOrientationUpdate(bearingInDegrees, tiltInDegrees);
var distanceToEarthInMeters = 1000 * 10.0; // Set to 10 kilometers.
MapMeasure mapMeasureZoom =
MapMeasure(MapMeasureKind.distance, distanceToEarthInMeters);
_hereMapController.camera
.lookAtPointWithMeasure(currentLocation, mapMeasureZoom);
_hereMapController.camera.lookAtPointWithGeoOrientationAndMeasure(
currentLocation, orientation, mapMeasureZoom);
// Add location indicator
_addLocationIndicator(
currentLocation, LocationIndicatorIndicatorStyle.navigation);
GeoCoordinates targetLocation = GeoCoordinates(
currentLocation.latitude + 0.1, currentLocation.longitude + 0.1);
GeoCoordinatesUpdate geoCoordinatesUpdate =
GeoCoordinatesUpdate.fromGeoCoordinates(targetLocation);
double bowFactor = 1.0;
MapCameraAnimation animation = MapCameraAnimationFactory.flyTo(
geoCoordinatesUpdate, bowFactor, const Duration(seconds: 3));
_hereMapController.camera.startAnimation(animation);
}
void _addLocationIndicator(GeoCoordinates geoCoordinates,
LocationIndicatorIndicatorStyle indicatorStyle) {
LocationIndicator locationIndicator = LocationIndicator();
locationIndicator.locationIndicatorStyle = indicatorStyle;
// For testing purposes, we create a Location object. Usually, you may want to get this from
// a GPS sensor instead.
Location location = Location.withCoordinates(geoCoordinates);
location.time = DateTime.now();
location.bearingInDegrees = 0.0;
locationIndicator.updateLocation(location);
.
_hereMapController.addLifecycleListener(locationIndicator);
}
}
I'm using Flutter and location package for measuring speed periodically in my iOS real device(iPhoneXS - maybe iOS 13) in debug mode and also running indoors.
This is my code.
class _TimerScreenState extends State<TimerScreen> {
Timer? timer;
int restMilliSec = 0;
int setCnt = 0;
#override
void initState() {
super.initState();
bool canVibrate;
restMilliSec = decideTimerTime(currentType) * 1000;
timer = Timer.periodic(Duration(milliseconds: 1), (timer) async {
// ... other code for another logic... //
if (canVibrate) Vibrate.vibrate();
setLocation();
}
});
}
void setLocation() async {
Location location = Location();
LocationData _currentPosition = await location.getLocation();
print("accuracy : ${_currentPosition.accuracy}, speed: ${_currentPosition.speed}");
print("Speed Accuracy : ${_currentPosition.speedAccuracy}");
}
}
I don't know what's the meaning of -1.
How can I get positive number for speed?
Other values are printed well.
The documentation for CoreLocation on iOS (upon which the Flutter location package is built) specifies the meaning of -1 for speed:
A negative value indicates an invalid speed.
and speedAccuracy:
When this property contains a negative number, the value in the speed property is invalid.
Thus, as you've deduced, negative values indicate an invalid or unavailable speed. Why your speed as coming back as invalid is difficult to say without more information.
I'm try to create a function to stop player control, but when I pass the duration as a parameter in the function, the variable keeps ina huge number never really decreasing.
public void StopAllPlayerControl(float duration) {
stopPlayerDuration = duration;
stopPlayerDuration -= Time.deltaTime;
//stop here what you need.
playerInput.enableMovement = false;
if (stopPlayerDuration <= 0) {
//restore here to normal state
playerInput.enableMovement = true;
}
}
And Im calling this funct in a Update method like this
StopAllPlayerControl(3);
Image here to show that stopPlayerDuration getsm huge but stays in those big numbers never really decreasing. huge number
I used a combination of both answers, organized my logic better and, in this case, I used a coroutine.
This function starts the coroutine and I can call it and control it with a bool
public void startStopPlayerCo(float dur) {
//function to start stop player courutine from anywhere.
StartCoroutine(StopPlayerCo(dur));
}
This is the coroutine that works well now
public IEnumerator StopPlayerCo(float dur) {
while (startCO) {
GetComponent<PlayerMove>().enabled = false;
yield return new WaitForSeconds(dur);
//reset
GetComponent<PlayerMove>().enabled = true;
startCO = false;
}
}
And I call it in Update Method like this:
startStopPlayerCo(2) //2 seconds, or any var for desired time
Try this:
float startTime = 0;
float duration = 0;
public void StopAllPlayerControl(float duration)
{
this.duration = duration;
if(playerInput.enableMovement)
{
startTime = Time.time;
playerInput.enableMovement = false;
}
if(Time.time - startTime >= this.duration)
{
playerInput.enableMovement = true;
}
}
Explaination
Step 1
Firstly, we need to check if movement is already enabled. If it is, we mark the point that we started the timer, and disable movement. We also store our duration in a variable, and reference it locally with the `this` keyword.
if(playerInput.enableMovement)
{
startTime = Time.time;
playerInput.enableMovement = false;
}
Step 2
If the timer exceeds the duration then movement is enabled.
if(Time.time - startTime < duration)
{
playerInput.enableMovement = true;
}
It is also good practice to enclose this method in a boolean lock to prevent it from being called again while the timer is running, unless you want such a feature to be allowed.
I would like to know if there is something like a framework for an execution limit per minute.
Let's say I have an API where I can request 100 times per minute.
If I send a "hello world" in a loop, I would exceed that limit.
For example, something like this:
ExecutionLimiter executer = ExecutionLimiter(executions: 100, duration: Duration(minutes: 1));
while (true) {
executer.add(() => print(“hello world“));
}
I've found the package queue, but this is only for parallelization.
Thanks for your help.
You can use Timer.periodic to activate a method every given time.
_timer = Timer.periodic(Duration(milliseconds: 600), (Timer t) {
// Send single api request every 600 ms
});
// Stop sending requests
Future.delayed(const Duration(minutes: 1), () {
_timer.cancel();
});
Just don't forget to save it in variable and dispose it when you finish using it.
Thanks to the support of Yair Chen, I have created a short example program that executes the function n-times in the given time span. The duration of the execution is taken into account.
import 'dart:async';
import 'dart:math';
List<Instance> instances = [];
int executionLimit = 10;
int apiCallLimitInSeconds = 5;
// for test purposes
int elapsedTime = 0;
int executedFunctions = 0;
main() {
Timer.periodic(Duration(seconds: 1), (Timer t) {
instances.removeWhere((element) => element.isInvalid);
for (int i = 0; instances.length < executionLimit; i++) {
instances.add(Instance(
Future.delayed(Duration(milliseconds: Random().nextInt(100)))
.then((value) => executedFunctions++)));
}
//tests again
elapsedTime++;
if (elapsedTime % 5 == 0) {
print(executedFunctions);
}
});
}
class Instance {
Future<void> execute;
bool isInvalid = false;
Instance(this.execute) {
execute.then((value) => Timer(
Duration(seconds: apiCallLimitInSeconds), () => isInvalid = true));
}
}
I am building an application with swipeable cards in a deck.
Swiping works perfectly fine at any speed so long as I am swiping sort of at least 50% of the distance of the screen.
People don't tend to do this however, it is a better user experience to just swipe a very short distance quickly left or right and have the application detect the intent and complete the scroll action.
My code is as follows:
void _onHorizontalDragStart(DragStartDetails details) {
startDrag = details.globalPosition;
startDragPercentScroll = scrollPercent;
}
void _onHorizontalDragUpdate(DragUpdateDetails details) {
final currentDrag = details.globalPosition;
final dragDistance = currentDrag.dx - startDrag.dx;
final singleCardDragPercent = dragDistance / context.size.width;
setState(() {
scrollPercent = (startDragPercentScroll + (-singleCardDragPercent / widget.cards.length)).clamp(0.0, 1.0 - (1 / widget.cards.length));
});
}
void _onHorizontalDragEnd(DragEndDetails details) {
finishScrollStart = scrollPercent;
finishScrollEnd = (scrollPercent * widget.cards.length).round() / widget.cards.length;
finishScrollController.forward(from: 0.0);
setState(() {
startDrag = null;
startDragPercentScroll = null;
});
}
I am certain there is just something wrong with my math there somewhere that is preventing short, quick swipes from working.
What happens instead is the card moves a short distance and then snaps back to the same card.