3

I have need to retrieve android device coordinates from android application and send these coordinates to sever even when the application is stopped and/or the device is asleep. I need to do this in fixed time intervals.

I clearly understand that this is complex solution, but could you please mention key aspects, that are needed to solve this problem? I need a direction to choose in the process of developing the application.

I have made extensive research on the web, there are many solutions but some of them seem to be several years old and others tend to solve particular problems in different ways. Its Impossible to try them all and from all this information compose the solution that will answer my needs and will be optimal and stable solution.

Thank you

Tornike Shavishvili
  • 1,244
  • 4
  • 16
  • 35

1 Answers1

2

I had the same problem and this solution worked for me:

Define a worker like below:

class SendLocationWorker(
  context: Context,
  workerParams: WorkerParameters
) : Worker(context, workerParams) {
  private var retrofit: Retrofit? = null
  private var locationApi: MyApi? = null
  private val userLocationDao = AppDatabase.getInstance(applicationContext)
      .userLocationDao()

  override fun doWork(): Result {
    return try {
      if (retrofit == null) {
        retrofit = MasterRetrofit().initRetrofit(Constants.MAIN_URL)
      }
      if (locationApi == null) {
        locationApi = retrofit!!.create(MyApi::class.java)
      }
      callApi()
      Result.success()
    } catch (ex: Exception) {
      Result.failure()
    }
  }

  @SuppressLint("CheckResult")
  private fun callApi() {
    val locations = getUserLocations()
    if (locations.isNotEmpty()) {
      val request = InsertLocationUserRequest()
      request.saveTrackings = locations

      locationApi!!.SaveTracking(request)
          .subscribeOn(Schedulers.io())
          .observeOn(AndroidSchedulers.mainThread())
          .map(SuccessMapper<Response<InsertLocationUserResponse>>())
          .subscribe(
              { response ->
                if (response.body()!!.success) {
                  Observable.fromIterable(locations)
                      .forEach { location -> location.isSync = true }
                  userLocationDao.update(locations)
                }
              },
              { throwable ->

              },
              {
              }
          )
    }
  }

  private fun getUserLocations(): List<UserLocation> {
    return userLocationDao.findAll("isSync", "0")
  }
}

Also, you need to define a method in MasterActivity or MasterPresenter like this:

  @Override public void sendStoredLocationToServer() {
    Constraints myConstraints = new Constraints.Builder()
        .setRequiresBatteryNotLow(true)
        .build();

    PeriodicWorkRequest sendLocationWorkerRequest =
        new PeriodicWorkRequest.Builder(SendLocationWorker.class, 10000, TimeUnit.MILLISECONDS)
            .setConstraints(myConstraints)
            .build();

    WorkManager.getInstance().enqueueUniquePeriodicWork("sendLocationWorker",
        ExistingPeriodicWorkPolicy.REPLACE,
        sendLocationWorkerRequest);
  }

Then you can call your worker in your MasterActivity or MasterPresenter everywhere you want like this:

sendStoredLocationToServer();

This worker will save your locations in the database and send them if it is possible and mark all send items as true (using isSyns flag).

This idea worked well for me.

Amin Pinjari
  • 2,129
  • 3
  • 25
  • 53
majid ghafouri
  • 787
  • 2
  • 7
  • 23
  • 1
    Thank you for the answer. I am curios, as i understand this code will get stopped when application is stopped or device goes to sleep, am i right? – Tornike Shavishvili Oct 07 '19 at 10:43
  • 2
    Of course it is. I handle it by a service. Notice that in android 8 or above you need an alarm manager to restart the service if needed. @TornikeShavishvili – majid ghafouri Oct 07 '19 at 11:00
  • Do you approve my earlier comment? If it is ok, please check my answer as true. thanks. @TornikeShavishvili – majid ghafouri Oct 07 '19 at 11:26
  • I will certainly accept your answer. But I want to have full picture before me. Web got me confused regarding running service in android even when app is closed (not running) or device goes to sleep. Maybe you could share your experience regarding this crucial issue? Thanks – Tornike Shavishvili Oct 07 '19 at 11:33
  • 1
    It is a little bit hard to share all experiences, but this post helped me before, and I hope it will help you: https://stackoverflow.com/questions/30525784/android-keep-service-running-when-app-is-killed – majid ghafouri Oct 07 '19 at 12:12