Как показывать разные уведомления на разных точках геозоны в одном приложении с помощью геофайра? - PullRequest
0 голосов
/ 11 ноября 2019

Я использую 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
    }

}

...