2015-10-21 10 views
7

ich Berichte über eine NetworkOnMainThread Ausnahme auf Lollipop bekommen +, wenn ein https api Anruf Retrofit und RxAndroid mit ausgeführt wird.NetworkOnMainThread RxJava + Retrofit + Lollipop +

Ich habe den Code isoliert und erstellt das folgende Beispiel, das immer noch fehlschlägt.

Hier ist der build.gradle:

apply plugin: 'com.android.application' 
apply plugin: 'me.tatarka.retrolambda' 

android { 
    compileSdkVersion 23 
    buildToolsVersion "23.0.1" 

    defaultConfig { 
    applicationId "com.example.bug" 
    minSdkVersion 9 
    targetSdkVersion 23 
    versionCode 1 
    versionName "1.0" 
    } 
    buildTypes { 
    release { 
     minifyEnabled false 
     proguardFiles getDefaultProguardFile('proguard-android.txt') 
    } 
    } 
    lintOptions { 
    abortOnError false 
    } 
    compileOptions { 
    sourceCompatibility JavaVersion.VERSION_1_8 
    targetCompatibility JavaVersion.VERSION_1_8 
    } 
} 

dependencies { 
    compile fileTree(dir: 'libs', include: ['*.jar']) 
    testCompile 'junit:junit:4.12' 
    compile 'com.android.support:appcompat-v7:23.0.1' 

    compile 'com.squareup.okhttp:okhttp:2.5.0' 
    compile 'com.squareup.okhttp:okhttp-urlconnection:2.5.0' 
    compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2' 
    compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2' 
    compile 'com.squareup.retrofit:retrofit:2.0.0-beta2' 
    compile 'io.reactivex:rxandroid:1.0.1' 
} 

Hier ist die einzige Tätigkeit:

public class HomeActivity extends Activity { 

    private static final String URL_BASE = "https://some.https.api.com/"; 
    private static final String ENDPOINT = "some/endpoint"; 

    @Override protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    OkHttpClient okHttpClient = new OkHttpClient(); 
    okHttpClient.setConnectTimeout(15, TimeUnit.SECONDS); 
    okHttpClient.setReadTimeout(15, TimeUnit.SECONDS); 

    Retrofit retrofit = new Retrofit.Builder() 
     .baseUrl(URL_BASE) 
     .client(okHttpClient) 
     .addConverterFactory(GsonConverterFactory.create(new Gson())) 
     .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
     .build(); 

    MyApi mService = retrofit.create(MyApi.class); 

    setContentView(R.layout.home_activity); 
    Button button = (Button) findViewById(R.id.button); 
    button.setOnClickListener(v-> 
     mService.whatever(new ParamObject()) 
      .subscribeOn(Schedulers.io()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(
       response -> Log.d("BUG", response.status), 
       error -> Log.d("BUG", error.toString())) 
    ); 
    } 

    interface MyApi { 

    @POST(ENDPOINT) 
    Observable<ResponseObject> whatever(@Body ParamObject requirements); 
    } 

    class ResponseObject { 
    public String status; 
    } 

    class ParamObject { 
    } 
} 

Hier ist die Ausnahme Stacktrace:

E/AndroidRuntime(28345): FATAL EXCEPTION: main 
E/AndroidRuntime(28345): Process: com.example.bug, PID: 28345 
E/AndroidRuntime(28345): java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread. 
E/AndroidRuntime(28345): at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:62) 
E/AndroidRuntime(28345): at android.os.Handler.handleCallback(Handler.java:739) 
E/AndroidRuntime(28345): at android.os.Handler.dispatchMessage(Handler.java:95) 
E/AndroidRuntime(28345): at android.os.Looper.loop(Looper.java:135) 
E/AndroidRuntime(28345): at android.app.ActivityThread.main(ActivityThread.java:5221) 
E/AndroidRuntime(28345): at java.lang.reflect.Method.invoke(Native Method) 
E/AndroidRuntime(28345): at java.lang.reflect.Method.invoke(Method.java:372) 
E/AndroidRuntime(28345): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
E/AndroidRuntime(28345): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 
E/AndroidRuntime(28345): Caused by: android.os.NetworkOnMainThreadException 
E/AndroidRuntime(28345): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1147) 
E/AndroidRuntime(28345): at com.android.org.conscrypt.OpenSSLSocketImpl$SSLOutputStream.write(OpenSSLSocketImpl.java:724) 
E/AndroidRuntime(28345): at okio.Okio$1.write(Okio.java:80) 
E/AndroidRuntime(28345): at okio.AsyncTimeout$1.write(AsyncTimeout.java:155) 
E/AndroidRuntime(28345): at okio.RealBufferedSink.flush(RealBufferedSink.java:221) 
E/AndroidRuntime(28345): at com.squareup.okhttp.internal.framed.Http2$Writer.rstStream(Http2.java:475) 
E/AndroidRuntime(28345): at com.squareup.okhttp.internal.framed.FramedConnection.writeSynReset(FramedConnection.java:356) 
E/AndroidRuntime(28345): at com.squareup.okhttp.internal.framed.FramedStream.close(FramedStream.java:222) 
E/AndroidRuntime(28345): at com.squareup.okhttp.internal.http.FramedTransport.disconnect(FramedTransport.java:215) 
E/AndroidRuntime(28345): at com.squareup.okhttp.internal.http.HttpEngine.disconnect(HttpEngine.java:573) 
E/AndroidRuntime(28345): at com.squareup.okhttp.Call.cancel(Call.java:122) 
E/AndroidRuntime(28345): at retrofit.OkHttpCall.cancel(OkHttpCall.java:162) 
E/AndroidRuntime(28345): at retrofit.RxJavaCallAdapterFactory$CallOnSubscribe$1.call(RxJavaCallAdapterFactory.java:102) 
E/AndroidRuntime(28345): at rx.subscriptions.BooleanSubscription.unsubscribe(BooleanSubscription.java:72) 
E/AndroidRuntime(28345): at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:124) 
E/AndroidRuntime(28345): at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:113) 
E/AndroidRuntime(28345): at rx.Subscriber.unsubscribe(Subscriber.java:98) 
E/AndroidRuntime(28345): at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:124) 
E/AndroidRuntime(28345): at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:113) 
E/AndroidRuntime(28345): at rx.Subscriber.unsubscribe(Subscriber.java:98) 
E/AndroidRuntime(28345): at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:124) 
E/AndroidRuntime(28345): at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:113) 
E/AndroidRuntime(28345): at rx.Subscriber.unsubscribe(Subscriber.java:98) 
E/AndroidRuntime(28345): at rx.observers.SafeSubscriber.onCompleted(SafeSubscriber.java:90) 
E/AndroidRuntime(28345): at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.pollQueue(OperatorObserveOn.java:201) 
E/AndroidRuntime(28345): at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber$2.call(OperatorObserveOn.java:170) 
E/AndroidRuntime(28345): at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55) 
E/AndroidRuntime(28345): ... 8 more 

Ein paar Dinge:

  • Dieses Codebeispiel funktioniert gut in Android 4.x
  • Ich habe dieses Beispiel (mit kleinen Änderungen) gegen die GitHub API versucht und es funktioniert gut.
  • Die API wird auf der App-Engine von Google ausgeführt.
  • Beachten Sie, dass die beobachtbare auf AndroidSchedulers.mainThread() auf Schedulers.io() und beobachtet abonnieren

Irgendwelche Ideen?

bearbeiten

  • Nach einem genaueren Blick auf die Stacktrace nehmen ich heraus es etwas über http2 war. Obwohl nicht das gleiche Problem gemeldet here, die folgende Zeile, um die OkHttp verfügbaren Protokolle zu beschränken hat es wieder funktioniert.

    okHttpClient.setProtocols(Collections.singletonList(Protocol.HTTP_1_1));

+0

nur weil der editierte Teil das Problem für mich auch behoben. hatte das gleiche Problem auf Android 5.0 + – Diogo

Antwort

3

Es ist ein bekannter Fehler in OkHttp dass eine Rufabstellung tut I/O auf dem Cancelling-Thread. Wird in einer zukünftigen Version behoben.

+0

Danke für die Antwort Jesse. –

+0

Also, um das zu beheben, entfernen Sie die OkHttp-Instanz? –

+0

@NicolasJafelle Fangen Sie einfach die Ausnahme oder https://github.com/square/okhttp/issues/1592#issuecomment-143313661 –

3

Bis this issue behoben wurde, fügen Sie unsubscribeOn(Schedulers.io()) der RX-Rufkette hinzu. Ein Beispiel finden Sie unter this commit, wenn Sie mehr Kontext benötigen.

Verwandte Themen