Background current location update

40 views Asked by At

I have a question is that possible to fetch current location every time the broacastreceiver makes a new OneTimeWorker? inside the worker? in my fragment i have a buttion in which triggers a pending Intent into my broadcast receiver. inside my broadcast receiver i'm making a OneTimeWorker as such:

class AlarmManagerReceiver : BroadcastReceiver() {


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




        val constraints = Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build()


        val workRequest = OneTimeWorkRequestBuilder<WeatherWorker>()
            .addTag("OneTimeJobNew") // Add a tag if needed
            .setConstraints(constraints)
            .build()

        WorkManager.getInstance(context!!).enqueue(workRequest)
    }

inside my WeatherWorker Class

@HiltWorker
class WeatherWorker @AssistedInject constructor(
    @Assisted appContext: Context,
    @Assisted workerParams: WorkerParameters,
    private val repository: WeatherRepository,
    private val fusedLocationClient: FusedLocationProviderClient
) : CoroutineWorker(appContext, workerParams) {

    override suspend fun doWork(): Result {

            return try {
                // Check for permission explicitly before accessing location
                if (ActivityCompat.checkSelfPermission(
                        applicationContext,
                        Manifest.permission.ACCESS_BACKGROUND_LOCATION
                    ) == PackageManager.PERMISSION_GRANTED
                ) {
                    var nextDayWeather :Any = Any()
                     //Permission is granted, proceed to fetch location
                    val locationResult = fusedLocationClient.lastLocation
                    val taskResult = Tasks.await(locationResult)
                    val lat = taskResult.latitude
                    val long = taskResult.longitude
                    val result = repository.fetchWeather("$lat,$long")
                   
                    if (result.status is Success) {
                        val currentDate = Calendar.getInstance()

                        // Add 1 day to the current date
                        currentDate.add(Calendar.DAY_OF_YEAR, 1)
                        val nextDate = currentDate.time

                        // Format and print the next date
                        val dateFormat = SimpleDateFormat("yyyy-MM-dd")
                        var nextDateStr = dateFormat.format(nextDate)
                        val forecastDayResult = result.status.data!!.forecast.forecastday
                        for (dayWeek in forecastDayResult){
                            if(dayWeek.date.contains(nextDateStr)){
                                nextDayWeather = dayWeek
                                break
                            }
                        }

                        if(nextDayWeather is forecastday){
                            AppUtils.notify(applicationContext,"Tomorrow's Weather","Weather Status: " + "${nextDayWeather.day.condition.text} " +
                                    " Average Temperature: " + "${nextDayWeather.day.avgtemp_c.toInt()}",
                                R.mipmap.ic_launcher_weather_round)
                        }


                        val intent = Intent(applicationContext, AlarmManagerReceiver::class.java)
                        val pendingIntent = PendingIntent.getBroadcast(
                            applicationContext,
                            1,
                            intent,
                            PendingIntent.FLAG_IMMUTABLE
                        )
                        val alarmManager =
                            applicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager

                        val calendar = Calendar.getInstance()
                        calendar.timeInMillis = System.currentTimeMillis()
                        calendar.add(Calendar.HOUR, 2)


                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                            val canScheduleExactAlarms = alarmManager.canScheduleExactAlarms()
                            if (!canScheduleExactAlarms) {
                                // Handle the case where exact alarms cannot be scheduled
                                // You can fallback to approximate alarms or handle it gracefully
                            }
                        }

                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            alarmManager.setExactAndAllowWhileIdle(
                                AlarmManager.RTC_WAKEUP,
                                calendar.timeInMillis,
                                pendingIntent
                            )
                        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                            alarmManager.setExact(
                                AlarmManager.RTC_WAKEUP,
                                calendar.timeInMillis,
                                pendingIntent
                            )
                        } else {
                            alarmManager.set(
                                AlarmManager.RTC_WAKEUP,
                                calendar.timeInMillis,
                                pendingIntent
                            )
                        }
                        Result.success()
                    } else {
                        Result.failure()
                    }
                } else {
                    // Permission is not granted
                    AppUtils.notify(applicationContext,"Error","Please select allow all the time from settings.")
                    Result.failure()
                }
            }
            catch (e: Exception) {
                Result.failure()
            }

        }

}

For some reason after two hours nothing really happens at all... The next pending intent seem not to fire at all what could be the error ?

in my manifest :

<uses-permission android:name="android.permission.INTERNET"/>

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
    <!-- or -->
    <uses-permission android:name="android.permission.USE_EXACT_ALARM" />

    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

Couldn't find any solution as for android 14... I know there are Restrictions on the amount of requests on the background for the current location but im sending a pending intent every 2 hours.

1

There are 1 answers

2
Gabe Sechan On

Why are you using a OneTimeWorker to set an alarm? Use a PeriodicWorkRequest, and the worker replaces your alarm. You would never use those two concepts together, you use AlarmManager OR WorkManager, not both