请查看以下文件以获取解决方案
在 Android 11 中的清单文件中添加 Google 地图 API 密钥和后台位置权限。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.recycler.geofencingdemo">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".GeofenceRegistrationService"
android:enabled="true"
android:exported="true"/>
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_map_key" />
</application>
</manifest>
GeofenceRegistrationService.kt
package com.recycler.geofencingdemo
import android.app.*
import android.content.Context
import android.content.Intent
import android.os.Build
import android.text.TextUtils
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.app.TaskStackBuilder
import com.google.android.gms.location.Geofence
import com.google.android.gms.location.GeofenceStatusCodes
import com.google.android.gms.location.GeofencingEvent
import com.google.android.gms.maps.model.LatLng
import java.util.*
class GeofenceRegistrationService : IntentService(TAG) {
override fun onHandleIntent(intent: Intent?) {
val geofencingEvent = GeofencingEvent.fromIntent(intent)
if (geofencingEvent.hasError()) {
Log.d(TAG, "GeofencingEvent error " + geofencingEvent.errorCode)
} else {
val transaction = geofencingEvent.geofenceTransition
val geofences = geofencingEvent.triggeringGeofences
val geofence = geofences[0]
if (transaction == Geofence.GEOFENCE_TRANSITION_ENTER && geofence.requestId == Constants.GEOFENCE_ID) {
Log.d(TAG, "You are inside Tacme")
} else {
Log.d(TAG, "You are outside Tacme")
}
val geofenceTransitionDetails = getGeofenceTrasitionDetails(transaction, geofences)
Constants.AREA_LANDMARKS[Constants.GEOFENCE_ID]?.let { sendNotification(applicationContext,geofenceTransitionDetails, it) }
}
}
private fun getGeofenceTrasitionDetails(geoFenceTransition: Int, triggeringGeofences: List<Geofence>): String {
val triggeringGeofencesList = ArrayList<String?>()
for (geofence in triggeringGeofences) {
triggeringGeofencesList.add(geofence.requestId)
}
var status: String? = null
if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER) status = "Entering " else if (geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) status = "Exiting "
return status + TextUtils.join(", ", triggeringGeofencesList)
}
fun sendNotification(context: Context, message: String, latLng: LatLng) {
val notificationManager = context
.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
&& notificationManager.getNotificationChannel(Companion.NOTIFICATION_CHANNEL_ID) == null) {
val name = context.getString(R.string.app_name)
val channel = NotificationChannel(Companion.NOTIFICATION_CHANNEL_ID,
name,
NotificationManager.IMPORTANCE_DEFAULT)
notificationManager.createNotificationChannel(channel)
}
val intent = MainActivity.newIntent(context.applicationContext, latLng)
val stackBuilder = TaskStackBuilder.create(context)
.addParentStack(MainActivity::class.java)
.addNextIntent(intent)
val notificationPendingIntent = stackBuilder
.getPendingIntent(getUniqueId(), PendingIntent.FLAG_UPDATE_CURRENT)
val notification = NotificationCompat.Builder(context, Companion.NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(message)
.setContentIntent(notificationPendingIntent)
.setAutoCancel(true)
.build()
notificationManager.notify(getUniqueId(), notification)
}
private fun getUniqueId() = ((System.currentTimeMillis() % 10000).toInt())
companion object {
private const val TAG = "GeoIntentService"
private fun getErrorString(errorCode: Int): String {
return when (errorCode) {
GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE -> "GeoFence not available"
GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES -> "Too many GeoFences"
GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS -> "Too many pending intents"
else -> "Unknown error."
}
}
private const val NOTIFICATION_CHANNEL_ID = BuildConfig.APPLICATION_ID + ".channel"
}
}
Constants.kt
package com.recycler.geofencingdemo
import com.google.android.gms.maps.model.LatLng
import java.util.*
object Constants {
const val GEOFENCE_ID = "TACME"
const val GEOFENCE_RADIUS_IN_METERS = 100f
val AREA_LANDMARKS = HashMap<String, LatLng>()
init {
AREA_LANDMARKS[GEOFENCE_ID] = LatLng(48.8603, 2.2914)
}
}