Today's

길을 나서지 않으면 그 길에서 만날 수 있는 사람을 만날 수 없다

모바일 앱(안드로이드)

안드로이드 앱 만들기 : triggeringGeofences 가 뭐지 ( geoFenceing)

Billcorea 2022. 9. 27. 23:41
반응형

지오펜싱 트리거 되는 위치의 명칭 표시 

지오펜스 앱을 수정하면서 또 하나를 찾았습니다.  구현해 보고 싶었던 것은 지오펜싱에서 찾은 위치에 대한 알림을 구현할 때 현재 내가 도착한 위치가 어떤 것 때문에 표시가 되고 있는지 알고 싶다는 것입니다.  물론 잘 아시는 분들은 이미 찾으셨을리라고 생각이 되지만, 이제 구현을 해 가고 있는 분들을 위해서 기억을 남겨 두고자 합니다. 

 


import android.annotation.SuppressLint
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.billcoreatech.ontheway801.MainComposeActivity
import com.billcoreatech.ontheway801.R
import com.google.android.gms.location.Geofence
import com.google.android.gms.location.GeofenceStatusCodes
import com.google.android.gms.location.GeofencingEvent

class GeofenceBroadcastReceiver : BroadcastReceiver() {

    companion object {
        var TAG = "GeofenceBroadcastReceiver"
        internal const val ACTION_GEOFENCE_EVENT =
            "action.ACTION_GEOFENCE_EVENT"
    }


    override fun onReceive(context: Context, intent: Intent) {

        if (intent.action == ACTION_GEOFENCE_EVENT) {
            Log.e(TAG, "onReceive ...")

            val geofencingEvent = GeofencingEvent.fromIntent(intent)
            // Test that the reported transition was of interest.
            if (geofencingEvent != null) {

                if (geofencingEvent.hasError()) {
                    val errorMessage = GeofenceStatusCodes.getStatusCodeString(geofencingEvent.errorCode)
                    Log.e("GeofenceBR", errorMessage)
                    return
                }

                // 트리거된 위치에 대한 정보를 취득해 보기 위해서...
                var geofenceList = geofencingEvent.triggeringGeofences
                var whereString = " "
                if (geofenceList != null) {
                    for (geofence in geofenceList) {
                        Log.e(TAG, "requestId = ${geofence.requestId}")
                        whereString += "${geofence.requestId} "
                    }
                }

                when(val geofenceTransition = geofencingEvent.geofenceTransition) {
                    Geofence.GEOFENCE_TRANSITION_DWELL -> {
                        if (context != null) {
                            sendNotification(context, context.getString(R.string.DWell) + "[${whereString}]")
                        }
                        Log.e(TAG, context.getString(R.string.DWell))
                    }
                    Geofence.GEOFENCE_TRANSITION_ENTER -> {
                        if (context != null) {
                            sendNotification(context, context.getString(R.string.Enter) + "[${whereString}]")
                        }
                        Log.e(TAG, "Entered")
                    }
                    Geofence.GEOFENCE_TRANSITION_EXIT -> {
                        if (context != null) {
                            sendNotification(context, context.getString(R.string.Exit) + "[${whereString}]")
                        }
                        Log.e(TAG, "Exit")
                    }
                    else -> {
                        if (context != null) {
                            sendNotification(context, "Geofence ${geofenceTransition.hashCode()}")
                        }
                        Log.e(TAG, "geofenceTransition = ${geofenceTransition.hashCode()}")
                    }

                }
            } else {
                Log.e(TAG, "geofencingEvent is null...")
            }
        }
    }

    @SuppressLint("MissingPermission")
    private fun sendNotification(context : Context, messageBody: String) {
        val intent = Intent(context, MainComposeActivity::class.java)
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
        val extras = Bundle()
        extras.putString("MSGRCV", messageBody)
        intent.putExtras(extras)
        val pendingIntent = PendingIntent.getActivity(
            context, 0 /* Request code */, intent,
            PendingIntent.FLAG_MUTABLE
        )

        val channelId: String = context.getString(R.string.default_notification_channel_id)
        val channelName: CharSequence = context.getString(R.string.default_notification_channel_name)
        val importance = NotificationManager.IMPORTANCE_DEFAULT
        val notificationChannel = NotificationChannel(channelId, channelName, importance)
        notificationChannel.enableLights(true)
        notificationChannel.lightColor = Color.RED
        notificationChannel.enableVibration(true)
        notificationChannel.vibrationPattern =
            longArrayOf(100, 200, 300, 400, 500, 400, 300, 200, 400)

        val wearNotifyManager = NotificationManagerCompat.from(context)
        val wearNotifyBuilder: NotificationCompat.Builder =
            NotificationCompat.Builder(context, channelId)
                .setSmallIcon(R.drawable.ic_locationnote_foreground)
                .setContentTitle(context.getString(R.string.app_name))
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setContentIntent(pendingIntent)
                .setVibrate(longArrayOf(100, 200, 300, 400, 500, 400, 300, 200, 400))
                .setDefaults(-1)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            wearNotifyManager.createNotificationChannel(notificationChannel)
        }
        wearNotifyManager.notify(0, wearNotifyBuilder.build())
    }
}

 

코드가 구현된 예제 화면

위에 기술된 전체 소스의 내용과 같이 트리거 되는 위치에 대한 정보를 취해서 그곳에 대한 알림을 전달하는 방식으로 내가 지정한 위치에 도달하였을 때 명칭을 표시하는 방법을 구현해 보게 됩니다. 

 

지오펜싱 위치 도달 알림.

 

트리거 명칭 전달 방법

참 저렇게 trigger 되게 하는 부분은 다음과 같이 적용했습니다.   아래처럼 geofenceList.add을 하게 되는 경우 builder을 설정하면서 setRequestId에 넣는 값을 표시하고자 하는 장소의 명칭을 넣었습니다.  그러면 위에 기술된 코드에서는 getRequestId로 값을 가져와 현재 표시되는 위치의 명칭을 보여주는 기능을 구현할 수 있습니다.

 

private fun doAddGeoFence(documents: ResponseBean.Documents) {
    geofenceList.clear()
    geofenceList.add(Geofence.Builder()
        // Set the request ID of the geofence. This is a string to identify this
        // geofence.
        .setRequestId(documents.placeName)

        // Set the circular region of this geofence.
        .setCircularRegion(
            documents.posY,
            documents.posX,
            sp.getFloat("aroundArea", 300f)
        )

        // Set the expiration duration of the geofence. This geofence gets automatically
        // removed after this period of time.
        .setExpirationDuration(sp.getFloat("geofenceTime", 1.0f).toLong() * 60 * 60 * 1000)

        // Set the transition types of interest. Alerts are only generated for these
        // transition. We track entry and exit transitions in this sample.
        .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_EXIT)

        // Create the geofence.
        .build())

    geofencingClient.addGeofences(getGeofencingRequest(), geofencePendingIntent).run {
        addOnSuccessListener {
            Log.e(TAG, "addOnSuccessListener")
            showSnackbar(this@MainComposeActivity,
                R.string.add_geofences,
                R.string.geofences_added,
                View.OnClickListener {
                    var dbHandler = DBHandler.open(this@MainComposeActivity)
                    var geoBean = GeoDataBean(
                        0, documents.placeName, documents.posY, documents.posX, documents.addressName, "Y"
                    )
                    dbHandler.insert(geoBean)
                    dbHandler.close()
                }
            )
        }
        addOnFailureListener {
            // Failed to add geofences
            // ...
            Log.e(TAG, "addOnFailureListener ${it.message}")
        }
    }
}

 

이상으로 구현 예시는 정리를 마치도록 하겠습니다.  이렇게 구현 되는 앱은 다 정리가 되면 playstore에 게시할 예정입니다.   

반응형