DEV Community

Cover image for FusionLocation: Cross-Platform Swift Mobile App Development
SCADE for Developers
SCADE for Developers

Posted on • Edited on

FusionLocation: Cross-Platform Swift Mobile App Development

Introduction

Hi everyone πŸ™‹πŸ»β€β™‚οΈ! My name is Vedant, and it is time to build another SCADE app! We all love hybrid tech stack when it comes to building cross-platform mobile apps. And then we start having discussions within the team for the possible tech stack to implement the new app idea. But what if the team is not willing to learn any other language?

SCADE solves this problem for us and makes it super easy to code cross-platform mobile apps using the only language Swift. It’s like developing Android apps using Swift, without coding a single line in Java or Kotlin. In this article, we will explore the map and geolocation apps that use just a few lines of Swift code, to develop using SCADE.

Fusion SDK

Recently, the SCADE team has gone open-source with their breakthrough technology called Fusion libraries. Fusion enables us to invoke the Android APIs using the Scade Fusion SDK. The benefit, is we don’t have to bother about setting up the Android platform-specific stuff in the gradle or anywhere. Even iOS-specific settings are very easy and no further prerequisite is required for the same.

SCADE swift codebase acts as the single source of truth in this case, and Fusion SDK makes it possible. Currently, Fusion SDK provides easy integrations for the Geolocation, Bluetooth, NFC, and Media Player, and many more Fusion libraries are in development by the SCADE developers.

Image description

We will now start the development of the FusionLocation app by integrating the Fusion extension in our SCADE project. Navigate to the Package.swift and add the below code snippet.

dependencies: [
        .package(name: "FusionLocation", url: "https://github.com/scade-platform/FusionLocation.git", .branch("main"))
    ],    
targets: [
        .target(
            name: "GeoLocation",
            dependencies: [
                .product(name: "FusionLocation", package: "FusionLocation")
            ],
            exclude: ["main.page"],
            swiftSettings: [
                .unsafeFlags(["-F", SCADE_SDK], .when(platforms: [.macOS, .iOS])),
                .unsafeFlags(["-I", "\(SCADE_SDK)/include"], .when(platforms: [.android])),
            ]
        )
    ]
Enter fullscreen mode Exit fullscreen mode

We also need to provide the location permission in build.yaml for both iOS and Android platforms.

ios:
  ...
  plist:
    ...
    - key: NSLocationAlwaysAndWhenInUseUsageDescription
      type: string
      value: This app just tracks your location to test FusionLocation      
    - key: NSLocationWhenInUseUsageDescription
      type: string
      value: This app just tracks your location to test FusionLocation
    ...

android:
  ...
  permissions: ["ACCESS_FINE_LOCATION"]
Enter fullscreen mode Exit fullscreen mode

Please note that the Google API key can also be passed as the value of the key google-api-key in build.yaml for invoking Google Cloud APIs related to maps and geolocation.

Tracking User Location

FusionLocation has utility methods for performing location updates in the background. We often require background location update operations for various use cases related to mobility and delivery of mobile apps. All we need to do is to initialize the LocationManager instance, authenticate the instance and call the location update method of the LocationManager.

// initialize the LocationManager
let locationManager = LocationManager(usage: .always)

// request authorization
locationManager.requestAuthorization()

// start location tracking
locationManager.startUpdatingLocation { location in
    print("Location Updated.")
    print(location?.coordinate)
}
Enter fullscreen mode Exit fullscreen mode

Get the Distance between two Coordinates

In order to find the distance between two locations, we will call the inbuilt distanceBetween method and will pass the location value for the from and to params.

let mallLocation = Location(latitude: 12.9574292, longitude: 77.6383552)
let parkLocation = Location(latitude: 12.973826, longitude: 77.590591)

let dist = locationManager.distanceBetween(
          from: familyMallLocation, to: cubbon_parkLocation)

print("Distance between Mall and the Park:")
print(String(dist))
Enter fullscreen mode Exit fullscreen mode

We will get the output somewhat like this with real-time updates of the user location coordinates and the distance in meters.

Image description

Get Bearing distance

Bearing distance is required in various domains like aircraft navigation or land surveying. Fusion makes it very easy to calculate the bearing distance between two coordinates.

// get bearing between from and to
locationManager.bearingBetween(from: from, to: to)
Enter fullscreen mode Exit fullscreen mode

SCADE Map Integration

SCADE provides MapUIControl to integrate the map widget into our mobile app. Let’s start integrating the map into our existing Fusion SCADE app. Navigate to the main.page and add the below UI widgets.

a.) MapUI Control: Drag the map widget to the page and we will make the map to cover the entire main.page height and width.

b.) RowViewUI Control: We need RowView to contain a set of buttons horizontally laid at the bottom of the page.

c.) 5 UI Buttons: We will now create 5 buttons horizontally in the RowView, namely Airport and Seaport to mark the location in the map, and the other 3 buttons will be used to set the type of map at runtime.

Image description

First, we will define a few location coordinates which will be used throughout the app.

let airport_coordinate = SCDPlatformLocationCoordinate(latitude: 28.556160, longitude: 77.100281)

let seaport_coordinate = SCDPlatformLocationCoordinate(latitude: 13.08441, longitude: 80.2899)
Enter fullscreen mode Exit fullscreen mode

In order to navigate to the defined coordinate region on the map, we use the setRegion method of the mapWidget.

func goto(coordinates: SCDPlatformLocationCoordinate) {
        self.mapWidget.setRegion(coordinates, latitudinalMeters: 1000, longitudinalMeters: 1000)
}
Enter fullscreen mode Exit fullscreen mode

It takes the coordinates as the input parameter along with the latitudinalMeters and longitudinalMeters to display the location for the given width and height of the region. We will call this goto method for the above-defined buttons to navigate to the coordinates on the map.

// Goto Airport location
self.btnAirport.onClick.append(
  SCDWidgetsEventHandler { _ in
    self.goto(coordinates: self.airport_coordinate)

})
// goto Seaport location
self.btnSeaport.onClick.append(
    SCDWidgetsEventHandler { _ in
        self.goto(coordinates: self.seaport_coordinate)

})
Enter fullscreen mode Exit fullscreen mode

To show the marker image for the location on the map, we use the map annotations to append the marker image using the SCDWidgetsMapAnnotation class.

func setPinAsAnnotaton(coordinate:   SCDPlatformLocationCoordinate, imagePath: String) {

    let svgImage = SCDSvgImage(width: SCDSvgUnit(value: 55),  height: SCDSvgUnit(value: 55))
    svgImage.xhref = imagePath

    let ann = SCDWidgetsMapAnnotation(location: coordinate)
    ann.drawing = svgImage

    self.mapWidget.annotations.append(ann)
}
Enter fullscreen mode Exit fullscreen mode

We will now call the above utility method and pass the coordinate and image file path as input parameters.

self.setPinAsAnnotaton(coordinate: airport_coordinate,  imagePath: "Assets/mpin.png")
Enter fullscreen mode Exit fullscreen mode

iOS

ios1

ios2

Android

android1

andorid2

SCADE map widget provides the feature to change the map type to Standard, Satellite, and Hybrid. SCDWidgetsMapType class has the inbuilt methods for these map types.

func setMapType(_ name: String) {
    switch name {
    case "btnHybrid":
      self.mapWidget.mapType = SCDWidgetsMapType.hybrid
    case "btnSatelite":
      self.mapWidget.mapType = SCDWidgetsMapType.satellite
    case "btnStandard":
      self.mapWidget.mapType = SCDWidgetsMapType.standard
    default:
      print("not covered")
    }
}
Enter fullscreen mode Exit fullscreen mode

We will now set the click listeners to the rest of the buttons to change the map type at runtime.

// satellite mode
self.btnSatelite.onClick.append(
   SCDWidgetsEventHandler { _ in
      self.setMapType("btnSatelite")
})
// Standard mode
self.btnStandard.onClick.append(
   SCDWidgetsEventHandler { _ in
      self.setMapType("btnStandard")
})

// Hybrid mode
self.btnHybrid.onClick.append(
   SCDWidgetsEventHandler { _ in
       self.setMapType("btnHybrid")
})
Enter fullscreen mode Exit fullscreen mode

We are now ready to run the app and test if everything is working as expected. Please save the project otherwise the changes won’t reflect in the app.

iOS

Image description

Android

Image description

Voila πŸŽ‰! It is very easy to integrate SCADE map and Fusion SDK to create an iOS or Android app for all location needs. We don’t have to bother about any native Android/iOS environment setup or anything like that. We call Android APIs directly through Fusion SDK.

It is cool right! You should try FusionLocation in your next app for maps and geolocation 😊.

Top comments (0)