title: How to implement live map location in android in MVVM pattern?
body: <p>I have this Activity which contains the map fragment and all the map channel methods</p>
  
  <pre><code>class Maps : AppCompatActivity(), OnMapReadyCallback,
      SharedPreferences.OnSharedPreferenceChangeListener {
      // The BroadcastReceiver used to listen from broadcasts from the service.
      private var myReceiver: MyReceiver? = null
      // A reference to the service used to get location updates.
      private var mService: LocationUpdatesService? = null
      // Tracks the bound state of the service.
      private var mBound = false
      // UI elements.
      private var mRequestLocationUpdatesButton: Button? = null
      private var mRemoveLocationUpdatesButton: Button? = null
  
      private lateinit var mMap: GoogleMap
  
      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
  //        setContentView(R.layout.activity_maps)
          // Obtain the SupportMapFragment and get notified when the map is ready to be used.
  
          val binding: ActivityMapsBinding =
              DataBindingUtil.setContentView(this, R.layout.activity_maps)
  
          val viewModel = ViewModelProvider(this).get(MapsViewModel::class.java)
  
          binding.viewmodel = viewModel
  
          viewModel.initActivity()
  
          myReceiver = MyReceiver()
          // Check that the user hasn't revoked permissions by going to Settings.
          if (ServiceUtils.requestingLocationUpdates(this)) {
              if (!checkPermissions()) {
                  requestPermissions()
              }
          }
  //        lifecycle.addObserver(MapsObserver())
          val mapFragment = supportFragmentManager
              .findFragmentById(R.id.map) as SupportMapFragment
          mapFragment.getMapAsync(this)
      }
  
      // Monitors the state of the connection to the service.
      private val mServiceConnection: ServiceConnection = object : ServiceConnection {
          override fun onServiceConnected(name: ComponentName, service: IBinder) {
              val binder: LocationUpdatesService.LocalBinder = service as LocationUpdatesService.LocalBinder
              mService = binder.service
              mBound = true
          }
  
          override fun onServiceDisconnected(name: ComponentName) {
              mService = null
              mBound = false
          }
      }
  
  
      override fun onStart() {
          super.onStart()
          PreferenceManager.getDefaultSharedPreferences(this)
              .registerOnSharedPreferenceChangeListener(this)
          mRequestLocationUpdatesButton =
              findViewById&lt;View&gt;(R.id.request_location_updates_button) as Button
          mRemoveLocationUpdatesButton =
              findViewById&lt;View&gt;(R.id.remove_location_updates_button) as Button
          mRequestLocationUpdatesButton!!.setOnClickListener {
              if (!checkPermissions()) {
                  requestPermissions()
              } else {
                  mService!!.requestLocationUpdates()
              }
          }
          mRemoveLocationUpdatesButton!!.setOnClickListener { mService!!.removeLocationUpdates() }
          // Restore the state of the buttons when the activity (re)launches.
          setButtonsState(ServiceUtils.requestingLocationUpdates(this))
          // Bind to the service. If the service is in foreground mode, this signals to the service
  // that since this activity is in the foreground, the service can exit foreground mode.
          bindService(
              Intent(this, LocationUpdatesService::class.java), mServiceConnection,
              Context.BIND_AUTO_CREATE
          )
      }
  
      override fun onResume() {
          super.onResume()
          LocalBroadcastManager.getInstance(this).registerReceiver(
              myReceiver!!,
              IntentFilter(LocationUpdatesService.ACTION_BROADCAST)
          )
      }
  
      override fun onPause() {
          LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver!!)
          super.onPause()
      }
  
      override fun onStop() {
          if (mBound) { // Unbind from the service. This signals to the service that this activity is no longer
  // in the foreground, and the service can respond by promoting itself to a foreground
  // service.
              unbindService(mServiceConnection)
              mBound = false
          }
          PreferenceManager.getDefaultSharedPreferences(this)
              .unregisterOnSharedPreferenceChangeListener(this)
          super.onStop()
      }
  
      /**
       * Returns the current state of the permissions needed.
       */
      private fun checkPermissions(): Boolean {
          return PackageManager.PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(
              this,
              Manifest.permission.ACCESS_FINE_LOCATION
          )
      }
  
      private fun requestPermissions() {
          val shouldProvideRationale =
              ActivityCompat.shouldShowRequestPermissionRationale(
                  this,
                  Manifest.permission.ACCESS_FINE_LOCATION
              )
          // Provide an additional rationale to the user. This would happen if the user denied the
  // request previously, but didn't check the "Don't ask again" checkbox.
          if (shouldProvideRationale) {
              Log.i(
                  TAG,
                  "Displaying permission rationale to provide additional context."
              )
              Snackbar.make(
                  findViewById(R.id.maps_layout),
                  R.string.permission_rationale,
                  Snackbar.LENGTH_INDEFINITE
              )
                  .setAction(R.string.ok) {
                      // Request permission
                      ActivityCompat.requestPermissions(
                          this@Maps,
                          arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
                          REQUEST_PERMISSIONS_REQUEST_CODE
                      )
                  }
                  .show()
          } else {
              // Request permission. It's possible this can be auto answered if device policy
  // sets the permission in a given state or the user denied the permission
  // previously and checked "Never ask again".
              ActivityCompat.requestPermissions(
                  this@Maps,
                  arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
                  REQUEST_PERMISSIONS_REQUEST_CODE
              )
          }
      }
  
      /**
       * Callback received when a permissions request has been completed.
       */
      override fun onRequestPermissionsResult(
          requestCode: Int, permissions: Array&lt;String&gt;,
          grantResults: IntArray
      ) {
          Log.i(TAG, "onRequestPermissionResult")
          if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) {
              if (grantResults.size &lt;= 0) { // If user interaction was interrupted, the permission request is cancelled and you
  // receive empty arrays.
                  Log.i(TAG, "User interaction was cancelled.")
              } else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission was granted.
                  mService!!.requestLocationUpdates()
              } else { // Permission denied.
                  setButtonsState(false)
                  Snackbar.make(
                      findViewById(R.id.maps_layout),
                      R.string.permission_denied_explanation,
                      Snackbar.LENGTH_INDEFINITE
                  )
                      .setAction(R.string.settings) {
                          // Build intent that displays the App settings screen.
                          val intent = Intent()
                          intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
                          val uri = Uri.fromParts(
                              "package",
                              BuildConfig.APPLICATION_ID, null
                          )
                          intent.data = uri
                          intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
                          startActivity(intent)
                      }
                      .show()
              }
          }
      }
  
      /**
       * Receiver for broadcasts sent by [LocationUpdatesService].
       */
      private inner class MyReceiver() : BroadcastReceiver(){
          override fun onReceive(
              context: Context,
              intent: Intent
          ) {
              val location =
                  intent.getParcelableExtra&lt;Location&gt;(LocationUpdatesService.EXTRA_LOCATION)
  
              if (location != null) {
                  Toast.makeText(
                      this@Maps, ServiceUtils.getLocationText(location),
                      Toast.LENGTH_SHORT
                  ).show()
  
                  latitude = location.latitude
                  longitude = location.longitude
              }
          }
      }
  
      override fun onSharedPreferenceChanged(
          sharedPreferences: SharedPreferences,
          s: String
      ) { // Update the buttons state depending on whether location updates are being requested.
          if (s == ServiceUtils.KEY_REQUESTING_LOCATION_UPDATES) {
              setButtonsState(
                  sharedPreferences.getBoolean(
                      ServiceUtils.KEY_REQUESTING_LOCATION_UPDATES,
                      false
                  )
              )
          }
      }
  
      private fun setButtonsState(requestingLocationUpdates: Boolean) {
          if (requestingLocationUpdates) {
              mRequestLocationUpdatesButton!!.isEnabled = false
              mRemoveLocationUpdatesButton!!.isEnabled = true
          } else {
              mRequestLocationUpdatesButton!!.isEnabled = true
              mRemoveLocationUpdatesButton!!.isEnabled = false
          }
      }
  
      companion object {
          private val TAG = Maps::class.java.simpleName
          // Used in checking for runtime permissions.
          private const val REQUEST_PERMISSIONS_REQUEST_CODE = 34
  
          private var latitude: Double = 0.0
          private var longitude: Double =0.0
  
      }
  
      override fun onMapReady(googleMap: GoogleMap) {
          mMap = googleMap
  
          // Add a marker in Sydney and move the camera
          val sydney = LatLng(-34.0, 151.0)
          mMap.addMarker(MarkerOptions().position(sydney).title("Marker in Sydney"))
          mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney))
      }
  }
  </code></pre>
  
  <p>This is the viewmodel I'm using for the activity:</p>
  
  <pre><code> class MapsViewModel() : ViewModel(), OnMapReadyCallback {
  
      private var googleMap: GoogleMap? = null
      var mMapLatLng = ObservableField&lt;LatLng&gt;()
  
      fun initMap(context: Context?, mapFragment: SupportMapFragment?){
          mapFragment?.getMapAsync(this)
      }
  
      @BindingAdapter("initMap")
      fun initMap(mapView: MapView?, latLng: LatLng?) {
          if (mapView != null) {
              mapView.onCreate(Bundle())
              val sydney = LatLng(-34.0, 151.0)
              mapView.getMapAsync(OnMapReadyCallback { googleMap -&gt;
                  // Add a marker
                  googleMap.addMarker(MarkerOptions().position(sydney).title("Marker in India"))
              })
          }
      }
  
  
      fun initActivity(){
          val conn: SocketConnection = SocketConnection()
          conn.initConnection()
      }
  
      override fun onMapReady(googleMap: GoogleMap?) {
          this.googleMap = googleMap
  
          // Add a marker in Sydney and move the camera
          val sydney = LatLng(-34.0, 151.0)
          this.googleMap?.addMarker(MarkerOptions().position(sydney).title("Marker in Sydney"))
          this.googleMap?.moveCamera(CameraUpdateFactory.newLatLng(sydney))
      }
  }
  
  //Maps Observer
  
  class MapsObserver : LifecycleObserver {
  
      @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
  
  
      public fun onCreateEvent(){
  
      }
  
  }
  </code></pre>
  
  <p>I have a location update service in my service package. 
  I am pretty confused about how to structure everything to maintain the MVVM pattern.</p>
  
  <p>Is it fine to the codes in this way, for maintaining the MVVM architecture? I still have not invoked dependency injection here.</p>