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
}
}