In my app I am using ReactiveLocationProvider library (link). I subscribe for updates in the onCreate method. It works fine when the device is online but if I switch my wifi off and wait for the next background location updates the device OnErrorNotImplementedException. This is the log:
12-30 00:05:44.711 12237-12237/koemdzhiev.com.stormy E/AndroidRuntime: FATAL EXCEPTION: main
Process: koemdzhiev.com.stormy, PID: 12237
java.lang.IllegalStateException: Exception thrown on Scheduler.Worker thread. Add `onError` handling.
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:60)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
Caused by: rx.exceptions.OnErrorNotImplementedException: Timed out waiting for response from server
at rx.Observable$27.onError(Observable.java:7535)
at rx.observers.SafeSubscriber._onError(SafeSubscriber.java:154)
at rx.observers.SafeSubscriber.onError(SafeSubscriber.java:111)
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.pollQueue(OperatorObserveOn.java:197)
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber$2.call(OperatorObserveOn.java:170)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
Caused by: java.io.IOException: Timed out waiting for response from server
at android.location.Geocoder.getFromLocation(Geocoder.java:136)
at pl.charmas.android.reactivelocation.observables.geocode.ReverseGeocodeObservable.call(ReverseGeocodeObservable.java:34)
at pl.charmas.android.reactivelocation.observables.geocode.ReverseGeocodeObservable.call(ReverseGeocodeObservable.java:13)
at rx.Observable.unsafeSubscribe(Observable.java:7710)
at rx.internal.operators.OperatorSubscribeOn$1$1.call(OperatorSubscribeOn.java:62)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
MainActivity code:
public class MainActivity extends AppCompatActivity {
ReactiveLocationProvider locationProvider;
Observable<List<Address>> reverseGeocodeObservable;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//-----------MY CODE STARTS HERE-----------------
//check if the user previously has seen the whats new message...
sharedPref = getPreferences(Context.MODE_PRIVATE);
editor = sharedPref.edit();
if (sharedPref.getInt(getString(R.string.saved_if_whats_new_seen), 1) != 0){
WhatsNewDialogCreator dialogCreator = new WhatsNewDialogCreator(this, sharedPref);
dialogCreator.show();
}
request = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY)
.setSmallestDisplacement(0)
.setFastestInterval(1 * 60 * 1000)
.setInterval(60 * 60 * 1000);
locationProvider = new ReactiveLocationProvider(this);
//subscribe for background location updates...
if(isNetworkAvailable()) {
startBackgroundUpdates();
}
if(isFirstTimeLaunchingTheApp) {
Log.d(TAG, "onCreate getLocation");
getLocation();
}
}
private void startBackgroundUpdates() {
subscription = locationProvider.getUpdatedLocation(request)
.subscribe(new Action1<Location>() {
@Override
public void call(Location location) {
Log.d(TAG, "Getting Background updates...");
MainActivity.this.latitude = location.getLatitude();
MainActivity.this.longitude = location.getLongitude();
numOfBackgroundUpdates++;
reverseGeocodeObservable = locationProvider
.getReverseGeocodeObservable(location.getLatitude(), location.getLongitude(), 1);
getLocationName();
}
});
}
@Override
protected void onPause() {
super.onPause();
/*
* check if onCreate there was no internet, thus = subscription == null...
* start the background updates onPause if there is internet
*/
if (subscription == null && isNetworkAvailable()){
Log.d(TAG,"startBackgroundUpdates on Pause...");
startBackgroundUpdates();
}
}
Here, in the above code we see as soon as we get an exception in map operator and then we directly goto onError and the onNext doesn't get called or even onComplete. So, to handle the error in cases like this we use different operators and it will not move to onError directly. Let us understand them one by one.
onNext(): This method is called when a new item is emitted from the Observable. onError(): This method is called when an error occurs and the emission of data is not successfully completed. onComplete(): This method is called when the Observable has successfully completed emitting all items.
RxJava implements the Catch operator with three distinct operators: onErrorReturn. instructs an Observable to emit a particular item when it encounters an error, and then terminate normally. onErrorResumeNext. instructs an Observable to begin emitting a second Observable sequence if it encounters an error.
There is an error happening when you are trying to geocode the location.
Caused by: java.io.IOException: Timed out waiting for response from server at android.location.Geocoder.getFromLocation(Geocoder.java:136)
When you call subscribe with one Action1
as a parameter it only handles calls to onNext
and if an error happens the app will crash.
You need to subscribe with:
subscribe(new Subscriber<Location>() {
@Override
public void onNext(Location location) { /*Handle the location updates*/ }
@Override
public void onCompleted() { }
@Override
public void onError(Throwable e) { }
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With