У меня есть это действие, которое содержит фрагмент карты и все методы канала карты
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<View>(R.id.request_location_updates_button) as Button
mRemoveLocationUpdatesButton =
findViewById<View>(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<String>,
grantResults: IntArray
) {
Log.i(TAG, "onRequestPermissionResult")
if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) {
if (grantResults.size <= 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<Location>(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))
}
}
Это модель представления, которую я использую для действия:
class MapsViewModel() : ViewModel(), OnMapReadyCallback {
private var googleMap: GoogleMap? = null
var mMapLatLng = ObservableField<LatLng>()
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 ->
// 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(){
}
}
У меня есть служба обновления местоположения в моем пакете услуг. Я довольно озадачен тем, как структурировать все для поддержки шаблона MVVM.
Хорошо ли кодам таким образом поддерживать архитектуру MVVM? Я до сих пор не вызывал внедрение зависимости здесь.