Firebase - Coding Infinite https://codinginfinite.com/firebase/ Your infinite Coding Solutions Mon, 07 Oct 2019 17:09:11 +0000 en-US hourly 1 https://wordpress.org/?v=6.5.3 https://codinginfinite.com/wp-content/uploads/2018/07/CODING-INFINITE-FAVICON.png Firebase - Coding Infinite https://codinginfinite.com/firebase/ 32 32 Car Location Tracking Android App With Firebase Tutorial | Part 2 https://codinginfinite.com/location-tracking-app-firebase-android-part-2/ https://codinginfinite.com/location-tracking-app-firebase-android-part-2/#comments Tue, 28 Aug 2018 14:49:51 +0000 https://codinginfinite.com/?p=937 This is the second part of the location tracking tutorial. I hope you guy’s have seen my previous article in which we’ve developed the Driver App. In this tutorial, we’re going to develop the Passenger App. Here, we are not going to do the same work which we’ve done in the previous article like creating...

The post Car Location Tracking Android App With Firebase Tutorial | Part 2 appeared first on Coding Infinite.

]]>
This is the second part of the location tracking tutorial. I hope you guy’s have seen my previous article in which we’ve developed the Driver App.

In this tutorial, we’re going to develop the Passenger App. Here, we are not going to do the same work which we’ve done in the previous article like creating a Google Map API key or creating a Firebase project.

So, without wasting a time let’s dive into Android Studio and start making the Passenger App.

Passenger App

First, add the below dependencies to your app level build.gradle file.

implementation 'com.google.android.gms:play-services-location:15.0.1'
implementation 'com.google.android.gms:play-services-maps:15.0.1'
implementation 'com.google.firebase:firebase-database:16.0.1'

After adding the dependencies you need to sync or build your project. Later the successful build adds the Internet and Location permission to Android. Manifest file.

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

There’s one more thing we need to do, to show the Google Maps in the Android App. Add the below meta tags in Android. Manifest file.

<meta-data android:name="com.google.android.gms.version" 
           android:value="@integer/google_play_services_version" />
 <meta-data android:name="com.google.android.geo.API_KEY" 
            android:value="@string/map_api_key" />  // change it your Google Maps Api key or directly paste API key here.

Now in this app, we don’t need to create a new Firebase project. Below are the steps you need to do for add firebase in Passenger App.

  1. Sign In Firebase Console and open the previous project which you create when working with Driver App.
  2. Click on Settings Icon -> Project Settings.
  3. In General, tab click on Add app -> Add Firebase to your Android app.
  4. After adding the Android app to firebase project download the latest google-services.json file and add to the app directory of your Android app.

All the prep work being done regarding firebase and Google Maps. Now let’s start making Passenger app. Below is the UI of Passenger App that we’re gonna make.

Passenger App UI

You see the UI is very basic, we’ve got a Google Maps and a TextView which tells how many drivers are currently online. The following shows the code of the above UI.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <fragment
        android:id="@+id/supportMap"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="spartons.com.frisbeeGo.fragments.MapFragment" />

    <TextView
        android:id="@+id/totalOnlineDrivers"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginEnd="30dp"
        android:layout_marginStart="30dp"
        android:layout_marginTop="40dp"
        android:background="#FFFFFF"
        android:gravity="center"
        android:padding="10dp"
        android:text="@string/total_online_drivers"
        android:textColor="#000000"
        android:textSize="15sp" />

</RelativeLayout>

MainActivity

class MainActivity : AppCompatActivity(), FirebaseDriverListener {

    companion object {
        private const val MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 6161
        private const val ONLINE_DRIVERS = "online_drivers"
    }

    private lateinit var googleMap: GoogleMap
    private lateinit var locationProviderClient: FusedLocationProviderClient
    private lateinit var locationRequest: LocationRequest
    private lateinit var locationCallback: LocationCallback
    private var locationFlag = true
    private lateinit var valueEventListener: FirebaseEventListenerHelper
    private val uiHelper = UiHelper()
    private val googleMapHelper = GoogleMapHelper()
    private val databaseReference = FirebaseDatabase.getInstance().reference.child(ONLINE_DRIVERS)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val mapFragment: SupportMapFragment = supportFragmentManager.findFragmentById(R.id.supportMap) as SupportMapFragment
        mapFragment.getMapAsync { googleMap = it }
        createLocationCallback()
        locationProviderClient = LocationServices.getFusedLocationProviderClient(this)
        locationRequest = uiHelper.getLocationRequest()
        if (!uiHelper.isPlayServicesAvailable(this)) {
            Toast.makeText(this, "Play Services did not installed!", Toast.LENGTH_SHORT).show()
            finish()
        } else requestLocationUpdate()
        valueEventListener = FirebaseEventListenerHelper(this)
        databaseReference.addChildEventListener(valueEventListener)
    }

    @SuppressLint("MissingPermission")
    private fun requestLocationUpdate() {
        if (!uiHelper.isHaveLocationPermission(this)) {
            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION)
            return
        }
        if (uiHelper.isLocationProviderEnabled(this))
            uiHelper.showPositiveDialogWithListener(this, resources.getString(R.string.need_location), resources.getString(R.string.location_content), object : IPositiveNegativeListener {
                override fun onPositive() {
                    startActivity(Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS))
                }
            }, "Turn On", false)
        locationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper())
    }

    private fun createLocationCallback() {
        locationCallback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult?) {
                super.onLocationResult(locationResult)
                if (locationResult!!.lastLocation == null) return
                val latLng = LatLng(locationResult.lastLocation.latitude, locationResult.lastLocation.longitude)
                Log.e("Location", latLng.latitude.toString() + " , " + latLng.longitude)
                if (locationFlag) {
                    locationFlag = false
                    animateCamera(latLng)
                }
            }
        }
    }

    private fun animateCamera(latLng: LatLng) {
        val cameraUpdate = googleMapHelper.buildCameraUpdate(latLng)
        googleMap.animateCamera(cameraUpdate, 10, null)
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION) {
            val value = grantResults[0]
            if (value == PackageManager.PERMISSION_DENIED) {
                Toast.makeText(this, "Location Permission denied", Toast.LENGTH_SHORT).show()
                finish()
            } else if (value == PackageManager.PERMISSION_GRANTED) requestLocationUpdate()
        }
    }

    override fun onDriverAdded(driver: Driver) {
        val markerOptions = googleMapHelper.getDriverMarkerOptions(LatLng(driver.lat, driver.lng))
        val marker = googleMap.addMarker(markerOptions)
        marker.tag = driver.driverId
        MarkerCollection.insertMarker(marker)
        totalOnlineDrivers.text = resources.getString(R.string.total_online_drivers).plus(" ").plus(MarkerCollection.allMarkers().size)
    }

    override fun onDriverRemoved(driver: Driver) {
        MarkerCollection.removeMarker(driver.driverId)
        totalOnlineDrivers.text = resources.getString(R.string.total_online_drivers).plus(" ").plus(MarkerCollection.allMarkers().size)
    }

    override fun onDriverUpdated(driver: Driver) {
        val marker = MarkerCollection.getMarker(driverId = driver.driverId)
        MarkerAnimationHelper.animateMarkerToGB(marker!!, LatLng(driver.lat, driver.lng), LatLngInterpolator.Spherical())
    }

    override fun onDestroy() {
        super.onDestroy()
        databaseReference.removeEventListener(valueEventListener)
        locationProviderClient.removeLocationUpdates(locationCallback)
        MarkerCollection.clearMarkers()
    }
}

The MainActivity got a bunch of important points which I’m going to explain below.

  • databaseReference: The DatabaseReference will be the online-drivers node because the passenger wants to track all drivers. Now if there is more than one driver then the passenger will be able to see all drivers on Google Map. If you want to listen to the specific driver then another child node will be added with the driverId.
  • onDriverAdded: This method will be called whenever new driver online in the firebase real-time database. When the new driver comes online we show the Marker to Google Maps and store the Marker in our MarkerCollection.
  • onDriverRemoved: This function will be called when the driver goes offline in the firebase real-time database. Later that we’ll remove the driver Marker from Google Maps and from MarkerCollection as well.
  • onDriverUpdated: This method will be called when the driver current position changed. Later that we get the driver Marker from MarkerCollection and animate the Marker to driver new position.
  • onDestroy: In this method, we’re removing firebase events, removing the current location updates and clearing the MarkerCollection.

Other methods of MainActivity are same as Driver App which I’ve explained in my previous article.

MarkerCollection

object MarkerCollection {

    private val markers: MutableList<Marker> = LinkedList()

    fun insertMarker(marker: Marker) = apply {
        markers.add(marker)
    }

    fun getMarker(driverId: String): Marker? {
        for (marker in markers)
            if (marker.tag == driverId) return marker
        return null
    }

    fun clearMarkers() = apply {
        markers.clear()
    }

    fun removeMarker(driverId: String) {
        val marker = getMarker(driverId)
        marker?.remove()
        if (marker != null) markers.remove(marker)
    }

    fun allMarkers() = markers
}

The following explains about MarkerCollection class.

  • insertMarker: Add the Marker instance to markers collection.
  • getMarker: When creating a Marker in MainActivity we set the driverId as a tag so, we search the Marker on the basis of Tag.
  • removeMarker: This method remove the specific driver Marker from the Google Maps when he goes offline.
  • clearMarker: Empty the Marker Collection.

FirebaseEventListenerHelper

class FirebaseEventListenerHelper(private val firebaseDriverListener: FirebaseDriverListener) : ChildEventListener {

    override fun onCancelled(p0: DatabaseError) {

    }

    override fun onChildMoved(p0: DataSnapshot, p1: String?) {

    }

    override fun onChildChanged(p0: DataSnapshot, p1: String?) {
        val driver = p0.getValue(Driver::class.java)
        firebaseDriverListener.onDriverUpdated(driver!!)
    }

    override fun onChildAdded(p0: DataSnapshot, p1: String?) {
        val driver = p0.getValue(Driver::class.java)
        firebaseDriverListener.onDriverAdded(driver!!)
    }

    override fun onChildRemoved(p0: DataSnapshot) {
        val driver = p0.getValue(Driver::class.java)
        firebaseDriverListener.onDriverRemoved(driver!!)
    }
}

This is a helper class for listening to the events in firebase real-time database. The FirebaseEventListenerHelper class implements ChildEventListener interface.

FirebaseDriverListener

interface FirebaseDriverListener {

    fun onDriverAdded(driver: Driver)

    fun onDriverRemoved(driver: Driver)

    fun onDriverUpdated(driver: Driver)
}

The GoogleMapHelper, UiHelper, MarkerAnimationHelper, Driver, IPositiveNegativeListener and LatLngInterpolator classes I’ve discussed these classes in my previous article.

Alright, guys, this is here we complete both of our apps. If you’ve any queries regarding this post please do comment below.

Download Complete Code

Thank you for being here and keep reading…

Here’re some more related articles:

Everything You Need To Know About Using Google Maps In Cab Booking App

5 Best Android Tracking Apps to Find It All

Building A Location Distance Tracking App | Android

Previous Part

The post Car Location Tracking Android App With Firebase Tutorial | Part 2 appeared first on Coding Infinite.

]]>
https://codinginfinite.com/location-tracking-app-firebase-android-part-2/feed/ 20
Car Location Tracking Android App With Firebase Tutorial https://codinginfinite.com/car-location-tracking-android-app-firebase-tutorial/ https://codinginfinite.com/car-location-tracking-android-app-firebase-tutorial/#comments Tue, 28 Aug 2018 14:47:48 +0000 https://codinginfinite.com/?p=925 In this tutorial, we’re building a car location tracking app like Careem and Uber. Although we’re not developing complete apps like Uber and Careem. But we’ll see how to online a driver and show the online driver in the passenger app and update the driver whenever its current location changed. For online and offline the...

The post Car Location Tracking Android App With Firebase Tutorial appeared first on Coding Infinite.

]]>
In this tutorial, we’re building a car location tracking app like Careem and Uber. Although we’re not developing complete apps like Uber and Careem. But we’ll see how to online a driver and show the online driver in the passenger app and update the driver whenever its current location changed.

For online and offline the driver we’re going to use the Firebase Real-time Database. The driver simply sends its current location to the firebase and passenger see the driver on the Google Map.

Below is the demo of applications which we gonna make in this article.

Prerequisite:

  1. You’ve to have a Google Map API key for showing the Map. See this link for getting the API key.
  2. Need a Firebase project for the real-time database. Click to this link for creating a Firebase project.

Now we’ve Google Map API key and a Firebase project let’s dive into coding and start building our mobile applications.

Android App Coding:

Like I said earlier, there are two apps one for driver and one for the passenger. So, we’re gonna start making with the driver app.

DriverApp:

First, add the below dependencies to your app level build.gradle file.

implementation 'com.google.android.gms:play-services-location:15.0.1'
implementation 'com.google.android.gms:play-services-maps:15.0.1'
implementation 'com.google.firebase:firebase-database:16.0.1'

After adding the dependencies you need to sync or build your project. Later the successful build adds the Internet and Location permission to Android. Manifest file.

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Now, to show the Google Maps in the app we need to add the meta tags in Android. Manifest file.

<meta-data
    android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version" />

<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="@string/map_api_key" />   // Change it with your Google Maps API key.

All the prep work are done for showing the Google Maps and for reading the user current Location. Now, we need to add the google-services.json file. In this tutorial, I’m not gonna show you how to create a firebase project, register your Android app to that firebase project, and add the google-services.json file in Android app. There’s a link for a video to add the google-services.json file in Android app.

So, without further ado let’s dive into coding. Below is the UI of the driver app that we’re gonna make.

Driver Tracker App Main Screen

You see the UI is very basic, we’ve one SwitchCompat for online and offline the driver and below is the Google Map itself. Now let’s see the code of the above UI. Below is the activity_main.xml file.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/driverStatusLayout"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/colorPrimary"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/driverStatusTextView"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginStart="15dp"
            android:gravity="center"
            android:text="@string/offline"
            android:textColor="@color/colorIcons"
            android:textSize="22sp" />

        <android.support.v7.widget.SwitchCompat
            android:id="@+id/driverStatusSwitch"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="end"
            android:layout_marginEnd="15dp"
            android:checked="false"
            android:theme="@style/SCBSwitch" />

    </FrameLayout>

    <fragment
        android:id="@+id/supportMap"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/driverStatusLayout"
        tools:context="spartons.com.frisbeeGo.fragments.MapFragment" />

</RelativeLayout>

MainActivity

class MainActivity : AppCompatActivity() {

    companion object {
        private const val MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 2200
    }

    private lateinit var googleMap: GoogleMap
    private lateinit var locationProviderClient: FusedLocationProviderClient
    private lateinit var locationRequest: LocationRequest
    private lateinit var locationCallback: LocationCallback
    private var locationFlag = true
    private var driverOnlineFlag = false
    private var currentPositionMarker: Marker? = null
    private val googleMapHelper = GoogleMapHelper()
    private val firebaseHelper = FirebaseHelper("0000")
    private val markerAnimationHelper = MarkerAnimationHelper()
    private val uiHelper = UiHelper()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val mapFragment: SupportMapFragment = supportFragmentManager.findFragmentById(R.id.supportMap) as SupportMapFragment
        mapFragment.getMapAsync { googleMap = it }
        createLocationCallback()
        locationProviderClient = LocationServices.getFusedLocationProviderClient(this)
        locationRequest = uiHelper.getLocationRequest()
        if (!uiHelper.isPlayServicesAvailable(this)) {
            Toast.makeText(this, "Play Services did not installed!", Toast.LENGTH_SHORT).show()
            finish()
        } else requestLocationUpdate()
        val driverStatusTextView = findViewById<TextView>(R.id.driverStatusTextView)
        findViewById<SwitchCompat>(R.id.driverStatusSwitch).setOnCheckedChangeListener { _, b ->
            driverOnlineFlag = b
            if (driverOnlineFlag) driverStatusTextView.text = resources.getString(R.string.online_driver)
            else {
                driverStatusTextView.text = resources.getString(R.string.offline)
                firebaseHelper.deleteDriver()
            }
        }
    }

    @SuppressLint("MissingPermission")
    private fun requestLocationUpdate() {
        if (!uiHelper.isHaveLocationPermission(this)) {
            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION)
            return
        }
        if (uiHelper.isLocationProviderEnabled(this))
            uiHelper.showPositiveDialogWithListener(this, resources.getString(R.string.need_location), resources.getString(R.string.location_content), object : IPositiveNegativeListener {
                override fun onPositive() {
                    startActivity(Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS))
                }
            }, "Turn On", false)
        locationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper())
    }

    private fun createLocationCallback() {
        locationCallback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult?) {
                super.onLocationResult(locationResult)
                if (locationResult!!.lastLocation == null) return
                val latLng = LatLng(locationResult.lastLocation.latitude, locationResult.lastLocation.longitude)
                Log.e("Location", latLng.latitude.toString() + " , " + latLng.longitude)
                if (locationFlag) {
                    locationFlag = false
                    animateCamera(latLng)
                }
                if (driverOnlineFlag) firebaseHelper.updateDriver(Driver(lat = latLng.latitude, lng = latLng.longitude))
                showOrAnimateMarker(latLng)
            }
        }
    }

    private fun showOrAnimateMarker(latLng: LatLng) {
        if (currentPositionMarker == null)
            currentPositionMarker = googleMap.addMarker(googleMapHelper.getDriverMarkerOptions(latLng))
        else markerAnimationHelper.animateMarkerToGB(currentPositionMarker!!, latLng, LatLngInterpolator.Spherical())
    }

    private fun animateCamera(latLng: LatLng) {
        val cameraUpdate = googleMapHelper.buildCameraUpdate(latLng)
        googleMap.animateCamera(cameraUpdate, 10, null)
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION) {
            val value = grantResults[0]
            if (value == PERMISSION_DENIED) {
                Toast.makeText(this, "Location Permission denied", Toast.LENGTH_SHORT).show()
                finish()
            } else if (value == PERMISSION_GRANTED) requestLocationUpdate()
        }
    }
}

In MainActivity there are a bunch of important points which I’m going to explain below.

  1.  createLocationCallback: We’re calling this function from the onCreate method of our MainActivity. In the LocationCallback abstract method, we’ll get the user current location, update the Driver info on Firebase Real-time database if the driver is online, and animate driver car Marker from the previous Location to a new one.
  2. requestLocationUpdates: Calling this function from the onCreate method of MainActivity if the user has installed GooglePlayServices in his/her mobile. In this method first, we request the Location permission from the user, then we check if the Location provider is enabled, and finally start the location updates.
  3. showOrAnimateMarker: In this method first we check if the driver car Marker is null then we simply add a new Marker to Google Maps else we animate the Marker.
  4. animteCamera: This method is called from createLocationCallback method only once because, we only want to animate the Google Maps to driver current location when he/she opens the app.
  5. onRequestPermissionsResult: Callback of the result of requesting location permission. This method invoked when the user performs an action on permission. Now in this method, if the user denies the permission then we simply show the toast else start the current location updates.

UiHelper

class UiHelper {

    fun isPlayServicesAvailable(context: Context): Boolean {
        val googleApiAvailability = GoogleApiAvailability.getInstance()
        val status = googleApiAvailability.isGooglePlayServicesAvailable(context)
        return ConnectionResult.SUCCESS == status
    }

    fun isHaveLocationPermission(context: Context): Boolean {
        return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || ActivityCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
    }

    fun isLocationProviderEnabled(context: Context): Boolean {
        val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
        return !locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) && !locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
    }

    fun showPositiveDialogWithListener(callingClassContext: Context, title: String, content: String, positiveNegativeListener: IPositiveNegativeListener, positiveText: String, cancelable: Boolean) {
        buildDialog(callingClassContext, title, content)
                .builder
                .positiveText(positiveText)
                .positiveColor(getColor(R.color.colorPrimary, callingClassContext))
                .onPositive { _, _ -> positiveNegativeListener.onPositive() }
                .cancelable(cancelable)
                .show()
    }

    private fun buildDialog(callingClassContext: Context, title: String, content: String): MaterialDialog {
        return MaterialDialog.Builder(callingClassContext)
                .title(title)
                .content(content)
                .build()
    }


    private fun getColor(color: Int, context: Context): Int {
        return ContextCompat.getColor(context, color)
    }

    fun getLocationRequest() : LocationRequest {
        val locationRequest = LocationRequest.create()
        locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        locationRequest.interval = 3000
        return locationRequest
    }
}

The following explains UiHelper class methods.

  1. isPlayServicesAvailable: This method checks that if the user currently has Google Play Services installed or not.
  2. isHaveLocationPermission: Checks that if a user gives the Location permission or not.
  3. isLocationProviderEnabled: Checks if the Location provider enabled or not. If not then open the Settings activity and turn on the Location Provider.
  4. showPositiveDialogWithListener: Utility function to show the Dialog when the user has not enabled the location provider in mobile settings.

GoogleMapHelper

class GoogleMapHelper {

    companion object {
        private const val ZOOM_LEVEL = 18
        private const val TILT_LEVEL = 25
    }

    /**
     * @param latLng in which position to Zoom the camera.
     * @return the [CameraUpdate] with Zoom and Tilt level added with the given position.
     */

    fun buildCameraUpdate(latLng: LatLng): CameraUpdate {
        val cameraPosition = CameraPosition.Builder()
                .target(latLng)
                .tilt(TILT_LEVEL.toFloat())
                .zoom(ZOOM_LEVEL.toFloat())
                .build()
        return CameraUpdateFactory.newCameraPosition(cameraPosition)
    }

    /**
     * @param position where to draw the [com.google.android.gms.maps.model.Marker]
     * @return the [MarkerOptions] with given properties added to it.
     */

    fun getDriverMarkerOptions(position: LatLng): MarkerOptions {
        val options = getMarkerOptions(R.drawable.car_icon, position)
        options.flat(true)
        return options
    }

    private fun getMarkerOptions(resource: Int, position: LatLng): MarkerOptions {
        return MarkerOptions()
                .icon(BitmapDescriptorFactory.fromResource(resource))
                .position(position)
    }
}

MarkerAnimationHelper

class MarkerAnimationHelper {

    fun animateMarkerToGB(marker: Marker, finalPosition: LatLng, latLngInterpolator: LatLngInterpolator) {
        val startPosition = marker.position
        val handler = Handler()
        val start = SystemClock.uptimeMillis()
        val interpolator = AccelerateDecelerateInterpolator()
        val durationInMs = 2000f
        handler.post(object : Runnable {
            var elapsed: Long = 0
            var t: Float = 0.toFloat()
            var v: Float = 0.toFloat()
            override fun run() {
                // Calculate progress using interpolator
                elapsed = SystemClock.uptimeMillis() - start
                t = elapsed / durationInMs
                v = interpolator.getInterpolation(t)
                marker.position = latLngInterpolator.interpolate(v, startPosition, finalPosition)
                // Repeat till progress is complete.
                if (t < 1) {
                    // Post again 16ms later.
                    handler.postDelayed(this, 16)
                }
            }
        })
    }
}

The above MarkerAnimationHelper class animate the driver car Marker from the previous location to user new Location.

LatLngInterpolator

interface LatLngInterpolator {

    fun interpolate(fraction: Float, a: LatLng, b: LatLng): LatLng

    class Spherical : LatLngInterpolator {

        override fun interpolate(fraction: Float, a: LatLng, b: LatLng): LatLng {
            // http://en.wikipedia.org/wiki/Slerp
            val fromLat = toRadians(a.latitude)
            val fromLng = toRadians(a.longitude)
            val toLat = toRadians(b.latitude)
            val toLng = toRadians(b.longitude)
            val cosFromLat = cos(fromLat)
            val cosToLat = cos(toLat)

            // Computes Spherical interpolation coefficients.
            val angle = computeAngleBetween(fromLat, fromLng, toLat, toLng)
            val sinAngle = sin(angle)
            if (sinAngle < 1E-6) {
                return a
            }
            val temp1 = sin((1 - fraction) * angle) / sinAngle
            val temp2 = sin(fraction * angle) / sinAngle

            // Converts from polar to vector and interpolate.
            val x = temp1 * cosFromLat * cos(fromLng) + temp2 * cosToLat * cos(toLng)
            val y = temp1 * cosFromLat * sin(fromLng) + temp2 * cosToLat * sin(toLng)
            val z = temp1 * sin(fromLat) + temp2 * sin(toLat)

            // Converts interpolated vector back to polar.
            val lat = atan2(z, sqrt(x * x + y * y))
            val lng = atan2(y, x)
            return LatLng(toDegrees(lat), toDegrees(lng))
        }

        private fun computeAngleBetween(fromLat: Double, fromLng: Double, toLat: Double, toLng: Double): Double {
            val dLat = fromLat - toLat
            val dLng = fromLng - toLng
            return 2 * asin(sqrt(pow(sin(dLat / 2), 2.0) + cos(fromLat) * cos(toLat) * pow(sin(dLng / 2), 2.0)))
        }
    }
}

The LatLngInterpolator interface helps to animate the driver car Marker.

FirebaseHelper

class FirebaseHelper constructor(driverId: String) {

    companion object {
        private const val ONLINE_DRIVERS = "online_drivers"
    }

    private val onlineDriverDatabaseReference: DatabaseReference = FirebaseDatabase
            .getInstance()
            .reference
            .child(ONLINE_DRIVERS)
            .child(driverId)

    init {
        onlineDriverDatabaseReference
                .onDisconnect()
                .removeValue()
    }

    fun updateDriver(driver: Driver) {
        onlineDriverDatabaseReference
                .setValue(driver)
        Log.e("Driver Info", " Updated")
    }

    fun deleteDriver() {
        onlineDriverDatabaseReference
                .removeValue()
    }
}

Before going to start to explain FirebaseHelper, I want to show you Firebase Real-time Database Structure.

Firebase Realtime Database

The following explains about FirebaseHelper class.

  1. onlineDriverDatabaseReference: When creating a DatabaseReference, we’re adding two children one for online drivers node and another one for the Driver itself. We need to inform firebase real-time database in which node to update the Diver that’s why I’m setting driverId as a top node and below the is the complete Driver object. The driverId must be unique because it differs in whole online drivers node which specific driver node to update.
  2. updateDriver: Update the Driver new Location to firebase real-time database.
  3. deleteDriver: Removes the driver node from firebase real-time database.

Driver

data class Driver(val lat: Double, val lng: Double, val driverId: String = "0000")

You can change driverId with the user primary key any anything which is unique.

Alright, guys, this was all from DriverApp. I’m going to end this article here if you want to see the Passenger app see the next article. If you’ve any queries regarding this post please do comment below.

Download Complete Code

Thank you for being here and keep reading…

Next Part

The post Car Location Tracking Android App With Firebase Tutorial appeared first on Coding Infinite.

]]>
https://codinginfinite.com/car-location-tracking-android-app-firebase-tutorial/feed/ 42
Debugging Realtime Database Performance with Firebase Database Profiler https://codinginfinite.com/firebase-database-profiler-performance-with-firebase-tools/ Tue, 21 Aug 2018 20:29:23 +0000 https://codinginfinite.com/?p=913 Firebase Real-time database is built to handle high data traffic apps, but if you don’t architect your data properly you can run into problems such as slow queries, high database load and most of all expensive bandwidth. So happily, the Firebase developers built us a Database Profiler (firebase profiling) which helps us to understand what’s...

The post Debugging Realtime Database Performance with Firebase Database Profiler appeared first on Coding Infinite.

]]>
Firebase Real-time database is built to handle high data traffic apps, but if you don’t architect your data properly you can run into problems such as slow queries, high database load and most of all expensive bandwidth. So happily, the Firebase developers built us a Database Profiler (firebase profiling) which helps us to understand what’s going on in the real-time database.

So, in order to use the database profileryou need to first install Firebase CLI. The firebase database profiler is bundled as a part of Firebase CLI. There are three steps to run the database profiler.

1. Install Firebase Tools:

To install firebase tools open your windows command line terminal (Cmd) and type below command.

npm install --global firebase-tools

Note: To install firebase tools you first have to install npm first.

2. Login To Firebase:

After successfully installed the firebase tools you need to login to your firebase account. Type the below command to enter firebase credentials.

firebase login

After typing the command your default web browser will be opened and asked you to enter your firebase account credentials.

 

 

Firebase CLI Tools3. Firebase Init:

Later the successful login you need to run the below command, to select on which firebase project you want to run the firebase database profiler.

Note: Before running the command make sure to create a different directory, navigate to that directory and then proceed.

firebase init

After entering the command, you need to verify the directory, select the Deploy Firebase Real-time Database Rules option and then select the firebase project which you need to debug.

4. Realtime Database Profiling:

So in order to profile the firebase real-time database. We need to run the below command to cmd.

firebase database:profile

Once we run the above command, the profiler is going to start requesting operations from your real-time database. The firebase database profiler will stream everything happens to each operation that’s going on to the firebase command line option(CLI).

Getting Real-time database load

Whenever you feel like you’ve collected enough operations, you just press Enter. Once you hit Enter button the CLI is going to aggregate all of those operations into a report that’s easy for you to understand.

Real-time database CLI reportNow the firebase CLI report is broken up into three sections.

4.1 Speed Report:

The speed report is the first section and it’s broken down into the read, write and broadcast speed.

  • Read & Write Speed: The read and write speed has four different columns. The Path column is for where data is written or from which Path data is reading. The Count is for how many times data has been reading or how many times written. Average column is the processing time and there’s also a column for Permission Denied, which lets you know if your security rules are misconfigured, or if you’ve apps that are making requests that they shouldn’t be.
  • Broadcast Speed: The broadcast speed is the time that it takes after the initial query when data gets updated at a location, for the servers to process and send out those updates.

4.2 Bandwidth Report:

The bandwidth report is the next section and it is also broken down into two categories, bytes download from the server and bytes uploaded to the server.

  • Downloaded Bytes: It corresponds to reads and updates sent from the server. The downloaded bytes also have four different columns. The Path column is for, from where the data has been downloaded, the Total column is for the size of data has been downloaded. The third one is Count, how many times data has been downloaded and the last column is Average for per download size.
  • Uploaded Bytes: The uploaded bytes are written that the clients are making to the server. The uploaded bytes have the same column like downloaded bytes but they measure data on the basis of clients sending data to the server.

4.3 Unindexed Queries:

This unindexed query is the last section of the firebase database profiler report. Usually, this ends up being an empty section. However, if it’s not empty then you really need to draw attention to it. Unindexed queries are when our client SDKs, instead of relying on an index to query data the server sends all of the data to a client device. These will lead to a very expensive operation for you.

Note: The Real-time database SDK also gives you Unindexed query warning in the console.

Let’s say we’ve tested our database in development mode and launch the product if everything works. Now, what if I want to see how my database works in production mode. The good news is, the firebase database profiler is designed to run in production without any overhead. It’s safe to use in all production.

You see the firebase database profiler tools is very helpful for you to check which queries take more bandwidth, which queries takes more average time to read, how to increase read and write speed etc..

Alright, guys that were all for this article. If you’ve any queries regarding this post please do comment below.

Thank you for being here and keep reading…

The post Debugging Realtime Database Performance with Firebase Database Profiler appeared first on Coding Infinite.

]]>
Google Firebase Live Group Chat JavaScript https://codinginfinite.com/google-firebase-live-group-chat-example-javascript/ Wed, 25 Apr 2018 12:52:39 +0000 http://codinginfinite.com/?p=343 Hi guys, today I’m going to implement Live Group Chat Example using Google Firebase Real-time Database. The complete working example is available on Github, you can find the link at the bottom of this post. You may also check Demo. Live Group Chat Demo Setup Firebase If you don’t have a Firebase account, you can go...

The post Google Firebase Live Group Chat JavaScript appeared first on Coding Infinite.

]]>
Firebase Group Chat Example Javascript

Hi guys, today I’m going to implement Live Group Chat Example using Google Firebase Real-time Database. The complete working example is available on Github, you can find the link at the bottom of this post. You may also check Demo.

Live Group Chat Demo

Setup Firebase

If you don’t have a Firebase account, you can go to the Signup page and create an account. If you already have an account, you can Login here.

Once you are on Account’s page, you will have an option there to create a new Firebase app.

Realtime moving Cars on Google Maps JavaScript using Google Firebase

From Firebase Console find “Add Firebase to your web app”

You will find JavaScript Code with your project key & other credentials.

<script src="proxy.php?url=https://www.gstatic.com/firebasejs/4.13.0/firebase.js"></script>
<script>
  // Initialize Firebase
  var config = {
    apiKey: "your-project-key-here",
    authDomain: "group-chat-codinginfinite.firebaseapp.com",
    databaseURL: "https://group-chat-codinginfinite.firebaseio.com",
    projectId: "group-chat-codinginfinite",
    storageBucket: "group-chat-codinginfinite.appspot.com",
    messagingSenderId: "129035491745"
  };
  firebase.initializeApp(config);
</script>

Setup Firebase Real-time Database

Create a Database to store the message and user id for each user. How my database looks like

group chat firebase realtime database

Firebase Anonymous Authentication

Enable firebase anonymous authentication:

  1. In the Firebase console, open the Authentication section.
  2. On the Sign-in Methods page, enable the Anonymous sign-in method.

Now you can get a unique id for each user using this code

var user = firebase.auth().signInAnonymously();

    firebase.auth().onAuthStateChanged(function(user) {
      if (user) {
        // User is signed in.
        var isAnonymous = user.isAnonymous;
        user_id = user.uid;
      } else {
        // User is signed out.
      }
    });

Write Message to Firebase Database

This simple code will push an object of user id and message text into the firebase database with a unique id.

function writeUserData(message) {

      db_ref.push({
          user_id: user_id,
          message: message
      });
  }

Add Messages to Chat

Now we need to add Events for Adding Messages, we do not need to get all messages List from Firebase Database, Add Event will do the job automatically for us.

// get firebase database reference...
var db_ref = firebase.database().ref('/');

db_ref.on('child_added', function (data) {
  var type;
  if(data.val().user_id == user_id){
    type="sent";
  }
  else{
    type="replies";
  }
  $('<li class="'+type+'"><p>' + data.val().message + '</p></li>').appendTo($('.messages ul'));
  $('.message-input input').val(null);
  $('.contact.active .preview').html('<span>You: </span>' + data.val().message);

    $(".messages").animate({ scrollTop: $(".messages")[0].scrollHeight }, 0);
});

Combine the code to get Complete Live group chat or you can download complete example from Github.

 
 
 

The post Google Firebase Live Group Chat JavaScript appeared first on Coding Infinite.

]]>
Realtime moving Cars on Google Maps JavaScript & Google Firebase https://codinginfinite.com/realtime-moving-cars-google-maps-javascript-firebase/ https://codinginfinite.com/realtime-moving-cars-google-maps-javascript-firebase/#comments Fri, 20 Apr 2018 07:49:47 +0000 http://codinginfinite.com/?p=279 Our aim has always been providing the solutions which are difficult to find or difficult to implement. Here’s another solution for real-time moving cars on Google Maps JavaScript using Google Firebase Real-time Database.  The complete working example is available on Github, you can find the link at the bottom of this post.  You may also check Demo here:...

The post Realtime moving Cars on Google Maps JavaScript & Google Firebase appeared first on Coding Infinite.

]]>
Realtime Moving Cars on Map using Firebase

Our aim has always been providing the solutions which are difficult to find or difficult to implement. Here’s another solution for real-time moving cars on Google Maps JavaScript using Google Firebase Real-time Database.  The complete working example is available on Github, you can find the link at the bottom of this post. 

You may also check Demo here:

Realtime Map Demo

What is Firebase?

Firebase is a real-time application platform. It allows developers to build rich, collaborative applications quickly using just client-side code. Applications built with Firebase:

  • Can be built rapidly
  • Update in realtime
  • Remain responsive even when a network connection is unavailable

Setup Firebase

If you don’t have a Firebase account, you can go to the Signup page and create an account. If you already have an account, you can Login here.

Once you are on Account’s page, you will have an option there to create a new Firebase app.

Firebase Console - Coding Infinite
Firebase Console – Coding Infinite

From Firebase Console find “Add Firebase to your web app”

You will find JavaScript Code with your project key & other credentials.

<script src="proxy.php?url=https://www.gstatic.com/firebasejs/4.12.1/firebase.js"></script>
<script>
// Initialize Firebase
var config = {
    apiKey: "project-key-here",
    authDomain: "realtime-on-map-example.firebaseapp.com",
    databaseURL: "https://realtime-on-map-example.firebaseio.com",
    projectId: "realtime-on-map-example",
    storageBucket: "",
    messagingSenderId: "851837622908"
};
firebase.initializeApp(config);
</script>

Firebase Realtime Database

Create a Database for Latitude, Longitude, and angle of the car. How my database looks like

Firebase Realtime Database - Coding Infinite
Firebase Realtime Database – Coding Infinite

Simple Google Maps Setup

For moving realtime cars on Maps using Firebase our first step is to display a Google Map using Google Maps JavaScript API, for doing this, first you need to get API key for Google Maps and then use the below code to display Google Maps

<!DOCTYPE html>
<html>
    <head>
        <style>
            #map {
                height: 100%;
            }

            html, body {
                height: 100%;
                margin: 0;
                padding: 0;
            }
        </style>
    </head>

    <body>
        <div id="map"></div>

        <!-- jQuery CDN -->
        <script src="proxy.php?url=https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        <script>

            var map;
            function initMap() { // Google Map Initialization... 
                map = new google.maps.Map(document.getElementById('map'), {
                    zoom: 16,
                    center: new google.maps.LatLng(31.52011, 74.368604),
                    mapTypeId: 'terrain'
                });
            }

        </script>
        <script async defer src="proxy.php?url=https://maps.googleapis.com/maps/api/js?key=AIzaSyC7DtKqWoAtgKFmYtUu-PceyA7bV1Y9NTU&callback=initMap">
        </script>

    </body>
</html>

Firebase Add, Remove, Update Events

Now we need to add Events for Car Added, Car Removed or if Car changes location, we do not need to get all Cars List from Firebase Database, Add Event will do the job automatically for you.

// get firebase database reference...
var cars_Ref = firebase.database().ref('/');

// this event will be triggered when a new object will be added in the database...
cars_Ref.on('child_added', function (data) {
    cars_count++;
    AddCar(data);
});

// this event will be triggered on location change of any car...
cars_Ref.on('child_changed', function (data) {
    markers[data.key].setMap(null);
    AddCar(data);
});

// If any car goes offline then this event will get triggered and we'll remove the marker of that car...  
cars_Ref.on('child_removed', function (data) {
    markers[data.key].setMap(null);
    cars_count--;
    document.getElementById("cars").innerHTML = cars_count;
});

Adding Car Marker

you can see in the above code that we child_added and chiled_changed methods calling AddCar Method, Job of this method is to create a car marker and Add marker on the Map.

function AddCar(data) {

    var icon = { // car icon
        path: 'M29.395,0H17.636c-3.117,0-5.643,3.467-5.643,6.584v34.804c0,3.116,2.526,5.644,5.643,5.644h11.759   c3.116,0,5.644-2.527,5.644-5.644V6.584C35.037,3.467,32.511,0,29.395,0z M34.05,14.188v11.665l-2.729,0.351v-4.806L34.05,14.188z    M32.618,10.773c-1.016,3.9-2.219,8.51-2.219,8.51H16.631l-2.222-8.51C14.41,10.773,23.293,7.755,32.618,10.773z M15.741,21.713   v4.492l-2.73-0.349V14.502L15.741,21.713z M13.011,37.938V27.579l2.73,0.343v8.196L13.011,37.938z M14.568,40.882l2.218-3.336   h13.771l2.219,3.336H14.568z M31.321,35.805v-7.872l2.729-0.355v10.048L31.321,35.805',
        scale: 0.4,
        fillColor: "#427af4", //<-- Car Color, you can change it 
        fillOpacity: 1,
        strokeWeight: 1,
        anchor: new google.maps.Point(0, 5),
        rotation: data.val().angle //<-- Car angle
    };

    var uluru = { lat: data.val().lat, lng: data.val().lng };

    var marker = new google.maps.Marker({
        position: uluru,
        icon: icon,
        map: map
    });

    markers[data.key] = marker; // add marker in the markers array...
    document.getElementById("cars").innerHTML = cars_count;
}

After combining the code you can view realtime moving cars on Google Maps. when you’ll update latitude or longitude at firebase database your car will move in realtime.

 
 
 

The post Realtime moving Cars on Google Maps JavaScript & Google Firebase appeared first on Coding Infinite.

]]>
https://codinginfinite.com/realtime-moving-cars-google-maps-javascript-firebase/feed/ 10