Azizah
Azizah

Reputation: 55

java.lang.IllegalArgumentException: Response must include generic type (e.g., Response<String>)

Error when I send a chat to others.

java.lang.IllegalArgumentException: Response must include generic type (e.g., Response<String>)
            for method APIService.sendnotif

at retrofit2.Utils.methodError(Utils.java:54)

at retrofit2.Utils.methodError(Utils.java:43)

at retrofit2.HttpServiceMethod.parseAnnotations(HttpServiceMethod.java:77)

at retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:39)
            at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:202)
            at retrofit2.Retrofit$1.invoke(Retrofit.java:160)
            at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
            at $Proxy0.sendnotif(Unknown Source)
            at com.azizah.msocial.ChatAct$7.onDataChange(ChatAct.java:297)

class interface ApiService

public interface APIService {

@Headers({
        "Content-Type:application/json",
        "Authorization:key=Lhghhkvhvhffgv"
})

@POST("fcm/send")
Call<Response> sendnotif(@Body Pengirim body);
}

sendnotif.class ERROR in line apiService.sendnotif must include generic type in here. can u explain to me to make generic type retrofit?

private void sendnotif(final String hisUid, final String name, final String pesan) {

DatabaseReference alltoken = FirebaseDatabase.getInstance().getReference("Tokens");
Query query = alltoken.orderByKey().equalTo(hisUid);
        query.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                for(DataSnapshot ds: dataSnapshot.getChildren()){
                    Tokenclass tokenclass = ds.getValue(Tokenclass.class);
                    Datanotif data = new Datanotif(myUid, name+":"+pesan, "Pesan Baru", hisUid, R.drawable.ic_usr_name);
                    Pengirim pengirim = new Pengirim(data, tokenclass.getToken());
                     apiService.sendnotif(pengirim)
                        .enqueue(new Callback<Response>() {
                            @Override
                            public void onResponse(Call<Response> call, Response<Response> response) {
                                Toast.makeText(ChatAct.this, ""+response.message(), Toast.LENGTH_SHORT).show();
                            }

                            @Override
                            public void onFailure(Call<Response> call, Throwable t) {

                            }
                        });
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {

        }
    });

}

error in apiService.sendnotif(pengirim)

please help me, It makes app force close

Upvotes: 3

Views: 2277

Answers (4)

mobimaks
mobimaks

Reputation: 71

I had a similar problem when server was returning String, but I didn't use the response data, only status code.

@POST
suspend fun postData(@Body data: Data): Response<String>

val response = postData(...)
when(response.code()) { ... }

Adding Proguard rules to preserve generic types and Continuation/retrofit2.Response classes didn't work for me.

Jake Wharton wrote a plugin to dynamically add rules to preserve those generic types.

Module-level build.gradle.kts

plugins {
   kotlin("kapt")
}
dependencies {
   kapt("com.squareup.retrofit2:response-type-keeper:2.11.0")
}

Disclaimer: currently it works only with KAPT, and not KSP

Upvotes: 0

Kamal Nayan
Kamal Nayan

Reputation: 1718

Extending the Daniel.W answer,

This rule is not mentioned yet in the retrofit's official proguard guide. You must mention this in your proguard rules

# R8 full mode strips generic signatures from return types if not kept.
-keep,allowobfuscation,allowshrinking class retrofit2.Response

Final proguard rules for retrofit is :

# Retrofit does reflection on method and parameter annotations.
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations

# Keep annotation default values (e.g., retrofit2.http.Field.encoded).
-keepattributes AnnotationDefault

# Retain service method parameters when optimizing.
-keepclassmembers,allowshrinking,allowobfuscation interface * {
    @retrofit2.http.* <methods>;
}

# Ignore annotation used for build tooling.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement

# Ignore JSR 305 annotations for embedding nullability information.
-dontwarn javax.annotation.**

# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
-dontwarn kotlin.Unit

# Top-level functions that can only be used by Kotlin.
-dontwarn retrofit2.KotlinExtensions
-dontwarn retrofit2.KotlinExtensions$*

# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>

# Keep inherited services.
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface * extends <1>

# With R8 full mode generic signatures are stripped for classes that are not
# kept. Suspend functions are wrapped in continuations where the type argument
# is used.
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation

# R8 full mode strips generic signatures from return types if not kept.
-if interface * { @retrofit2.http.* public *** *(...); }
-keep,allowoptimization,allowshrinking,allowobfuscation class <3>

# R8 full mode strips generic signatures from return types if not kept.
-keep,allowobfuscation,allowshrinking class retrofit2.Response

Upvotes: 3

Azizah
Azizah

Reputation: 55

my problem solved, I make mistake in the code

@Override
public void onResponse(Call<Response> call, Response<Response> response) {
Toast.makeText(ChatAct.this, ""+response.message(), Toast.LENGTH_SHORT).show();
 }

Call replace to Call because the class named Respon not Response.

Upvotes: 0

Related Questions