java retro2me,使用rxjava2时Retrofit2未经身份验证的401错误

Ever since i'v integrated RxJava2 , i am receiving 401 unauthenticated error in all retrofit calls that return Observable , i'm using basic authentication and i know error is due to it , but why it works on debug but not release.

In my opinion something is wrong with the configuration for rxjava adapters of retrofit2

Stack Trace:

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.* ;

}

-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 ;

}

-keep class rx.schedulers.ImmediateScheduler {

public ;

}

-keep class rx.schedulers.TestScheduler {

public ;

}

-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 code where error lies:

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);

}

}

I'm trying to resolve this issue for over a 2 week now here is my post at rxjava issue page and my previous same issue related question is here , how can i resolve this issue and make it working

解决方案

Your exception happens in the class which you had not listed here.

Anyway, you need to analyze the type of Exception which comes to onError handler. Handling of valid HTTP error responses with Retrofit2 Observables in (regardless of rxjava version) is quite easy.

First you need to know is that retrofit api method returning Obsrvable will propagate with onNext only 2xx HTTP responses. All other responses will be sent within onError handler. Here is the code how to handle it (Kotlin example, just to give and idea. Java will ):

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)

}

})

If you wish to get all responses into onNext, then you should use Observable. In that case all valid HTTP responses will end up in onNext, and all your code exceptions will be sent to onError.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值