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();
}
}
If you still wish to implement only one method and handle error too, then probably you can have abstract CustomSubscriber like below.
Implement this way
hope some one will benefited.
There is an error happening when you are trying to geocode the location.
When you call subscribe with one
Action1
as a parameter it only handles calls toonNext
and if an error happens the app will crash.You need to subscribe with:
Consider subscribing to the location data with
subscribe(Action<T> onNext, Action<Throwable> onError)
. In other words, you should handle errors that are emitted from the observable data.