Android Retrofit 2 multiple converters (Gson & SimpleXML) error

Check this presentation by Jake Wharton, where he solves exactly the problem you describe (and presents many other useful tricks).

In short he suggests creating annotations representing your expected data format (for example Json and Xml in your case) and annotate your API calls accordingly. Then you define your custom ConverterFactory where you delegate to either GsonConverterFactory or SimpleXmlConverterFactory depending on the annotation encountered.

However, you need add two things to the Jake's solution.

First do not forget to annotate your annotations with @Retention(RetentionPolicy.RUNTIME) otherwise they won't be kept during the runtime:

@Retention(RetentionPolicy.RUNTIME)
public @interface Json {}

Second, the annotations you receive in your responseBodyConverter method are not actually your annotations. They are proxies created by the system to your annotations. Therefore you need to replace the conditions:

annotation.getClass() == Json.class
annotation.getClass() == Xml.class

with:

annotation.annotationType() == Json.class
annotation.annotationType() == Xml.class

Thanks to @Marcin and the reference.

Below is the code from the mentioned presentation by Jake Warton adjusted according to Marcin's comments (and added Json factory as default if no annotation was found):

public class AnnotatedConverterFactory extends Converter.Factory {

    @Retention(RetentionPolicy.RUNTIME)
    public @interface Json {}

    @Retention(RetentionPolicy.RUNTIME)
    public @interface Xml {}


    final Map<Class<?>, Converter.Factory> mFactoryMap;

    public AnnotatedConverterFactory(Map<Class<?>, Converter.Factory> factoryMap) {
        mFactoryMap = factoryMap;
    }


    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        for(Annotation annotation : annotations){
            Converter.Factory factory = mFactoryMap.get(annotation.annotationType());
            if(factory != null){
                return factory.responseBodyConverter(type, annotations, retrofit);
            }
        }
        //try to default to json in case no annotation on current method was found
        Converter.Factory jsonFactory = mFactoryMap.get(Json.class);
        if(jsonFactory != null){
            return jsonFactory.responseBodyConverter(type, annotations, retrofit);
        }
        return null;
    }

    static class Builder {
        Map<Class<?>, Converter.Factory> mFactoryMap = new LinkedHashMap<>();

        Builder add(Class<? extends Annotation> factoryType, Converter.Factory factory){
            if(factoryType == null) throw new NullPointerException("factoryType is null");
            if(factory == null) throw new NullPointerException("factory is null");
            mFactoryMap.put(factoryType, factory);
            return this;
        }
        public AnnotatedConverterFactory build(){
            return new AnnotatedConverterFactory(mFactoryMap);
        }

    }
}

Usage:

    interface RetrofitService{
        @POST
        @AnnotatedConverterFactory.Xml
        Call<Envelope> someApiMethodWithXmlRespoonse(@Url String url, @Body Envelope envelope);

        @POST
        @AnnotatedConverterFactory.Json
        Call<Envelope> someApiMethodWithJsonRespoonse(@Url String url, @Body Model model);
    }

Instantiate retrofit:

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(mOkHttpClient)
                .addConverterFactory(new AnnotatedConverterFactory.Builder()
                        .add(AnnotatedConverterFactory.Xml.class, SimpleXmlConverterFactory.createNonStrict())
                        .add(AnnotatedConverterFactory.Json.class, GsonConverterFactory.create(mGson))
                        .build()
                )


        mRetrofitService = retrofit.create(RetrofitService.class);