1

i'm building an app that records location and accelerometer data, and exports that data into a csv file.

The problem:

when I'm deploying to android everything working fine.
I have a running clock as you can see at the build widget: time:DateTime.now().toString()),.
And the location updates and displays speed information:speed: (_speed?.round() ?? 0), .

But when I'm deploying to ios, the state of the widget doesn't update at all.
the clock is stuck, and location service doesn't update.
and if I leave the specific page to the homepage and open it again, the clock updates to the current time, but stays stuck.
its seems that for some reason the state of the app doest update in iOS, and I cant figure out
why.

I added the following lines to the info.plist:

    <key>NSMotionUsageDescription</key>
    <string>banana</string>
    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>banana</string>
    <key>NSLocationAlwaysUsageDescription</key>
    <string>banana</string>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>banana</string>

The code:

import 'package:flutter/material.dart';
import 'package:different/widgets/StatGridDrive.dart';
import 'package:location/location.dart';
import 'dart:async';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:sensors/sensors.dart';

class DataStorage {
  Future<String> get _localPath async {
    final directory = await getApplicationDocumentsDirectory();
    return directory.path;
  }

  Future<File> get _localFile async {
    final path = await _localPath;
    return File('$path/locationData.csv');
  }

  Future<File> writeData(String data) async {
    final file = await _localFile;

    // Write the file
    return file.writeAsString(data, mode: FileMode.append);
  }
}

class DriveScreen extends StatefulWidget {
  final DataStorage data;
  DriveScreen({Key key, @required this.data}) : super(key: key);

  @override
  _DriveScreenState createState() => _DriveScreenState();
}

class _DriveScreenState extends State<DriveScreen> {
  double _speed;
  Timer _timer;
  String _accelerometerValues;
  String _gyroscopeValues;
  List<StreamSubscription<dynamic>> _streamSubscriptions =
      <StreamSubscription<dynamic>>[];

  @override
  void initState() {
    super.initState();
    _streamSubscriptions
        .add(accelerometerEvents.listen((AccelerometerEvent event) {
      setState(() {
        _accelerometerValues = event.x.toString() +
            "," +
            event.y.toString() +
            "," +
            event.z.toString();
      });
    }));
    _streamSubscriptions.add(gyroscopeEvents.listen((GyroscopeEvent event) {
      setState(() {
        _gyroscopeValues = event.x.toString() +
            "," +
            event.y.toString() +
            "," +
            event.z.toString();
      });
    }));
  }

  //location data
  final Location location = Location();

  LocationData _location;
  StreamSubscription<LocationData> _locationSubscription;
  String _error;

  Future<void> _listenLocation() async {
    _locationSubscription =
        location.onLocationChanged.handleError((dynamic err) {
      setState(() {
        _error = err.code;
      });
      _locationSubscription.cancel();
    }).listen((LocationData currentLocation) {
      setState(() {
        _error = null;
        _location = currentLocation;
        _speed = _location.speed;
      });
    });
  }

  Future<void> _stopListen() async {
    _locationSubscription.cancel();
  }

  Future<void> newData() async {
    // Write the variable as a string to the file.
    if (_location != null) {
      widget.data.writeData(
          '${_location.longitude.toString() + "," + _location.latitude.toString() + "," + _accelerometerValues + "," + _gyroscopeValues.toString()} \n');
    }
  }

  @override
  void dispose() {
    super.dispose();
    for (StreamSubscription<dynamic> subscription in _streamSubscriptions) {
      subscription.cancel();
      _locationSubscription.cancel();
      _timer.cancel();
    }
  }

  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      appBar: AppBar(
          leading: GestureDetector(
            onTap: () {
              _stopListen();
              Navigator.pop(context);
            },
            child: Icon(
              Icons.baby_changing_station,
            ),
          ),
          title: Text('LyftOff'),
          backgroundColor: Color(0xFF282828)),
      backgroundColor: Color(0xFF333333),
      body: SizedBox(
        height: 325,
        child: StatsGrid(
            distance: 15,
            speed: (_speed?.round() ?? 0),
            time: DateTime.now().toString()),
      ),
      floatingActionButton: SizedBox(
        height: 60.0,
        width: 185.0,
        child: FloatingActionButton.extended(
          onPressed: () {
            _listenLocation();
            _timer = new Timer.periodic(
                Duration(milliseconds: 100), (Timer t) => newData());
          },
          backgroundColor: Colors.green,
          label: Text(
            'התחל נסיעה',
            style: TextStyle(
              fontSize: 20.0,
            ),
          ),
          icon: Icon(
            Icons.car_rental,
            size: 30.0,
          ),
          splashColor: Colors.greenAccent,
        ),
      ),
    ));
  }
}

Any pointers to what I'm doing wrong?

amitt1236
  • 29
  • 5

1 Answers1

0

you are using setstate() inside initstate() check out this for more :

[https://stackoverflow.com/questions/53363774/importance-of-calling-setstate-inside-initstate][1]

  • weird, that's how it was written on the flutter docs. even though I tried to erase all of the accelerometer request from the initstate(), and it didn't help. still the page state is'nt updating. – amitt1236 Mar 06 '21 at 11:28