Skip to main content

Flutter Tutorial: Save GPS Data from the Devices

In this article we will cover how to collect the value of the speed of a vehicle through GPS. We will use as a basis for this project the Flutter framework that has been widely used by several developers.

We will cover the following topics:

  • Creating a Standard Project with Flutter
  • Installing and configuring the “geolocator: ^8.2.0” plugin
  • Save the speed data as the device moves.

Step 1. Creating a Standard Project with Flutter

flutter create -i objc -a java my_speed

Step 2. Install & Configure Geolocator Plugin

To save GPS device moves, we will use the “geolocator: ^8.2.0” flutter plugin available in the official package repository for Dart and Flutter applications.

The “geolocator: ^8.2.0” is a simple yet powerful tool to collect this data. To use this plugin, we need to install and configure some settings.

To simplify what was done in this project, I will bring here all the configurations made in a simpler way.

flutter pub add geolocator:8.1.1

or by editing your pubspec.yaml file:

dependencies: 

    geolocator: ^8.2.0

Import the plugin to your main.dart file:

import 'package:geolocator/geolocator.dart';

3. Save the speed data as the device moves

add new permission to plaform specific manifest, like Android or iOS. For android, edit the android/app/src/main/AndroidManifest.xml files. Add this permission:







also the gradle properties:

android.useAndroidX=true
android.enableJetifier=true

for iOS platform, edit ios/Runner/Info.plist files and add:

NSLocationWhenInUseUsageDescription
This app needs access to location when open.
NSLocationAlwaysUsageDescription
This app needs access to location when in the background.
NSLocationTemporaryUsageDescriptionDictionary

NSLocationTemporaryUsageDescriptionDictionary

YourPurposeKey
The example App requires temporary access to the device's precise location.

In your main.dart files, add geolocator variables:

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
  double? latitude = 0.0;
  double? longitude = 0.0;
  double? altitude = 0.0;
  double? speed = 0.0;
  DateTime? timestamp = DateTime.now();
 
  //Resto do codigo

}

Create the run Permission() method in the My HomePage class, this class will be responsible for checking if the application has permission to use the device's GPS.

 runPermission() async {
    LocationPermission permission;
    permission = await Geolocator.checkPermission();
    if (permission == LocationPermission.denied ||
        permission == LocationPermission.whileInUse) {
      permission = await Geolocator.requestPermission();
      if (permission == LocationPermission.deniedForever) {
        _showDialog();
      }
    }
  }

At first it checks if it has the permission with the parameter ”Geolocator.checkPermission()” if it doesn't have it, or if it only allowed it while the “application is in use” it will make a request through the parameter “Geolocator.requestPermission()”.

In order for the application to respond appropriately to the user if he does not give permission, create a _showDialog(), this method will execute a pop-up on the user's screen informing him that permission has been denied.

  void _showDialog() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: const Text("Permissao para Acessar local"),
          content: const Text(
              "Deve escolher opção de permição: 'Permitir o tempo todo'"),
          actions: [
            TextButton(
              child: Text("OK"),
              onPressed: () async {
                Navigator.of(context).pop;
              },
            ),
          ],
        );
      },
    );
  }

Continued in the MyHomePage class create the runLocation() method. This method will be responsible for implementing the code that will verify the location as the vehicle moves. In this method, by calling getPositionStream(), it is possible to “listen” to the location changes.

Set the accuracy and distanceFilter according to the code below.

 runLocation() async {
    // ignore: prefer_const_constructors
    final LocationSettings locationSettings = LocationSettings(
      accuracy: LocationAccuracy.high,
      distanceFilter: 10,
    );
    StreamSubscription positionStream =
        Geolocator.getPositionStream(locationSettings: locationSettings)
            .listen((Position? position) {
      setState(() {
        latitude = position?.latitude;
        longitude = position?.longitude;
        altitude = position?.altitude;
        speed = position?.speed;
        timestamp = position?.timestamp;
      });

      print(position == null
          ? 'Unknown'
          : '${position.latitude.toString()}, ${position.longitude.toString()}');
    });
  }
  

Use the setState() method and insert the variables for the data to be collected. setState() is used to update the values of your View in real time.

The runLocation() has to be asynchronous and as the device moves, this method will be executed and automatically update the values of the latitude, longitude, altitude, speed and timestamp variables.

A good place to insert external API communication for data synchronization is inside the getPositionStream() method. Since this method will always be executed as the device moves.

Use the standard flutter method initState() to call the two created methods runPermission() and runLocation().

   @override
 void initState() {
   runPermission();
   runLocation();
 }

All the methods we need to get the GPS parameters were created, to make the application look more pleasant, we can edit the Widget from within the MyHomePage class and take advantage of it and pass our variables

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 0,
        toolbarHeight: 150,
        backgroundColor: Color.fromARGB(255, 230, 229, 229),
        centerTitle: true,
        title: GradientText(
          'My Speed',
          style: const TextStyle(fontSize: 40),
          gradient: LinearGradient(colors: [
            Colors.blue.shade400,
            Color.fromARGB(255, 144, 13, 161),
          ]),
        ),
      ),
      body: Center(
          child: Container(
              child: Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: ListView(children: [
                    //Latitude Card
                    Card(
                      clipBehavior: Clip.antiAlias,
                      child: Column(
                        children: [
                          ListTile(
                            leading: const RotatedBox(
                              quarterTurns: 1,
                              child: Icon(Icons.height_rounded),
                            ),
                            title: const Text('Latitude'),
                            subtitle: Text(
                              '$latitude',
                              style: TextStyle(
                                  color: Colors.black.withOpacity(0.6)),
                            ),
                          ),
                        ],
                      ),
                    ),
                    //Longitude Card
                    Card(
                      clipBehavior: Clip.antiAlias,
                      child: Column(
                        children: [
                          ListTile(
                            leading: const Icon(Icons.height_rounded),
                            title: const Text('Longitude'),
                            subtitle: Text(
                              '$longitude',
                              style: TextStyle(
                                  color: Colors.black.withOpacity(0.6)),
                            ),
                          ),
                        ],
                      ),
                    ),
                    //Altitude Card
                    Card(
                      clipBehavior: Clip.antiAlias,
                      child: Column(
                        children: [
                          ListTile(
                            leading: const Icon(Icons.terrain),
                            title: const Text('Altitude'),
                            subtitle: Text(
                              '$altitude',
                              style: TextStyle(
                                  color: Colors.black.withOpacity(0.6)),
                            ),
                          ),
                        ],
                      ),
                    ),
                    //speed Card
                    Card(
                      clipBehavior: Clip.antiAlias,
                      child: Column(
                        children: [
                          ListTile(
                            leading: const Icon(Icons.speed),
                            title: const Text('Velocidade'),
                            subtitle: Text(
                              "${(speed! * 3.6)} km/h",
                              style: TextStyle(
                                  color: Colors.black.withOpacity(0.6)),
                            ),
                          ),
                        ],
                      ),
                    ),
                    //Date Time Card
                    Card(
                      clipBehavior: Clip.antiAlias,
                      child: Column(
                        children: [
                          ListTile(
                            leading: const Icon(Icons.access_time),
                            title: const Text('Data & Hora'),
                            subtitle: Text(
                              '$timestamp',
                              style: TextStyle(
                                  color: Colors.black.withOpacity(0.6)),
                            ),
                          ),
                        ],
                      ),
                    ),
                  ])))),
      
    );
  }
}

Create cards for each GPS variable that will allow you to see each one independently. The GradientText that shows in the Title of the AppBar is another class made inside the main.dart file

  class GradientText extends StatelessWidget {
  const GradientText(
    this.text, {
    required this.gradient,
    this.style,
  });

  final String text;
  final TextStyle? style;
  final Gradient gradient;

  @override
  Widget build(BuildContext context) {
    return ShaderMask(
      blendMode: BlendMode.srcIn,
      shaderCallback: (bounds) => gradient.createShader(
        Rect.fromLTWH(0, 0, bounds.width, bounds.height),
      ),
      child: Text(text, style: style),
    );
  }
}

After completing all these steps in the application, it is now possible to capture GPS data as the device is moved.

Comments

Popular posts from this blog

Cara Disable Antimalware Service Executable di Windows 10

Disadari atau tidak, Windows 10 (dan juga windows-windows lainnya) hadir dengan banyak sekali aplikasi bloatware (aplikasi yang tidak perlu-perlu amat dimiliki oleh end user). Contohnya, adalah aplikasi yang seharusnya sudah tergantikan fungsinya oleh antivirus, seperti Antimalware Service Executable . Aplikasi ini dicurigai membuat Windows 10 mengalami inefisiensi memori/RAM, memakan resource yang tinggi, dengan Load yang tinggi (tanpa limit terkadang). Nah, berikut adalah cara men-disable nya: Tekan tombol Windows + I untuk membuka apliaksi Windows Setting. Pilih icon menu Update and Security Pilih lagi menu disamping kiri Windows Security Pada jendela baru yang muncul, ada pilihan Virus & Threat protection Klik ini Lalu matikan proses Real-time protection tersebut. Dengan Regedit. Buka dialog regedit, Windows + R dan ketik ‘regedit’ Cari Folder regedit ini HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender Buat sebuah DWORD baru dengan klik kanan

Setup Debian 11 Official Repository In sources.list (/etc/apt/sources.list)

When you install Debian 11 using a DVD, the OS installer sets the DVD as the source for getting packages for your system if you didn't choose to scan for network mirrors. Due to this reason, the system would ask you to insert a DVD if the disc is not present in the DVD drive when you try to install any software.  Also, the packages on DVD may not be the latest release.  So, we need to get the packages from the Internet. Media change: please insert the disc labeled 'Debian GNU/Linux 11.0.0 _Bullseye_ - Official amd64 DVD Binary-1 20210814-10:04' in the drive '/media/cdrom/' and press [Enter] The /etc/apt/sources.list file with DVD as a source would look something like below. # deb cdrom:[Debian GNU/Linux 11.0.0 _Bullseye_ - Official amd64 DVD Binary-1 20210814-10:04]/ bullseye contrib main deb cdrom:[Debian GNU/Linux 11.0.0 _Bullseye_ - Official amd64 DVD Binary-1 20210814-10:04]/ bullseye contrib main deb http://security.debian.org/debian-security bullseye-security

How to Install Traefik in Debian (Without Docker)

 Download the suitable version of Traefik for your system from here: https://github.com/traefik/traefik/releases as an example, we'll be download the linux 64 bit version: wget https://github.com/traefik/traefik/releases/download/v2.8.7/traefik_v2.8.7_linux_amd64.tar.gz extract those package: tar -xzvf traefik_v2.8.7_linux_amd64.tar.gz set the traefik as executable and move the traefik binary to linux bin folder