2017-01-23 12 views
3

С тех пор как i'v интегрирован RxJava2, я получаю 401 не прошедшую проверку ошибки во всех перенастроенных вызовах, которые возвращают Observable, я использую базовую аутентификацию, и я знаю, что ошибка из-за этого, но почему он работает на отладке, но не выпуске.Retrofit2 Unauthenticated 401 ошибка при использовании rxjava2

По-моему, что-то не так с конфигурацией для rxjava адаптеров retrofit2

трассировки стека:

com.jakewharton.retrofit2.adapter.rxjava2.HttpException: HTTP 401 Unauthorized 
01-22 19:24:14.872 11502-11502/? W/System.err:  at com.jakewharton.retrofit2.adapter.rxjava2.BodyObservable$BodyObserver.onNext(BodyObservable.java:54) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at com.jakewharton.retrofit2.adapter.rxjava2.BodyObservable$BodyObserver.onNext(BodyObservable.java:37) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at com.jakewharton.retrofit2.adapter.rxjava2.CallObservable.subscribeActual(CallObservable.java:43) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at io.reactivex.Observable.subscribe(Observable.java:10514) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at com.jakewharton.retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:34) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at io.reactivex.Observable.subscribe(Observable.java:10514) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at io.reactivex.internal.operators.observable.ObservableDoOnLifecycle.subscribeActual(ObservableDoOnLifecycle.java:33) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at io.reactivex.Observable.subscribe(Observable.java:10514) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at io.reactivex.internal.operators.observable.ObservableDoOnEach.subscribeActual(ObservableDoOnEach.java:42) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at io.reactivex.Observable.subscribe(Observable.java:10514) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at io.reactivex.internal.operators.observable.ObservableObserveOn.subscribeActual(ObservableObserveOn.java:44) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at io.reactivex.Observable.subscribe(Observable.java:10514) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at io.reactivex.internal.operators.observable.ObservableSubscribeOn$1.run(ObservableSubscribeOn.java:39) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at io.reactivex.Scheduler$1.run(Scheduler.java:134) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:59) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:51) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1115) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:590) 
01-22 19:24:14.872 11502-11502/? W/System.err:  at java.lang.Thread.run(Thread.java:818) 

build.gradle:

::project:: 
apply plugin: 'com.android.application' //or apply plugin: 'java' 
apply plugin: 'me.tatarka.retrolambda' 
apply plugin: 'com.jakewharton.hugo' 
apply plugin: 'android-apt' 
def AAVersion = '4.1.0' 

android { 
    compileSdkVersion 25 
    buildToolsVersion '25.0.2' 

    defaultConfig { 
     applicationId "com.jutt.example1" 
     minSdkVersion 14 
     targetSdkVersion 25 
     versionCode 4 
     versionName "1.0" 
     multiDexEnabled false 
    } 
    buildTypes { 
     release { 
      minifyEnabled true 
      shrinkResources false 
      zipAlignEnabled true 
      //debuggable false 
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 
     } 
    } 
    compileOptions { 
     sourceCompatibility JavaVersion.VERSION_1_8 
     targetCompatibility JavaVersion.VERSION_1_8 
    } 
    compileOptions { 
     targetCompatibility 1.8 
     sourceCompatibility 1.8 
    } 

} 

apt { 
    arguments { 
     // you should set your package name here if you are using different application IDs 
     // resourcePackageName "your.package.name" 

     // You can set optional annotation processing options here, like these commented options: 
     // logLevel 'INFO' 
     // logFile '/var/log/aa.log' 
    } 
} 

dependencies { 
    compile fileTree(include: ['*.jar'], dir: 'libs') 
    testCompile 'junit:junit:4.12' 
    apt "org.androidannotations:androidannotations:$AAVersion" 
    compile "org.androidannotations:androidannotations-api:$AAVersion" 
    // Retrofit & OkHttp 
    // Because RxAndroid releases are few and far between, it is recommended you also 
// explicitly depend on RxJava's latest version for bug fixes and new features. 

// If you want to bind to Android-specific lifecycles 

// If you want pre-written Activities and Fragments you can subclass as providers 
    compile 'com.android.support:support-v4:25.1.0' 
    compile 'com.android.support:multidex:1.0.1' 
    compile 'com.android.support:appcompat-v7:25.1.0' 
    compile 'com.squareup.retrofit2:retrofit:2.1.0' 
    //compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' 
    compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' 
    compile 'com.squareup.okhttp3:logging-interceptor:3.4.2' 
    compile 'com.squareup.retrofit2:converter-gson:2.1.0' 
    compile 'com.afollestad.material-dialogs:core:0.9.0.2' 
    compile 'com.github.ganfra:material-spinner:1.1.1' 
    compile 'com.android.support:design:25.1.0' 
    compile 'org.apache.commons:commons-lang3:3.4' 
    compile 'com.wdullaer:materialdatetimepicker:2.5.0' 
    //compile 'io.reactivex:rxandroid:1.2.1' 
    //compile 'io.reactivex:rxjava:1.1.6' 
    compile 'io.reactivex.rxjava2:rxjava:2.0.2' 
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1' 
    compile 'com.trello.rxlifecycle2:rxlifecycle:2.0.1' 
} 

::app:: 

// Top-level build file where you can add configuration options common to all sub-projects/modules. 

buildscript { 
    repositories { 
     jcenter() 
    } 
    dependencies { 
     classpath 'com.android.tools.build:gradle:2.3.0-beta2' 
     classpath 'com.jakewharton.hugo:hugo-plugin:1.2.1' 
     classpath 'me.tatarka:gradle-retrolambda:3.3.1' 

     // NOTE: Do not place your application dependencies here; they belong 
     // in the individual module build.gradle files 
     // replace with the current version of the android-apt plugin 
     classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' 
    } 
} 


allprojects { 
    repositories { 
     jcenter() 
     mavenCentral() 
     mavenLocal() 
    } 
} 

task clean(type: Delete) { 
    delete rootProject.buildDir 
} 

progaurd:

# Add project specific ProGuard rules here. 
# By default, the flags in this file are appended to flags specified 
# in /Users/zulqurnainjutt/Library/Android/sdk/tools/proguard/proguard-android.txt 
# You can edit the include path and order by changing the proguardFiles 
# directive in build.gradle. 
# 
# For more details, see 
# http://developer.android.com/guide/developing/tools/proguard.html 

# Add any project specific keep options here: 

# If your project uses WebView with JS, uncomment the following 
# and specify the fully qualified class name to the JavaScript interface 
# class: 
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { 
# public *; 
#} 

-optimizationpasses 5 
#-allowaccessmodification 
-dontusemixedcaseclassnames 
-dontskipnonpubliclibraryclasses 
-dontskipnonpubliclibraryclassmembers 
-dontpreverify 
-verbose 

#your package path where your gson models are stored 
-keep class com.jutt.example1.model.** { *; } 

# Retrofit, OkHttp, Gson 
-keepattributes *Annotation* 
-keepattributes Signature 
-keep class com.squareup.okhttp.** { *; } 
-keep interface com.squareup.okhttp.** { *; } 
-dontwarn com.squareup.okhttp.** 
-dontwarn rx.** 
-dontwarn retrofit.** 
-keep class retrofit.** { *; } 
-keepclasseswithmembers class * { 
    @retrofit.http.* <methods>; 
} 
-keep class sun.misc.Unsafe { *; } 
-dontwarn java.nio.file.* 
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement 

# OkHttp3 
-keepattributes Signature 
-keepattributes *Annotation* 
-keep class okhttp3.** { *; } 
-keep interface okhttp3.** { *; } 
-dontwarn okhttp3.** 

# Rxjava-promises 

-keep class com.darylteo.rx.** { *; } 

-dontwarn com.darylteo.rx.** 

# RxJava 0.21 

-keep class rx.schedulers.Schedulers { 
    public static <methods>; 
} 
-keep class rx.schedulers.ImmediateScheduler { 
    public <methods>; 
} 
-keep class rx.schedulers.TestScheduler { 
    public <methods>; 
} 
-keep class rx.schedulers.Schedulers { 
    public static ** test(); 
} 

## Retrolambda specific rules ## 

# as per official recommendation: https://github.com/evant/gradle-retrolambda#proguard 
-dontwarn java.lang.invoke.* 

-keep class rx.internal.util.unsafe.** { 
    *; 
} 

Basic Authentication код, где ошибка лежит:

class Factory { 
     private static SERVERAPI service; 

     public static SERVERAPI getIstance(Context context, String base_url,String username,String password) { 
      if (service == null) { 

       OkHttpClient.Builder builder = new OkHttpClient().newBuilder(); 
       builder.readTimeout(2, TimeUnit.MINUTES); 
       builder.connectTimeout(2, TimeUnit.MINUTES); 
       builder.writeTimeout(2, TimeUnit.MINUTES); 

       //builder.certificatePinner(new CertificatePinner.Builder().add("*.androidadvance.com", "sha256/RqzElicVPA6LkKm9HblOvNOUqWmD+4zNXcRb+WjcaAE=") 
       // .add("*.xxxxxx.com", "sha256/8Rw90Ej3Ttt8RRkrg+WYDS9n7IS03bk5bjP/UXPtaY8=") 
       // .add("*.xxxxxxx.com", "sha256/Ko8tivDrEjiY90yGasP6ZpBU4jwXvHqVvQI0GS3GNdA=") 
       // .add("*.xxxxxxx.com", "sha256/VjLZe/p3W/PJnd6lL8JVNBCGQBZynFLdZSTIqcO0SJ8=") 
       // .build()); 


       if (BuildConfig.DEBUG) { 
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); 
        interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC); 
        builder.addInterceptor(interceptor); 

        if(username != null) { 
         if(password == null){ 
          password = ""; 
         } 
         final String credential = Credentials.basic(username, password); 
         builder.addInterceptor(chain -> { 
          Request original = chain.request(); 

          Request.Builder requestBuilder = original.newBuilder() 
            .header("Authorization", credential); 
          requestBuilder.header("Accept", "application/json"); 
          requestBuilder.method(original.method(), original.body()); 

          Request request = requestBuilder.build(); 
          return chain.proceed(request); 
         }); 
        } 
       } 

       int cacheSize = 10 * 1024 * 1024; // 10 MiB 
       Cache cache = new Cache(context.getCacheDir(), cacheSize); 
       builder.cache(cache); 
       Retrofit retrofit; 
       //RxJavaCallAdapterFactory rxAdapter = RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io()); 
       if (base_url == null) { 
        retrofit = new Retrofit.Builder() 
          .client(builder.build()) 
          .addConverterFactory(GsonConverterFactory.create()) 
          .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 
          .baseUrl(BASE_URL).build(); 
       } else { 
        retrofit = new Retrofit.Builder() 
          .client(builder.build()) 
          .addConverterFactory(GsonConverterFactory.create()) 
          .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 
          .baseUrl(base_url).build(); 
       } 
       service = retrofit.create(SERVERAPI.class); 
       return service; 
      } else { 
       return service; 
      } 
     } 

     public static SERVERAPI getIstance(Context context) { 
      return getIstance(context, null,null,null); 
     } 

     public static SERVERAPI getInstanceWithAuthBasic(Context context,String username,String password){ // im using this method 
      return getIstance(context, null,username,password); 
     } 

     public static SERVERAPI getInstanceWithAuthBasic(Context context,String base_url,String username,String password){ 
      return getIstance(context, base_url,username,password); 
     } 
    } 

Я пытаюсь решить эту проблему в течение более 2 недели теперь здесь мой пост на rxjava issue странице и мой предыдущий вопрос такой же вопрос родственный here, как может Я разрешаю эту проблему и делаю ее работоспособной.

+0

Вы уверены, что этого не происходит на стороне сервера? У меня никогда не было этой проблемы с Retrofit и RxJava –

+0

Нет, я уверен, ее абсолютно нормально работает как debug apk, но в релизе apk все вызовы retrofit2, которые используют базовую аутентификацию, не работают –

+0

Весь код, связанный с учетными данными, находится внутри ' if (BuildConfig.DEBUG) {'block. – jmcdale

ответ

0

Ваше исключение происходит в классе, который вы не указали здесь.

Во всяком случае, вам нужно проанализировать тип Exception, который приходит к onError обработчика. Обработка действительных ответов об ошибках HTTP с помощью Retrofit2 Наблюдения в (независимо от версии rxjava) довольно просты.

Прежде всего вам нужно знать, что retrofit api method возвращает Obsrvable<MyObject> будет распространяться с onNext только 2xx HTTP-ответами. Все остальные ответы будут отправлены в течение onError обработчика. Вот код, как справиться с этим (пример Котлин, просто чтобы дать и идея Java будет.):

retrofitApiService.suggest(
     token, 
     query).subscribe ({ suggestions -> 
    log.info("Got result: {}", suggestions) 
}, { error -> 
    // 

    if(error is HttpException) { 
     if(error.code() == 401) { 
      // We've got HTTP 401 Unauthorized 
     } else { 

      log.error("HTTP Error: {} {}, {}", 
        error.response().code(), 
        error.response().message(), 
        error.response().errorBody().toString()) 
     } 

    } else { 
     // something really wrong happened 
     // e.g.: invalid json or something else 
     log.error("Error: ${error.message}", error) 
    } 
}) 

Если вы хотите, чтобы получить все ответы на onNext, то вы должны использовать Observable<ResponseBody>. В этом случае все действительные ответы HTTP будут в конечном итоге в onNext, и все ваши исключения кода будут отправлены на onError.