当应用程序处于后台时,Firebase FCM 不会受到影响。我想在 MessageReceived 上运行后台服务以进行位置更新

问题描述 投票:0回答:2

我想在后台启动位置更新服务,我想要实现的是,当用户在

onMessageReceived(remoteMessage: RemoteMessage)
中收到来自 firebase FCM 的通知时启动该服务,当应用程序位于前台时,onMessageReceived 启动服务,但是当应用程序被终止或不在前台位置未更新或服务未在后台运行。当应用程序处于后台或处于终止状态时,在后台获取用户位置的正确方法是什么

<--- Firebase 消息传递 --->

@AndroidEntryPoint
class MyFirebaseMessagingService : FirebaseMessagingService() {
    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        super.onMessageReceived(remoteMessage)

    if (remoteMessage.data.isNotEmpty()) {
        Log.d("FirebaseLogs", "Remote message data: ${remoteMessage.data}")
        Intent(this, LocationBackgroundService::class.java).also { intent ->
            intent.action = LocationBackgroundService.ACTION_START
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                startForegroundService(intent)
            } else {
                startService(intent)
            }
        }
    } else {
        Log.d("FirebaseLogs", "Remote message data is empty")
    }

}

override fun onNewToken(token: String) {
    super.onNewToken(token)
    SharedPrefDataStore.init().setValue(this, FCM_TOKEN, token)
}

}

<--- This is my service class --->

@AndroidEntryPoint
class LocationBackgroundService : Service() {

private val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
private lateinit var locationClient: LocationClient
private lateinit var db: FirebaseFirestore

override fun onBind(intent: Intent?): IBinder? {
    return null
}

override fun onCreate() {
    super.onCreate()
    db = FirebaseFirestore.getInstance()
    locationClient = DefaultLocationClient(
        applicationContext,
        LocationServices.getFusedLocationProviderClient(applicationContext)
    )
    createNotificationChannel()
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    when(intent?.action){
        ACTION_START -> start()
        ACTION_STOP -> stop()
    }
    //return START_STICKY
    return super.onStartCommand(intent, flags, startId)
}

private fun start() {

    val pendingIntent: PendingIntent =
        Intent(this, MainActivity::class.java).let { notificationIntent ->
            PendingIntent.getActivity(
                this, 0, notificationIntent,
                PendingIntent.FLAG_IMMUTABLE
            )
        }

    val notification = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
        .setContentTitle("Tracking location...")
        .setContentText("")
        .setSmallIcon(R.drawable.we_care_small)
        .setOngoing(true)

    val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

    locationClient
        .getLocationUpdates(10000L)
        .catch { e -> e.printStackTrace() }
        .onEach { location ->
            val lat = location.latitude.toString()
            val long = location.longitude.toString()
            val geoPoint = GeoPoint(location.latitude, location.longitude)

            saveUserLocation(geoPoint)
            val updatedNotification = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                .setContentTitle("Tracking location...")
                .setContentText("Location: ($lat, $long)")
                .setSmallIcon(R.drawable.we_care_small)
                .setContentIntent(pendingIntent)
                .setOngoing(true)
                .build()
            notificationManager.notify(1, updatedNotification)
        }
        .launchIn(serviceScope)

    startForeground(1, notification.build())
}

private fun createNotificationChannel() {
    val channel = NotificationChannel(
        NOTIFICATION_CHANNEL_ID,
        NOTIFICATION_CHANNEL_NAME,
        NotificationManager.IMPORTANCE_DEFAULT
    ).apply {
        description = "Channel for location service"
    }
    val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    manager.createNotificationChannel(channel)
}

private fun stop() {
    stopForeground(true)
    stopSelf()
}

override fun onDestroy() {
    super.onDestroy()
    serviceScope.cancel()
}

private fun saveUserLocation(geoPoint: GeoPoint) {
     db.collection(USER_LOCATION)
        .document(Firebase.auth.currentUser?.uid.toString())
        .update("geo_location", geoPoint)
        .addOnCompleteListener {
            Log.d(TAG, "Save UserLocation from Service :: " + it.isSuccessful)
        }
        .addOnFailureListener {
            Log.d(TAG, "Fail to save UserLocation :: " + it.message)
        }
}

companion object {
    const val ACTION_START = "ACTION_START"
    const val ACTION_STOP = "ACTION_STOP"
}

}

<--- Manifest --->

<service
        android:name=".service.LocationBackgroundService"
        android:enabled="true"
        android:foregroundServiceType="location"
        android:exported="false"
        tools:ignore="ForegroundServicePermission" />
android firebase kotlin firebase-cloud-messaging
2个回答
0
投票

这里有一个旧的官方存储库,它应该可以满足您的需要,但请记住,该存储库已被存档并被使用不同方法的新版本(链接存储库中的详细信息)取代。


0
投票

var message = { "registration_ids": [ fcmToken ], "webpush": { "headers": { "Urgency": "high" } }, "android": { "priority": "high" }, "priority": 10

}

© www.soinside.com 2019 - 2024. All rights reserved.