地理围栏在 Kotlin 不起作用

2020年5月26日 21点热度 0条评论

尽管相同的代码在Java中也可以使用,但Geofence在Kotlin中不起作用。我是Kotlin的新手,因此无法理解该问题。
实际上我正在从 Activity MainGeofence.kt调用MainActivity服务类,以下是代码

MainGeofence.kt

 public class MainGeofence : IntentService("MyService"), LocationListener {

    internal var mGeofencePendingIntent: PendingIntent? = null
    private var mGeofenceList: ArrayList<Geofence>? = null
    private var mGoogleApiClient: GoogleApiClient? = null
    val TAG = "Activity"
    internal lateinit var mLocationRequest: LocationRequest
    internal var currentLatitude = <<lat value
    internal var currentLongitude = <<long value

    override fun onCreate() {
        super.onCreate()
    }

    override fun onHandleIntent(p0: Intent?) {
        mGeofenceList = ArrayList<Geofence>()

        if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this)
                == ConnectionResult.SUCCESS) {
            initGoogleAPIClient()

            createGeofences(currentLatitude, currentLongitude)
        } else {
            Log.e(TAG, "Your Device doesn't support Google Play Services.")
        }

        mLocationRequest = LocationRequest.create()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(1 * 1000)
                .setFastestInterval(1 * 1000)
    }

    public fun initGoogleAPIClient(): Unit {
        mGoogleApiClient = GoogleApiClient.Builder(this)
                .addApi(API)
                .addConnectionCallbacks(connectionAddListener)
                .addOnConnectionFailedListener(connectionFailedListener)
                .build()
        mGoogleApiClient?.connect()
    }

    private val connectionAddListener = object : GoogleApiClient.ConnectionCallbacks {
        @SuppressLint("MissingPermission")
        override fun onConnected(bundle: Bundle?) {
            Log.i(TAG, "onConnected")

            @SuppressLint("MissingPermission")
            val location = FusedLocationApi.getLastLocation(mGoogleApiClient)

            if (location == null) {
                FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this@MainGeofence)
            } else {
                //If everything went fine lets get latitude and longitude
                currentLatitude = location.latitude
                currentLongitude = location.longitude

                Log.i(TAG, currentLatitude.toString() + " WORKS " + currentLongitude)

                //createGeofences(currentLatitude, currentLongitude);
                //registerGeofences(mGeofenceList);
            }

            try {
                GeofencingApi.addGeofences(
                        mGoogleApiClient,
                        getGeofencingRequest(),
                        getGeofencePendingIntent()
                ).setResultCallback(ResultCallback<Status> { status ->
                    if (status.isSuccess) {
                        Log.i(TAG, "Saving Geofence")

                    } else {
                        Log.e(TAG, "Registering geofence failed: " + status.statusMessage +
                                " : " + status.statusCode)
                    }
                })

            } catch (securityException: SecurityException) {
                // Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
                Log.e(TAG, "Error")
            }

        }

        override fun onConnectionSuspended(i: Int) {

            Log.e(TAG, "onConnectionSuspended")

        }
    }

    /**
     * Create a Geofence list
     */
    fun createGeofences(latitude: Double, longitude: Double) {
        val id = UUID.randomUUID().toString()
        println("latnlon " + latitude + " " + longitude)
        val fence = Geofence.Builder()
                .setRequestId(id)
                .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_EXIT)
                .setCircularRegion(latitude, longitude, 50f)
                .setExpirationDuration(Geofence.NEVER_EXPIRE)
                .build()
        mGeofenceList?.add(fence)
    }

    private fun getGeofencingRequest(): GeofencingRequest {
        val builder = GeofencingRequest.Builder()
        builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
        builder.addGeofences(mGeofenceList)
        return builder.build()
    }

    private fun getGeofencePendingIntent(): PendingIntent {
        // Reuse the PendingIntent if we already have it.
        if (mGeofencePendingIntent != null) {
            return mGeofencePendingIntent!!
        }
        val intent = Intent(this, GeofenceIntentService::class.java)
        // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
        // calling addGeofences() and removeGeofences().
        return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
    }

    private val connectionFailedListener = GoogleApiClient.OnConnectionFailedListener { Log.e(TAG, "onConnectionFailed") }

    override fun onLocationChanged(location: Location?) {

        if (location != null) {
            currentLatitude = location.latitude
            currentLongitude = location.longitude
            Log.i(TAG, "onLocationChanged")
        }
    }

}


MainActivity.kt

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        dummyBtn = findViewById(R.id.dummyBtn)
        dummyTv = findViewById(R.id.dummyTv)

        dummyBtn.setOnClickListener(View.OnClickListener {
            //            startLocationUpdates()
            startService(Intent(this, MainGeofence::class.java))
              ...
        })
              ....
    }


GeofenceIntentService.kt

public class GeofenceIntentService : IntentService("GeofenceIntentService") {

    private final var TAG: String = "Geofence"

    override fun onHandleIntent(intent: Intent?) {
        Log.i(TAG, "onHandleIntent")
        val geofencingEvent = fromIntent(intent)
        if (geofencingEvent.hasError()) {
            Log.e(TAG, "Goefencing Error " + geofencingEvent.errorCode)
            return
        }
        //Create AudioManager object to change phone profile
        var am: AudioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
        // Get the transition type.
        val geofenceTransition = geofencingEvent.geofenceTransition
        Log.i(TAG, "geofenceTransition = " + geofenceTransition + " Enter : " +
                Geofence.GEOFENCE_TRANSITION_ENTER + "Exit : " + Geofence.GEOFENCE_TRANSITION_EXIT)
        when (geofenceTransition) {

            Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_DWELL -> {
                showNotification("Entered", "Entered the Location")
                am.setRingerMode(AudioManager.RINGER_MODE_VIBRATE) //put ringer to vibration
            }
            Geofence.GEOFENCE_TRANSITION_EXIT -> {
                showNotification("Exited", "Exited the Location")
                am.setRingerMode(AudioManager.RINGER_MODE_NORMAL) //put ringer to normal
            }
            else -> {
                println("oh cow's eye! something bad happened!")
                Log.e(TAG, "Error ")
            }
        }

    }

    fun showNotification(text: String, bigText: String) {

        // 1. Create a NotificationManager
        val notificationManager = this.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        // 2. Create a PendingIntent for AllGeofencesActivity
        val intent = Intent(this, MainActivity::class.java)
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
        val pendingNotificationIntent = PendingIntent.getActivity(this, 0,
                intent, PendingIntent.FLAG_UPDATE_CURRENT)

        // 3. Create and send a notification
        val notification = NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("Title")
                .setContentText(text)
                .setContentIntent(pendingNotificationIntent)
                .setStyle(NotificationCompat.BigTextStyle().bigText(bigText))
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setAutoCancel(true)
                .build()
        notificationManager.notify(0, notification)
    }

}

地理围栏很少触发,也只有
Exit一个。但是代码在Java中工作完美。这是语言还是实施问题?

非常感谢您的帮助!

解决方案如下:

我认为您的问题是onHandleIntent中的when子句

你基本上有

when (x) {
        A or B -> { ... }
        C -> { ... }
        else -> { ... }
}

我认为
Geofence.GEOFENCE_TRANSITION_ENTER等是
Int类型,因此您最终会使用
infix fun or(other: Int): Int (source) 在它们上调用“按位或”。

我认为您真正想要的是:

when (x) {
        A, B -> { ... }
        C -> { ... }
        else -> { ... }
}