Monday 9 March 2020

expo gps 1

app opens, click update location

gps is turned on and updates every second

press stop update, press copy button beside gps info to copy location to clipboard

press search address

press Realtime GPS to collapse it, press open map

google map is the default map app, our location is at center

open offline gps app, paste copied location

offline gps finds our location
//app.js

import React, { useState, useEffect } from 'react';
import { Clipboard } from 'react-native';
import {
  Container, Header, Title, Content, Footer,
  FooterTab, Button, Left, Right, Body, Icon, Text,
  Accordion, Card, CardItem, Thumbnail, ListItem,
  CheckBox, DatePicker, DeckSwiper, Fab, View,
  Badge, Form, Item, Input, Label, Picker, Textarea,
  Switch, Radio, Spinner, Tab, Tabs, TabHeading,
  ScrollableTab, H1, H2, H3, Drawer,
} from 'native-base';
import * as Font from 'expo-font'
import * as Location from 'expo-location'
import * as TaskManager from 'expo-task-manager'
import useInterval from 'react-useinterval'
import openMap from 'react-native-open-maps'

const LOCATION_TASK_NAME = 'background-location-task';
let background_location = null

export default function App() {
  const [loadfont, setloadfont] = useState(true)
  const [permission_status, setpermission_status] = useState('undetermined')
  const [acc, setacc] = useState(-1)
  const [altitude, setaltitude] = useState(-1)
  const [heading, setheading] = useState(-1)
  const [latitude, setlatitude] = useState(-1)
  const [longitude, setlonggitude] = useState(-1)
  const [speed, setspeed] = useState(-1)
  const [time, settime] = useState('')
  const [updatePeriod, setupdatePeriod] = useState(null)
  const [address, setaddress] = useState(null)
  const [card_collapse1, setcard_collapse1] = useState(false)
  const [card_collapse2, setcard_collapse2] = useState(false)

  useEffect(() => {
    initializeApp()
    return () => stop_update_location()
  }, [])

  initializeApp = async () => {
    const { status } = await Location.requestPermissionsAsync()
    setpermission_status(status)

    await Font.loadAsync({
      Roboto: require("native-base/Fonts/Roboto.ttf"),
      Roboto_medium: require("native-base/Fonts/Roboto_medium.ttf")
    })
    setloadfont(false)
  }

  useInterval(() => (
    update_location()
  ), updatePeriod);

  update_location = async () => {

    await Location.startLocationUpdatesAsync(LOCATION_TASK_NAME, {
      accuracy: Location.Accuracy.High,
    })

    if (background_location) {
      const e = background_location.coords
      setacc(e.accuracy)
      setaltitude(e.altitude)
      setheading(e.heading)
      setlatitude(e.latitude)
      setlonggitude(e.longitude)
      setspeed(e.speed)
      settime(Date(background_location.timestamp).toString())
    }
  }

  stop_update_location = async () => {
    setupdatePeriod(null)
    const taskRegistered = await TaskManager.isTaskRegisteredAsync(LOCATION_TASK_NAME)
    if (taskRegistered) {
      await TaskManager.unregisterTaskAsync(LOCATION_TASK_NAME)
    }
  }

  search_address = async () => {
    if (background_location) {
      const _address = await Location.reverseGeocodeAsync(background_location.coords)
      setaddress(_address[0])
    }
  }

  open_map = () => {
    if (background_location) {
      const e = background_location.coords
      openMap({ latitude: e.latitude, longitude: e.longitude })
    }
  }

  write_to_clipboard = (text) => {
    Clipboard.setString(text);
  }

  if (permission_status !== 'granted') {
    <Container style={{ backgroundColor: '#1C2833' }}>
      <Text>App needs location permission granted</Text>
    </Container>
  }

  if (loadfont) {
    return <Container style={{ backgroundColor: '#1C2833' }}><Spinner /></Container>
  }

  return (
    <Container style={{ backgroundColor: '#1C2833' }}>
      <Content style={{ marginTop: 25 }}>
        <Card style={{ backgroundColor: '#1C2833' }}>
          <CardItem header bordered button style={{ backgroundColor: "#1C2833" }}
            onPress={() => setcard_collapse1(!card_collapse1)}>
            <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between' }}>
              <H3 style={{ color: '#D0D3D4' }}>Realtime GPS</H3>
              <H3 style={{ color: "#D0D3D4" }}>+</H3>
            </View>
          </CardItem>
          {card_collapse1 ? null :
            <CardItem bordered style={{ backgroundColor: '#1C2833' }}>
              <Text style={{ color: "#D0D3D4", fontStyle: 'italic' }}>
                Accuracy: {acc} Meters{'\n'}
                Altitude: {altitude} Meters{'\n'}
                Heading: {heading} Degree{'\n'}
                Latitude: {latitude} Degree{'\n'}
                Longitude: {longitude} Degree{'\n'}
                Speed: {speed} M/S{'\n'}
                Time: {time}
              </Text>
              <Button light small bordered icon style={{ position: 'absolute', right: 10, top: 10 }}
                onPress={() => { write_to_clipboard(latitude + ',' + longitude) }}>
                <Icon name='copy'></Icon>
              </Button>
            </CardItem>
          }
          <CardItem header bordered button style={{ backgroundColor: '#1C2833' }}
            onPress={() => setcard_collapse2(!card_collapse2)}>
            <View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between' }}>
              <H3 style={{ color: '#D0D3D4' }}>Address (update location first)</H3>
              <H3 style={{ color: '#D0D3D4' }}>+</H3>
            </View>
          </CardItem>
          {card_collapse2 ? null :
            <CardItem style={{ backgroundColor: '#1C2833' }}>
              {address ?
                <Text style={{ color: '#D0D3D4' }}>
                  {address.name}  {address.street} {'\n'}
                  {address.city} {address.region} {address.country}  {address.postalCode}
                </Text>
                : <Text style={{ color: '#D0D3D4' }}>Waiting for GPS location</Text>}
              <Button light small bordered icon style={{ position: 'absolute', right: 10, top: 10 }}
                onPress={() => {
                  write_to_clipboard(address.name + ' ' + address.street + ' ' +
                    address.city + ' ' + address.region + ' ' + address.country + ' ' + address.postalCode)
                }}>
                <Icon name='copy'></Icon>
              </Button>
            </CardItem>
          }
        </Card>

        <View style={{ flexDirection: 'row', justifyContent: "space-around", marginTop: 10 }}>
          <Button small style={{ width: 150, justifyContent: "center" }} onPress={() => setupdatePeriod(1000)}>
            <Text>Update Location</Text>
          </Button>
          <Button small style={{ width: 150, justifyContent: "center" }} onPress={() => stop_update_location()}>
            <Text>Stop Update</Text>
          </Button>
        </View>
        <View style={{ flexDirection: 'row', justifyContent: "space-around", marginTop: 10 }}>
          <Button small style={{ width: 150, justifyContent: "center" }} onPress={() => search_address()}>
            <Text>Search Address</Text>
          </Button>
          <Button small style={{ width: 150, justifyContent: "center" }} onPress={() => open_map()}>
            <Text>Open Map</Text>
          </Button>
        </View>
      </Content>
    </Container>
  );
}

TaskManager.defineTask(LOCATION_TASK_NAME, ({ data, error }) => {
  if (error) {
    // Error occurred - check `error.message` for more details.
    console.log(error.message)
    return;
  }
  if (data) {
    const { locations } = data;
    // do something with the locations captured in the background
    background_location = locations[locations.length - 1]
  }
});

reference:
http://chuanshuoge2.blogspot.com/2020/03/expo-location.html

No comments:

Post a Comment