admin管理员组

文章数量:1287840

I am facing a problem with the android google activity recognisation service to detect user activity , When I install appplication it work just fine and I get udpate like still ,tilt , on foot , in vehicle , but after some time like 15 /16 hours it just stop to receive any update,

I have add Activity client in foreground service , I have created Broadcast receiver for Activity Recognisation and Transition , And created A work manager to Recreate Actiivty client at Monring 6 AM and after every 30 minutes I am recreating this ,

I am sharing what I have done

(Service, BroadcastReceiver, Manifest included)

    class ActivityRecognitionService : Service() {

    private val examplePreferenceUseCase: ExamplePreferenceUseCase by inject()

    companion object {
        const val DETECTED_ACTIVITY = "DETECTED_ACTIVITY"
        const val PREF_NAME = "example_preferences"
    }

    lateinit var client: ActivityRecognitionClient
    private val channelId = "activity_recognition_channel"
    private val notificationId = 101

    override fun onCreate() {
        super.onCreate()
        AppLogger.log(applicationContext, "ActivityRecognitionService", "Service created, initializing components.")

        client = ActivityRecognition.getClient(this)
        requestForUpdates()
        createNotificationChannel()
        startForeground(notificationId, buildNotification("Detecting activity..."))
        scheduleUploadWorker(applicationContext)
        scheduleActivityRecognitionWorker(applicationContext)
        JobSchedulerHelper.scheduleJob(applicationContext)
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        return START_STICKY
    }

    private fun requestForUpdates() {
        client.requestActivityTransitionUpdates(ActivityTransitionsUtil.getActivityTransitionRequest(), getPendingIntent())
            .addOnSuccessListener {
                AppLogger.log(applicationContext, "ActivityRecognitionService", "Activity transition updates registered successfully.")
            }
            .addOnFailureListener { e ->
                AppLogger.log(applicationContext, "ActivityRecognitionService", "Failed to register activity transition updates: ${e.localizedMessage}")
            }

        client.requestActivityUpdates(0L, getPendingIntent())
            .addOnSuccessListener {
                AppLogger.log(applicationContext, "ActivityRecognitionService", "Activity updates registered successfully.")
            }
            .addOnFailureListener { e ->
                AppLogger.log(applicationContext, "ActivityRecognitionService", "Failed to register activity updates: ${e.localizedMessage}")
            }
    }

    private fun getPendingIntent(): PendingIntent {
        val intent = Intent(this, ActivityTransitionReceiver::class.java)
        return PendingIntent.getBroadcast(this, 123, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
    }

    private fun createNotificationChannel() {
        val channel = NotificationChannel(channelId, "Activity Recognition", NotificationManager.IMPORTANCE_HIGH)
        val manager = getSystemService(NotificationManager::class.java)
        manager.createNotificationChannel(channel)
    }

    private fun buildNotification(content: String): Notification {
        return NotificationCompat.Builder(this, channelId)
            .setContentTitle("Activity Recognition Service")
            .setContentText(content)
            .setSmallIcon(android.R.drawable.ic_dialog_info)
            .build()
    }

    private fun updateNotification(content: String) {
        val notification = buildNotification(content)
        val manager = getSystemService(NotificationManager::class.java)
        manager.notify(notificationId, notification)
    }

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

    fun scheduleUploadWorker(context: Context) {
        val constraints = Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build()

        val time = examplePreferenceUseCase.getSyncAllTripDataInterval().toLong()
        val uploadRequest = PeriodicWorkRequestBuilder<UploadWorker>(time, TimeUnit.MINUTES)
            .setConstraints(constraints)
            .build()

        WorkManager.getInstance(context).enqueueUniquePeriodicWork(
            "UploadWorker",
            ExistingPeriodicWorkPolicy.KEEP,
            uploadRequest
        )

        AppLogger.log(context, "ActivityRecognitionService", "UploadWorker scheduled every $time minutes.")
    }

    fun scheduleActivityRecognitionWorker(context: Context) {
        val workManager = WorkManager.getInstance(context)

        val now = Calendar.getInstance()
        val scheduledTime = Calendar.getInstance().apply {
            set(Calendar.HOUR_OF_DAY, 6)
            set(Calendar.MINUTE, 0)
            set(Calendar.SECOND, 0)
            if (before(now)) {
                add(Calendar.DAY_OF_MONTH, 1)
            }
        }

        val initialDelay = scheduledTime.timeInMillis - now.timeInMillis

        val oneTimeWorkRequest = OneTimeWorkRequestBuilder<ActivityRecognitionWorker>()
            .setInitialDelay(initialDelay, TimeUnit.MILLISECONDS)
            .build()

        workManager.enqueueUniqueWork(
            "TripCheckWorker_6AM",
            ExistingWorkPolicy.REPLACE,
            oneTimeWorkRequest
        )

        AppLogger.log(context, "WorkManagerScheduler", "First worker scheduled at 6 AM.")

        val periodicWorkRequest = PeriodicWorkRequestBuilder<ActivityRecognitionWorker>(30, TimeUnit.MINUTES)
            .setConstraints(
                Constraints.Builder()
                    .setRequiredNetworkType(NetworkType.NOT_REQUIRED)
                    .build()
            )
            .build()

        workManager.enqueueUniquePeriodicWork(
            "TripCheckWorker_8HourCycle",
            ExistingPeriodicWorkPolicy.KEEP,
            periodicWorkRequest
        )

        AppLogger.log(context, "WorkManagerScheduler", "Repeating worker scheduled every 8 hours.")
    }

    override fun onDestroy() {
        AppLogger.log(applicationContext, "ActivityRecognitionService", "Service destroyed.")
        super.onDestroy()
    }
}

    class ActivityTransitionReceiver : BroadcastReceiver() {

    companion object {
        private const val ACTIVITY_TRANSITION_NOTIFICATION_ID = 111
        private const val CHANNEL_ID = "activity_transition_channel"
    }

    override fun onReceive(context: Context, intent: Intent) {
        AppLogger.log(context, "ActivityTransitionReceiver", "onReceive triggered")

        if (ActivityRecognitionResult.hasResult(intent)) {
            val result = ActivityRecognitionResult.extractResult(intent) ?: return
            val detectedActivity = result.mostProbableActivity

            AppLogger.log(
                context, "ActivityRecognition", 
                "Detected activity: ${ActivityTransitionsUtil.toActivityString(detectedActivity.type)}"
            )

            ExamplePreferenceManager.setLastUpdateTime()
            handleDetectedActivity(context, detectedActivity.type, "ActivityRecognition")
        } else if (ActivityTransitionResult.hasResult(intent)) {
            val transitionResult = ActivityTransitionResult.extractResult(intent) ?: return

            for (event in transitionResult.transitionEvents) {
                AppLogger.log(
                    context, "ActivityTransition", 
                    "Transition detected: ${ActivityTransitionsUtil.toActivityString(event.activityType)}"
                )

                ExamplePreferenceManager.setLastUpdateTime()
                handleDetectedActivity(context, event.activityType, "ActivityTransition")
            }
        }
    }

    private fun handleDetectedActivity(context: Context, activityType: Int, tripSource: String) {
        AppLogger.log(
            context, "ActivityHandling", 
            "Handling activity type: ${ActivityTransitionsUtil.toActivityString(activityType)} from: $tripSource"
        )

        when (activityType) {
            DetectedActivity.IN_VEHICLE -> {
                if (!ExamplePreferenceManager.isTripOngoing()) {
                    startLocationTracking(context, tripSource)
                    showNotification(context, activityType, tripSource)
                }
            }
            else -> {
                stopLocationTracking(context)
                showNotification(context, activityType, tripSource)
            }
        }
    }

    private fun startLocationTracking(context: Context, tripSource: String) {
        val serviceIntent = Intent(context, LocationUpdateService::class.java).apply {
            action = LocationUpdateService.START_TRACKING
            putExtra("tripSource", tripSource)
        }
        context.startForegroundService(serviceIntent)
    }

    private fun stopLocationTracking(context: Context) {
        val serviceIntent = Intent(context, LocationUpdateService::class.java).apply {
            action = LocationUpdateService.STOP_TRACKING
        }
        context.startForegroundService(serviceIntent)
    }

    private fun showNotification(context: Context, activityType: Int, from: String) {
        val notificationManager =
            context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        val channel = NotificationChannel(
            CHANNEL_ID,
            "Activity Recognition Notifications",
            NotificationManager.IMPORTANCE_HIGH
        ).apply {
            description = "Notifications for activity recognition"
        }
        notificationManager.createNotificationChannel(channel)

        val activityName = ActivityTransitionsUtil.toActivityString(activityType)

        val notification = NotificationCompat.Builder(context, CHANNEL_ID)
            .setSmallIcon(android.R.drawable.ic_dialog_info)
            .setContentTitle("Activity Detected")
            .setContentText("Detected: $activityName from: $from")
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setAutoCancel(true)
            .build()

        notificationManager.notify(ACTIVITY_TRANSITION_NOTIFICATION_ID, notification)
    }
}

     <receiver
            android:name=".gpstracking.receiver.ActivityTransitionReceiver"
            android:exported="true"
            android:permission="com.google.android.gms.permission.ACTIVITY_RECOGNITION">
            <intent-filter>
                <action android:name="com.example.driver.ACTIVITY_RESULT" />
            </intent-filter>
        </receiver>
    <service
            android:name=".gpstracking.service.ActivityRecognitionService"
            android:enabled="true"
            android:exported="false"
            android:foregroundServiceType="location" />

本文标签: