Я использую Geofire в своем приложении для отображения разных уведомлений в разных местах геозоны, я могу использовать Geofire для хранения нескольких местоположений и выдавать одно уведомление на все точки геозоны. но я хочу отправить уведомления на определенные точки геозоны в том же приложении. как это сделать ?
вот мой код
package com.example.geofencing
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.BitmapFactory
import android.graphics.Color
import android.location.Location
import android.media.MediaPlayer
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Looper
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.core.app.NotificationCompat
import com.firebase.geofire.GeoFire
import com.firebase.geofire.GeoLocation
import com.firebase.geofire.GeoQuery
import com.firebase.geofire.GeoQueryEventListener
import com.google.android.gms.location.*
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.CircleOptions
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.Marker
import com.google.android.gms.maps.model.MarkerOptions
import com.google.android.gms.tasks.OnCompleteListener
import com.google.android.gms.tasks.Task
import com.google.firebase.database.*
import com.karumi.dexter.Dexter
import com.karumi.dexter.PermissionToken
import com.karumi.dexter.listener.PermissionDeniedResponse
import com.karumi.dexter.listener.PermissionGrantedResponse
import com.karumi.dexter.listener.PermissionRequest
import com.karumi.dexter.listener.single.PermissionListener
import java.util.jar.Manifest
import kotlin.random.Random
class MapsActivity : AppCompatActivity(), OnMapReadyCallback, IOnLoadLocationListener,
GeoQueryEventListener {
private var mMap:GoogleMap? = null
private lateinit var locationRequest:LocationRequest
private lateinit var locationCallback: LocationCallback
private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
private var currentMarker : Marker? = null
private lateinit var myLocationRef : DatabaseReference
private lateinit var dangerousArea : MutableList<LatLng>
private lateinit var listener : IOnLoadLocationListener
private lateinit var myCity:DatabaseReference
private lateinit var lastLocation:Location
private var geoQuery:GeoQuery? = null
private lateinit var geoFire: GeoFire
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_maps)
Dexter.withActivity(this).withPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
.withListener(object :PermissionListener{
override fun onPermissionGranted(response: PermissionGrantedResponse?) {
buildLocationRequest()
buildLocationCallback()
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this@MapsActivity)
addDangerousToFirebase()
initArea()
settingGeoFire()
}
override fun onPermissionRationaleShouldBeShown(
permission: PermissionRequest?,
token: PermissionToken?
) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onPermissionDenied(response: PermissionDeniedResponse?) {
Toast.makeText(this@MapsActivity,"You must enable it",Toast.LENGTH_LONG).show()
}
}).check()
}
override fun onStop() {
fusedLocationProviderClient.removeLocationUpdates(locationCallback)
super.onStop()
}
override fun onGeoQueryReady() {
}
override fun onKeyEntered(key: String?, location: GeoLocation?) {
Log.d("anique",location?.latitude.toString()+" "+location?.longitude.toString())
Log.d("anique",key)
sendNotification("EDMTDev", String.format("is entered the dangerous area",key))
}
override fun onKeyMoved(key: String?, location: GeoLocation?) {
sendNotification("EDMTDev", String.format("is move within the dangerous area",key))
}
override fun onKeyExited(key: String?) {
sendNotification("EDMTDev", String.format("is leaved the dangerous area",key))
}
override fun onGeoQueryError(error: DatabaseError?) {
Toast.makeText(this,error?.message,Toast.LENGTH_LONG).show()
}
//Add areas to dangerous area list and call methods addUserMarker() && addCircleArea
override fun onLocationLoadSuccess(latLngs: List<MyLatLng>) {
dangerousArea = ArrayList()
for (myLatLng in latLngs){
val convert = LatLng(myLatLng.latitude,myLatLng.longitude)
dangerousArea!!.add(convert)
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
if (mMap!=null){
mMap!!.clear()
addUserMarker()
addCircleArea()
}
}
}
override fun onLocationLoadFailed(message: String) {
Toast.makeText(this,message,Toast.LENGTH_LONG).show()
}
override fun onMapReady(googleMap: GoogleMap) {
mMap = googleMap
mMap!!.uiSettings.isZoomControlsEnabled = true
if (fusedLocationProviderClient != null){
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
if (checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)!=PackageManager.PERMISSION_GRANTED)
return
}
fusedLocationProviderClient!!.requestLocationUpdates(locationRequest,locationCallback!!,Looper.myLooper())
addCircleArea()
}
}
private fun addDangerousToFirebase() {
dangerousArea = ArrayList()
dangerousArea.add(LatLng(30.1696660124382,-97.8866383060813))
dangerousArea.add(LatLng(30.1674688494844,-97.8852666914463))
dangerousArea.add(LatLng(30.1601636,-97.881481))
dangerousArea.add(LatLng(30.1519046999999,-97.8745824999999))
dangerousArea.add(LatLng(30.1500762000813,-97.8729680925607))
dangerousArea.add(LatLng(30.1417598545781,-97.8674340248107))
dangerousArea.add(LatLng(30.1341024795207,-97.8636195883154))
FirebaseDatabase.getInstance().getReference("DangerousArea")
.child("MyCity")
.setValue(dangerousArea)
.addOnCompleteListener{Toast.makeText(this@MapsActivity,"Update",Toast.LENGTH_LONG).show()
}.addOnFailureListener{ex->Toast.makeText(this@MapsActivity,ex.message,Toast.LENGTH_LONG).show()
}
}
private fun settingGeoFire() {
myLocationRef = FirebaseDatabase.getInstance().getReference("MyLocation")
geoFire = GeoFire(myLocationRef)
}
//retrieve list of areas from firebase and pass it in parameter of function onLocationSuccess()
private fun initArea() {
myCity = FirebaseDatabase.getInstance().getReference("DangerousArea").child("MyCity")
listener = this
myCity.addValueEventListener(object : ValueEventListener{
override fun onCancelled(p0: DatabaseError) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onDataChange(dataSnapshot: DataSnapshot) {
val latLngList = ArrayList<MyLatLng>()
for (locationSnapShot in dataSnapshot.children){
val latLng = locationSnapShot.getValue(MyLatLng::class.java)
latLngList.add(latLng!!)
}
listener.onLocationLoadSuccess(latLngList)
}
})
}
private fun sendNotification(title: String, content: String) {
Toast.makeText(this,content,Toast.LENGTH_LONG).show()
val NOTIFICATION_CHANNEL_ID = "edmt_multiple_location"
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel(
NOTIFICATION_CHANNEL_ID, "MyNotification",
NotificationManager.IMPORTANCE_DEFAULT
)
notificationChannel.description = "Channel Description"
notificationChannel.enableLights(true)
notificationChannel.lightColor = Color.RED
notificationChannel.vibrationPattern = longArrayOf(0, 1000, 500, 1000)
notificationChannel.enableVibration(true)
notificationManager.createNotificationChannel(notificationChannel)
}
val builder = NotificationCompat.Builder(this,NOTIFICATION_CHANNEL_ID)
builder.setContentTitle(title)
.setContentText(content)
.setAutoCancel(false)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(resources,R.mipmap.ic_launcher))
val notification = builder.build()
notificationManager.notify(java.util.Random().nextInt(),notification)
}
//add circle to the dangerous areas
private fun addCircleArea() {
if (geoQuery!=null){
geoQuery!!.removeGeoQueryEventListener(this@MapsActivity)
geoQuery!!.removeAllListeners()
}
for (latLng in dangerousArea){
mMap!!.addCircle(CircleOptions().center(latLng).radius(100.0).strokeColor(Color.BLUE).fillColor(0x220000FF).strokeWidth(5.0f))
geoQuery = geoFire.queryAtLocation(GeoLocation(latLng.latitude,latLng.longitude),0.1)
geoQuery!!.addGeoQueryEventListener(this@MapsActivity)
}
}
// get the lastLocation and call addUserMarker()
private fun buildLocationCallback() {
locationCallback = object:LocationCallback(){
override fun onLocationResult(locationResult: LocationResult?) {
super.onLocationResult(locationResult)
if (mMap!=null){
lastLocation = locationResult!!.lastLocation
addUserMarker()
}
}
}
}
//add user marker from the last location
private fun addUserMarker() {
geoFire!!.setLocation("You", GeoLocation(lastLocation!!.latitude,lastLocation!!.longitude)){_,_ ->
if (currentMarker!=null) currentMarker!!.remove()
currentMarker = mMap!!.addMarker(MarkerOptions().position(LatLng(lastLocation.latitude,lastLocation.longitude))
.title("You"))
mMap!!.animateCamera(CameraUpdateFactory.newLatLngZoom(currentMarker!!.position,12.0f))
}
}
private fun buildLocationRequest() {
locationRequest = LocationRequest()
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
locationRequest.interval = 5000
locationRequest.fastestInterval = 3000
locationRequest.smallestDisplacement = 10f
}
}