私のアプリでは、ReactiveLocationProviderライブラリ( link )を使用しています。 onCreateメソッドで更新をサブスクライブします。デバイスがオンラインの場合は正常に機能しますが、Wi-Fiをオフにして次のバックグラウンドの場所を待つと、デバイスのOnErrorNotImplementedExceptionが更新されます。これはログです:
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コード:
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();
}
}
場所をジオコーディングしようとすると、エラーが発生します。
原因:Java.io.IOException:Android.location.Geocoder.getFromLocation(Geocoder.Java:136)のサーバーからの応答を待機してタイムアウトしました
1つでサブスクライブを呼び出すときAction1
パラメータとして、onNext
への呼び出しのみを処理し、エラーが発生した場合、アプリはクラッシュします。
購読する必要があります:
subscribe(new Subscriber<Location>() {
@Override
public void onNext(Location location) { /*Handle the location updates*/ }
@Override
public void onCompleted() { }
@Override
public void onError(Throwable e) { }
})
subscribe(Action<T> onNext, Action<Throwable> onError)
を使用して位置データをサブスクライブすることを検討してください。つまり、観測可能なデータから発生するエラーを処理する必要があります。
それでも1つのメソッドのみを実装し、エラーも処理したい場合は、おそらく以下のような抽象CustomSubscriberを使用できます。
public abstract class CustomSubscriber<T> extends Subscriber<T> {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(T t) {
}
}
この方法で実装する
getObservable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new CustomSubscriber<List<String>>() {
@Override
public void onNext(List<String> list) {
}
});
誰かが恩恵を受けることを願っています。