#StackBounty: #android #kotlin #gson #retrofit #retrofit2 Retrofit Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $ …

Bounty: 50

So in my app a user can take a picture of their meal and through the use of Tensorflow’s image classification, it will classify what the meal is in onActivityResult. Then, using Edamam Recipe Search API, it will return a recipe for that meal to the user.

When I run my app, everything is working fine and nothing is crashing, however when I use Retrofit Callback, the onFailure method is called and I get this error:
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

This is what I have in my RecipeApi interface:

@GET("search")
fun searchRecipe(
    @Query("q") query: String,
    @Query("app_id") app_id: String,
    @Query("app_key") app_key: String,
    @Query("from") from: Int,
    @Query("to") to: Int
): Call<List<Recipe>>

And this is what I have in my onActivityResult in my MainActivity:

retrofit = Retrofit.Builder()
    .baseUrl(Constants.BASE_URL)
    .addConverterFactory(GsonConverterFactory.create())
    .build()
jsonPlaceHolderApi = retrofit.create(RecipeApi::class.java)
call = jsonPlaceHolderApi.searchRecipe(text, Constants.API_ID, Constants.API_KEY, 0, 1)
call.enqueue(object : Callback<List<Recipe>> {
    override fun onResponse(
        call: Call<List<Recipe>>,
        response: Response<List<Recipe>>
    ) {
        if (!response.isSuccessful) {
            println("Code: " + response.code())
            return
        }
        recipes = response.body()!!
        for (recipe: Recipe in recipes) {
            var content: String = ""
            content += "Yield: ${recipe.yield} + n"
            content += "Calories: ${recipe.calories} + n"
            content += "TotalWeight: ${recipe.totalWeight} + n"
            content += "Ingredients: ${recipe.ingredients} + n"
            content += "TotalNutrients: ${recipe.totalNutrients} + n"
            content += "TotalDaily: ${recipe.totalDaily} + nn"
            println(content)
        }
    }

    override fun onFailure(call: Call<List<Recipe>>, t: Throwable) {
        println(t.message)
    }
})

For jsonPlaceHolderApi, call, and recipes, I created those variables at the top of my activity:

private lateinit var jsonPlaceHolderApi: RecipeApi
private lateinit var call: Call<List<Recipe>>
private lateinit var recipes: List<Recipe>

Does anyone know how to fix this issue?


Get this bounty!!!

#StackBounty: #android #android-studio #search #retrofit #retrofit2 particular title(fetched from api) using searchview?

Bounty: 50

I want something like this–>
Required

so the thing is ,what I exactly want is when user type particular topic name(if present in app) in searchview it should able give suggestions and if found it should open that topic activity (just like Facebook,instagram,…etc searches)..and those title are coming from api(which I have successfully displayed in other activities)..like this–>
[enter image description here..what will the logic for it???please help.. Thanks

so I have just included searchview in xml like this–>

  <SearchView
    android:id="@+id/searchView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:queryHint="Search Here"
    android:iconifiedByDefault="false"
    android:layout_alignParentTop="true"
    android:background="@drawable/search_bar"
    android:layout_marginLeft="15dp"
    android:layout_marginRight="15dp"
    android:layout_marginTop="20dp"
    android:pointerIcon="crosshair"
    android:theme="@style/Widget.AppCompat.SearchView"
    android:focusedByDefault="true"

    />

Need help..thanks in advance….

here is my json:for [enter image description here

[{"id":"11","title":"TextView"},{"id":"10","title":"Edit Text"},{"id":"9","title":"ImageView"},{"id":"8","title":"Button "},{"id":"7","title":"CheckBox"},{"id":"6","title":"RadioButton & RadioGroup"},{"id":"5","title":"DatePicker"},{"id":"4","title":"TimePicker"},{"id":"3","title":"Switch"},{"id":"1","title":"Simple & Custom Toast"}]

here is my activity: for [enter image description here

public class StartLearning extends AppCompatActivity {
private RecyclerView recyclerView;
private SLAdapter slAdapter;
ProgressDialog progressDialog;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.startlearning_layout);
    progressDialog = new ProgressDialog(StartLearning.this);
    progressDialog.setMessage("Loading....");
    progressDialog.show();
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    if (getSupportActionBar() != null) {
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDisplayShowHomeEnabled(true);
        /*Create handle for the RetrofitInstance interface*/
        SLApiSevice service = SLApiClient.getRetrofitInstance().create(SLApiSevice.class);
        Call<List<SlModel>> call = service.getMySlmodel();

        call.enqueue(new Callback<List<SlModel>>() {
            @Override
            public void onResponse(Call<List<SlModel>> call, Response<List<SlModel>> response) {
                progressDialog.dismiss();
                generateDataList(response.body());
                Log.e("hello", String.valueOf(response.body()));

            }

            @Override
            public void onFailure(Call<List<SlModel>> call, Throwable t) {
                progressDialog.dismiss();
                Toast.makeText(getApplicationContext(), "Something went wrong...Please try later!", Toast.LENGTH_SHORT).show();


            }
        });
    }
}
private void generateDataList(List<SlModel> employeeList) {
    recyclerView = findViewById(R.id.SLrecycle);
    LinearLayoutManager manager = new LinearLayoutManager(getApplicationContext());
    recyclerView.setLayoutManager(manager);
    recyclerView.setHasFixedSize(true);
    slAdapter = new SLAdapter(getApplicationContext(),employeeList);
    recyclerView.setAdapter(slAdapter);
}

adapter:for [enter image description here

public class SLAdapter extends RecyclerView.Adapter<SLAdapter.CustomViewHolder> {

List<StartLearning.SlModel> Slmdel;
Context context;

public SLAdapter(Context context,List<StartLearning.SlModel> employees) {
    this.Slmdel = employees;
    this.context=context;
}

@Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.startlearning_item, parent, false);

    return new CustomViewHolder(itemView);
}

@Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
    // TipsModel employee = employees.get(position);
    //// holder.employeeName.setText(employees.get(position).getTips());
    holder.textView.setText(String.valueOf(position+1)+". ");
    holder.employeeName.setText(Slmdel.get(position).getTitle());


}

@Override
public int getItemCount() {
    return Slmdel.size();
    //return (employees == null) ? 0 : employees.size();

}

public class CustomViewHolder extends RecyclerView.ViewHolder {
    public TextView employeeName;
    TextView textView;

    public CustomViewHolder(View view) {
        super(view);
        employeeName = (TextView) view.findViewById(R.id.Sl2);
        textView=view.findViewById(R.id.Sl1);
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent =  new Intent(context, NextSLactivity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.putExtra("title", Slmdel.get(getAdapterPosition()).getTitle());
               intent.putExtra("idSLnext", Slmdel.get(getAdapterPosition()).getId());
                //Log.e("ashwini",WAmdel.get(getAdapterPosition()).getId());
                context.startActivity(intent);

            }
        });


    }
}

onclick of item(example :textview)

activity:one of the items(example :textview)

public class JavaFragment extends Fragment {

private RecyclerView recyclerView;
private NextSLJavaAdapter adapter;
private NextSLModel DescriptList;
ProgressDialog progressDialog;
public JavaFragment() {
    // Required empty public constructor
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.nextsl_layout, container, false);

}

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    Toolbar toolbar = (Toolbar) getView().findViewById(R.id. toolbar );
   // setSupportActionBar( toolbar );
    //if (getSupportActionBar() != null) {
      //  getSupportActionBar().setDisplayHomeAsUpEnabled(true);
       // getSupportActionBar().setDisplayShowHomeEnabled(true);
    //}
    progressDialog = new ProgressDialog(getContext());
    progressDialog.setMessage("Loading....");
    progressDialog.show();
    Intent intent = getActivity().getIntent();
    String title = intent.getStringExtra("title");
    //getSupportActionBar().setTitle(title);
    String id = intent.getStringExtra("idSLnext");
    Log.e("ashwini", String.valueOf(id));


    /*Create handle for the RetrofitInstance interface*/
    SLApiSevice service = SLApiClient.getRetrofitInstance().create(SLApiSevice.class);
    Call<NextSLModel> call = service.getnextslmodel(id);
    call.enqueue(new Callback<NextSLModel>() {
        @Override
        public void onResponse(Call<NextSLModel> call, Response<NextSLModel> response) {
            progressDialog.dismiss();
            DescriptList=response.body();
            generateDataList(DescriptList);

        }

        @Override
        public void onFailure(Call<NextSLModel> call, Throwable t) {
             progressDialog.dismiss();

            Toast.makeText(getContext(), "Something went wrong...Please try later!", Toast.LENGTH_SHORT).show();
        }
    });

}
private void generateDataList(NextSLModel photoList) {
    recyclerView = getView().findViewById(R.id.nextSLrecycle);
    LinearLayoutManager manager = new LinearLayoutManager(getContext());
    recyclerView.setLayoutManager(manager);
    recyclerView.setHasFixedSize(true);
    adapter = new NextSLJavaAdapter(getContext(),photoList);
    recyclerView.setAdapter(adapter);
}

}

adapter:

public class NextSLJavaAdapter extends RecyclerView.Adapter<NextSLJavaAdapter.CustomViewHolder> {

NextSLModel Slmdel;
Context context;

public NextSLJavaAdapter(Context context, NextSLModel employees) {
    this.Slmdel = employees;
    this.context = context;
}

@Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.nextsl_item, parent, false);

    return new CustomViewHolder(itemView);
}

@Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
    // TipsModel employee = employees.get(position);
    //// holder.employeeName.setText(employees.get(position).getTips());
 /////////   holder.textView.setText(String.valueOf(position + 1) + ". ");
    holder.employeeName.setText(Slmdel.getJava());
    Log.e("sl",Slmdel.getJava());


}

@Override
public int getItemCount() {
    return 1;
    //return (employees == null) ? 0 : employees.size();

}

public class CustomViewHolder extends RecyclerView.ViewHolder {
    public TextView employeeName;
    TextView textView;

    public CustomViewHolder(View view) {
        super(view);
        employeeName = (TextView) view.findViewById(R.id.detailsStartLearning);
        textView = view.findViewById(R.id.Sl1);}}}

see I haven’t done in search activity:

public class Search extends AppCompatActivity {
SearchView searchView;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.search);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    searchView=findViewById(R.id.searchView);
    if (getSupportActionBar() != null) {
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDisplayShowHomeEnabled(true);
    }

}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    if (item.getItemId() ==android.R.id.home) {
        finish();
    }
    return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed() {
    super.onBackPressed();
}

}

xml of search:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="@color/colorPrimary"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" >

</androidx.appcompat.widget.Toolbar>
<SearchView
    android:id="@+id/searchView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:queryHint="Search Here"
    android:iconifiedByDefault="false"
    android:layout_alignParentTop="true"
    android:background="@drawable/search_bar"
    android:layout_marginLeft="15dp"
    android:layout_marginRight="15dp"
    android:layout_marginTop="20dp"
    android:pointerIcon="crosshair"
    android:theme="@style/Widget.AppCompat.SearchView"
    android:focusedByDefault="true"

    />


Get this bounty!!!

#StackBounty: #android #retrofit #okhttp #amazon-elastic-beanstalk #aws-ebs How to fix "End of stream on null" network issue?

Bounty: 50

Some users of my Android application are frequently running into a network error with the following error message: "Unexpected end of stream on null".

I didn’t find any clear way to solve it by looking at other similar question. I haven’t been able to reproduce the network error on my end.

1) I have unsuccessfully appended Connection=close to the requests headers as this answer suggests

2) I have unsucessflly added .retryOnConnectionFailure(true) as this answer suggests

3) I have unsuccessfully searched for a server side issue as this answer suggests but the requests with network issues are not appearing in the nginx access.log file

Here is how I init Retrofit

OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                .connectTimeout(40, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true)
                .build();

Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
                .baseUrl(BuildConfig.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(okHttpClient);

this.retrofit = retrofitBuilder.build();

Here is my endpoint definition (in IUserService.java)

@POST("/v2/android/login/phone")
@Headers("Content-Type: application/json;charset=UTF-8;Connection=close")
Call<APIResult<Session>> phoneLogin(@Body APIRequest request);

And here is how the endpoint is queried

userService = retrofit.create(IUserService.class);
Call<APIResult<Session>> call = userService.phoneLogin(request);
call.enqueue(new GenericCallback<>(context, callback));

Our configuration:

Android (Java)

Retrofit 2.3.0: 'com.squareup.retrofit2:retrofit:2.3.0'

Okhttp 3.12.1: 'com.squareup.okhttp3:okhttp:3.12.1'

Server running on AWS Elastic Beanstalk, platform: Puma with Ruby 2.6 running on 64bit Amazon Linux/2.9.0

Can anyone explain better where the problem is coming from? Any idea how to reproduce this issue locally? Any way to solve this issue?


Get this bounty!!!

#StackBounty: #android #retrofit #retrofit2 Retrofit with large data payloads

Bounty: 50

I have an API endpoint that can sometimes return a large payload of data (not images/files) and at times the payload size can cause cause my app to throw out of memory exception

this is an example of what my interface looks like

@GET("People")
fun getPeopleAsync(): Deferred<Response<List<Person>>>

I am curious it using @Streaming would work with data payloads? I have only seen it used with files so would this even work with data payloads?

Are there any other methods for dealing with large payloads in retrofit?


Get this bounty!!!

#StackBounty: #android #kotlin #retrofit #rx-java #android-architecture-components android -java.io.IOException: Canceled when disposed

Bounty: 50

I’m using android architecture component ,rxjava and retrofit with mvvm structure , i’m new in these fields by the way

the problem I’ve is this , I’m disposed my disposables in viewmodel ,the problem is this , it’ll triggered when I go from activity to activity or close the application and it’ll not restart again when it reopens the activity, so I lost the connection and I get FAILED: java.io.IOException: Canceled error when I want to use the api connection again .

this is my code:

class CategoryViewModel(private val model:CategoryModel): ViewModel() {
private lateinit var catsLiveData:MutableLiveData<MutableList<Cat>>

fun getCats():MutableLiveData<MutableList<Cat>>{
    if(!::catsLiveData.isInitialized){
        catsLiveData=model.getCats()
    }
    return catsLiveData;
}

override fun onCleared() {
    super.onCleared()
    model.clearDisposable()
}

this is my model class where I get the data from internet :

class CategoryModel(
    private val netManager: NetManager,
    private val sharedPrefManager: SharedPrefManager) {

private lateinit var categoryDao: CategoryDao
private lateinit var dbConnection: DbConnection
private lateinit var lastUpdate: LastUpdate
private var list: MutableLiveData<MutableList<Cat>> = MutableLiveData()
public val compositeDisposable= CompositeDisposable()

fun getCats(): MutableLiveData<MutableList<Cat>> {

        return getCatsOnline();


}

private fun getCatsOnline(): MutableLiveData<MutableList<Cat>> {
    Log.v("this", "online ");
    val getCats = ApiConnection.client.create(Category::class.java)
    compositeDisposable+=getCats.getCats(sharedPrefManager.getUid(), lastUpdate.getLastCatDate())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                    { success ->
                        list += success.cats

                    }, { error ->
                Log.v("this", "ErrorGetCats " + error.localizedMessage);
            }
            )

    return list;
}


fun clearDisposable(){
    if(!compositeDisposable.isDisposed){
        compositeDisposable.dispose()
        Log.v("this","disposable called");
    }
}
}

what is wrong with this ?


Get this bounty!!!

#StackBounty: #android #amazon-s3 #retrofit #retrofit2 #aws-sdk Retrofit2-AWS S3 Multipart image File corrupt issue

Bounty: 50

I am using Retrofit2 for handling API calls in my Android application. The application contains several image upload features. All the image uploading features are wired up to two API calls and will fire one after another.

  1. The first API will upload the image content to the server and the server will generate a dynamic signed AWS S3 image URL as a response.

  2. The second API is using the above-signed URL and PUT the data into AWS S3.

It was working perfectly for small images. For large images, the API has failed. The possible solution for this issue is to change the upload API as multipart. So I have changed the second API as “Retrofit2-multipart“. But the problem here is, After uploading the image, the file got corrupted in the S3.

So my question is, Is retrofit multipart is fit for ASW S3 upload?
Do we have any solution to solve this issue?.

Please check my Implementation

Retrofit API Interface

 @Multipart
    @PUT
    Call<Void> uploadFile(@Url String url,
                          @Part MultipartBody.Part file);

Retrofit service creator

 private ApiServicesList createService() {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .readTimeout(300, TimeUnit.SECONDS)
                .connectTimeout(360, TimeUnit.SECONDS)
                .cache(null)
                .addInterceptor(new NetworkInterceptor(context))
                .addInterceptor(createLoggingInterceptor())
                .addInterceptor(createSessionExpiryInterceptor())
                .addInterceptor(createContextHeaderInterceptor())
                .build();

        return new Retrofit.Builder()
                .baseUrl(FirebaseConfig.getInstance().getStagingBaseURl())
                .addConverterFactory(GsonConverterFactory.create())
                .client(okHttpClient)
                .build()
                .create(ApiServicesList.class);
    }

File Upload Class

 public void uploadFileTos3(String url, MultipartBody.Part file, Callback<Void> listener) {
        Call<Void> call = mAPIServices.uploadFile(url,file);
        call.enqueue(listener);
    }

Presenter API Call

networkServices.uploadFileTos3(credentials.getSignedUrl(), prepareRequestBody(file), new Callback<Void>() {
            @Override
            public void onFailure(Call<Void> call, Throwable t) {
               //App Action
            }

            @Override
            public void
            onResponse(Call<Void> call, Response<Void> response) {
               //App Action
            }
        });

Request Body Method

 public static MultipartBody.Part prepareRequestBody(File file) {
        RequestBody requestFile = RequestBody.create(MediaType.parse(CONTENT_TYPE), file); // Checked Both "image/jpeg" and "multipart/form-data"
        return  MultipartBody.Part.createFormData("image", file.getName(), requestFile);
    }

DDMS LOGS

2019-04-10 19:07:13.926 18761-18874/com.xxx D/OkHttp: --> PUT https:Signed URL(Removed actual URL)
2019-04-10 19:07:13.926 18761-18874/com.xxx D/OkHttp: Content-Type: multipart/form-data; boundary=60561d1c-ff3f-4a43-8022-ca2be3e8ec4e
2019-04-10 19:07:13.926 18761-18874/com.xxx D/OkHttp: Content-Length: 71154
2019-04-10 19:07:13.931 18761-18874/com.xxx D/OkHttp: --60561d1c-ff3f-4a43-8022-ca2be3e8ec4e
2019-04-10 19:07:13.931 18761-18874/com.xxx D/OkHttp: Content-Disposition: form-data; name="image"; filename="forest-trees-fog-foggy.jpg"
2019-04-10 19:07:13.931 18761-18874/com.xxx D/OkHttp: Content-Type: image/jpeg
2019-04-10 19:07:13.931 18761-18874/com.xxx D/OkHttp: Content-Length: 70934
2019-04-10 19:07:13.931 18761-18874/com.xxx D/OkHttp: Image Body
2019-04-10 19:07:13.942 18761-18874/com.xxx D/OkHttp: --60561d1c-ff3f-4a43-8022-ca2be3e8ec4e--
2019-04-10 19:07:13.942 18761-18874/com.xxx D/OkHttp: --> END PUT (71154-byte body)
2019-04-10 19:07:15.648 18761-18874/com.xxx D/OkHttp: <-- 200 OK


Get this bounty!!!