0

So I'm using Worker Manger to open my app on the background, collect data from google fit and send it to server.

  • I tried calling api inside my worker and it works well.
  • then I tried to connect to google fit and collect data and it worked well as well.

but when I tried to combine the 2 points together it didn't work . it always throws android.os.NetworkOnMainThreadException with null message

can anyone give me a reason why this is happening?

here is my code

class TrackWorker(context: Context, params: WorkerParameters) : Worker(context, params), GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

@Inject
lateinit var useCase: TrackUseCase
val TAG: String = TrackWorker::class.java.simpleName
private var client: GoogleApiClient? = null
private var totalSteps: Int = 0
private var totalDistance: Float = 0f


override fun onConnectionFailed(p0: ConnectionResult) {
    Log.d(TAG, "Failed")
}

override fun onConnected(p0: Bundle?) {
    val ESTIMATED_STEP_DELTAS = DataSource.Builder()
            .setAppPackageName("com.google.android.gms")
            .setDataType(DataType.TYPE_STEP_COUNT_DELTA)
            .setType(DataSource.TYPE_DERIVED)
            .setStreamName("estimated_steps")
            .build()
    val readRequest = DataReadRequest.Builder()
            .aggregate(ESTIMATED_STEP_DELTAS, DataType.AGGREGATE_STEP_COUNT_DELTA)
            .aggregate(DataType.TYPE_DISTANCE_DELTA, DataType.AGGREGATE_DISTANCE_DELTA)
            .aggregate(DataType.TYPE_CALORIES_EXPENDED, DataType.AGGREGATE_CALORIES_EXPENDED)
            .aggregate(DataType.TYPE_ACTIVITY_SEGMENT, DataType.AGGREGATE_ACTIVITY_SUMMARY)
            .bucketByTime(1, TimeUnit.DAYS)
            .setTimeRange(CalendarUtil.getFirstDayOfWeek(), CalendarUtil.getNow(), TimeUnit.MILLISECONDS)
            .build()


    val result = Fitness.HistoryApi.readData(client, readRequest)
    val totalResult = result.setResultCallback { it ->

        if (it.status.isSuccess) {
            val buckets = it.buckets
            for (bucket in buckets) {
                val dataSets = bucket.dataSets

                for (dataSet in dataSets) {
                    if (dataSet.dataType.name == "com.google.step_count.delta") {
                        for (dp in dataSet.dataPoints) {
                            for (field in dp.dataType.fields) {
                                val steps = dp.getValue(field).asInt()
                                totalSteps += steps
                            }
                        }
                    }
                }

                for (dataSet in dataSets) {
                    if (dataSet.dataType.name == "com.google.distance.delta") {
                        for (dp in dataSet.dataPoints) {
                            for (field in dp.dataType.fields) {
                                val distance = dp.getValue(field).asFloat()
                                totalDistance += distance
                            }
                        }
                    }
                }
            }

        } else {
            Log.e(TAG, "There was a problem getting the step count")
        }

        if (totalSteps != 0 && totalDistance != 0f) {
            val jsonArray = JsonArray()
            val trackBodyJSON = JsonObject()


            trackBodyJSON.addProperty("trackDate", CalendarUtil.getCurrentDate())
            trackBodyJSON.addProperty("walksteps", totalSteps)
            trackBodyJSON.addProperty("walkkm", totalDistance)
            jsonArray.add(trackBodyJSON)


            useCase.execute(TrackUseCase.Request(jsonArray))
                    .subscribe({
                        Log.d(TAG, "it's here $it")
                    }, {
                        Log.d(TAG, "errorrrr ${it}")
                        when (it) {
                            is ApiException ->
                                Log.d(TAG, "API ERROR ? ${it.apiErrorResponse.message}")
                            is TimeoutConnectionException -> {
                                Log.d(TAG, "API ERROR ? Timeout")
                            }
                            else -> {
                                Log.d(TAG, "error ${it.localizedMessage}")
                            }
                        }
                    })


        }
    }


}

override fun onConnectionSuspended(p0: Int) {
    Log.d(TAG, "SUSSPENDED")
}


override fun doWork(): Result {
    (applicationContext as WalkAndTalkApp).component().inject(this)

    if (client == null) {
        client = GoogleApiClient.Builder(applicationContext)
                .addApi(Fitness.RECORDING_API)
                .addApi(Fitness.HISTORY_API)
                .addScope(Scope(Scopes.FITNESS_LOCATION_READ))
                .addScope(Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build()

        if (!client!!.isConnected)
            client!!.connect()
    }


    return Result.SUCCESS
}

}

I tried using chaining worker managers, but the second worker gets executed before the first one connecting to the google fit sdk and getting data

below is the code

 private var totalSteps: Int = 0
private var totalDistance: Float = 0f
val TAG: String = "DAILYTRAKWORKER"

class ConnectWorker(context: Context, params: WorkerParameters) : Worker(context, params), GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

    private var client: GoogleApiClient? = null



    override fun onConnectionFailed(p0: ConnectionResult) {
        Log.d(TAG, "Failed")
    }

    override fun onConnected(p0: Bundle?) {
        Log.d(TAG, "CONNNNECTED")

        val ESTIMATED_STEP_DELTAS = DataSource.Builder()
                .setAppPackageName("com.google.android.gms")
                .setDataType(DataType.TYPE_STEP_COUNT_DELTA)
                .setType(DataSource.TYPE_DERIVED)
                .setStreamName("estimated_steps")
                .build()
        val readRequest = DataReadRequest.Builder()
                .aggregate(ESTIMATED_STEP_DELTAS, DataType.AGGREGATE_STEP_COUNT_DELTA)
                .aggregate(DataType.TYPE_DISTANCE_DELTA, DataType.AGGREGATE_DISTANCE_DELTA)
                .aggregate(DataType.TYPE_CALORIES_EXPENDED, DataType.AGGREGATE_CALORIES_EXPENDED)
                .aggregate(DataType.TYPE_ACTIVITY_SEGMENT, DataType.AGGREGATE_ACTIVITY_SUMMARY)
                .bucketByTime(1, TimeUnit.DAYS)
                .setTimeRange(CalendarUtil.getFirstDayOfWeek(), CalendarUtil.getNow(), TimeUnit.MILLISECONDS)
                .build()


        val result = Fitness.HistoryApi.readData(client, readRequest)
        result.setResultCallback { it ->

            if (it.status.isSuccess) {
                val buckets = it.buckets
                for (bucket in buckets) {
                    val dataSets = bucket.dataSets
                    for (dataSet in dataSets) {
                        if (dataSet.dataType.name == "com.google.step_count.delta") {
                            for (dp in dataSet.dataPoints) {
                                for (field in dp.dataType.fields) {
                                    val steps = dp.getValue(field).asInt()
                                    totalSteps += steps
                                    Log.d(TAG, "steps: $steps")
                                }
                            }
                        }
                    }

                    for (dataSet in dataSets) {
                        if (dataSet.dataType.name == "com.google.distance.delta") {
                            for (dp in dataSet.dataPoints) {
                                for (field in dp.dataType.fields) {
                                    val distance = dp.getValue(field).asFloat()
                                    Log.d(TAG, "distance: " + distance / 1000)
                                    totalDistance += distance
                                }
                            }
                        }
                    }
                }

            } else {
                Log.e(TAG, "There was a problem getting the step count")
            }

        }


    }

    override fun onConnectionSuspended(p0: Int) {
        Log.d(TAG, "SUSSPENDED")
    }

    override fun doWork(): Result {

        if (client == null) {
            client = GoogleApiClient.Builder(applicationContext)
                    .addApi(Fitness.RECORDING_API)
                    .addApi(Fitness.HISTORY_API)
                    .addScope(Scope(Scopes.FITNESS_LOCATION_READ))
                    .addScope(Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build()

            if (!client!!.isConnected)
                client!!.connect()
        }
        return Result.SUCCESS
    }


}

class TrackWorker(context: Context, params: WorkerParameters) : Worker(context, params) {


    @Inject
    lateinit var useCase: TrackUseCase


    override fun doWork(): Result {
        (applicationContext as WalkAndTalkApp).component().inject(this)
        Log.i(TAG, "trackworker:$totalSteps ")

        if (totalSteps != 0 && totalDistance != 0f) {
            val jsonArray = JsonArray()
            val trackBodyJSON = JsonObject()
            Log.i(TAG, "Total steps:$totalSteps ")
            Log.i(TAG, "Total Distance:$totalDistance ")
            Log.d(TAG, "CURRENT DATE ${CalendarUtil.getCurrentDate()}")

            trackBodyJSON.addProperty("trackDate", CalendarUtil.getCurrentDate())
            trackBodyJSON.addProperty("walksteps", totalSteps)
            trackBodyJSON.addProperty("walkkm", totalDistance)
            jsonArray.add(trackBodyJSON)


            Log.d(TAG, "LIST --->   $jsonArray")

            useCase.execute(TrackUseCase.Request(jsonArray))
                    .subscribe({
                        Log.d(TAG, "it's here $it")
                    }, {
                        Log.d(TAG, "errorrrr ${it}")
                        when (it) {
                            is ApiException ->
                                Log.d(TAG, "API ERROR ?       ${it.apiErrorResponse.message}")
                            is TimeoutConnectionException -> {
                                Log.d(TAG, "API ERROR ? Timeout")
                            }

                            else -> {
                                Log.d(TAG, "error ${it.localizedMessage}")
                            }
                        }
                    })
        }

        return Result.SUCCESS
    }


}
Rawan
  • 1
  • 3
  • Possible duplicate of [Android HttpClient : NetworkOnMainThreadException](https://stackoverflow.com/questions/11736530/android-httpclient-networkonmainthreadexception) – O.O.Balance Oct 15 '18 at 07:24
  • How are you chaining the two workers? WorkManager's codelab has some sample on how to do it: https://codelabs.developers.google.com/codelabs/android-workmanager/#5 – pfmaggi Oct 15 '18 at 11:10

0 Answers0