0

Whenever I try to pass information between 2 activities by using intent, my app crashes and gives me this exception:

java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.example.poop123.FoodItem)

I can't possibly find a thread with an answer that resolves my issue.

foodLibrary.class

package com.example.poop123;

import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultCaller;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContract;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;
import android.widget.Toast;

import com.gigamole.navigationtabstrip.NavigationTabStrip;

import java.io.Serializable;
import java.util.ArrayList;


public class foodLibrary extends AppCompatActivity implements Serializable{

    ArrayList<FoodItem> foodItems = new ArrayList<>();

    boolean itemsExist = false;

    RecyclerView rv;

    ImageView closeArrow;
    ImageView addItem;

    FoodItem item;

    ActivityResultLauncher<Intent> activityLauncher = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            new ActivityResultCallback<ActivityResult>() {
                @Override
                public void onActivityResult(ActivityResult result) {

                    if (result.getResultCode() == 78) {
                        Intent intent = result.getData();

                        if (intent != null) {
                            item = (FoodItem) intent.getSerializableExtra("123");
                        }
                    }

                }
            }
    );

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.create_foods_menu, menu);
        return true;
    }


    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
            case R.id.addFood:
                Toast.makeText(this, "Yooo", Toast.LENGTH_SHORT).show();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_food_library);
        rv = findViewById(R.id.recycler);

        closeArrow = findViewById(R.id.arrow_foods);
        addItem = findViewById(R.id.add_button);

        Intent i = getIntent();
        item = (FoodItem) i.getSerializableExtra("123");

        if (itemsExist) {
            generateRecycler(item);
            adapterConnect();
        } else {
            itemsExist = true;
        }


        closeArrow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });

        addItem.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                openMenu();
            }
        });



    }

    private void generateRecycler(FoodItem item) {
        foodItems.add(item);
    }

    private void adapterConnect() {
        FoodRecyclerAdapter adapter = new FoodRecyclerAdapter(getApplicationContext(), item ,foodItems);
        rv.setAdapter(adapter);
        rv.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
    }


    private void openMenu() {
        PopupMenu popup = new PopupMenu(this, addItem);
        MenuInflater inflater = popup.getMenuInflater();
        inflater.inflate(R.menu.create_foods_menu, popup.getMenu());
        popup.show();
    }

    public void openNewFoodMenu (MenuItem item){  // ONCLICKLISTENER ESTÁ NO FICHEIRO XML
        Intent intent = new Intent(foodLibrary.this, newFoodMenu.class);
        activityLauncher.launch(intent);
    }

}

newFoodMenu.class

package com.example.poop123;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.DialogFragment;

import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.io.Serializable;

public class newFoodMenu extends AppCompatActivity implements SingleChoiceDialog.SingleChoiceListener, Serializable {

    ImageView closeButton;
    TextView measurementSelector;
    RelativeLayout saveButton;
    String asterisco;

    public String sDescription; public String sBrand; public String sBarcode; public String sServing; public String sMeasurement; public String sCalories; public String sFat; public String sCarbohydrate; public String sProtein;

    public EditText eDescription; public EditText eBrand; public EditText eBarcode; public EditText eServing; public EditText eCalories; public EditText eFat; public EditText eCarbohydrate; public EditText eProtein;

    public TextView tDescription;
    public TextView tBrand;
    public TextView tBarcode;
    public TextView tServing;
    public TextView tMeasurement;
    public TextView tCalories;
    public TextView tFat;
    public TextView tCarbohydrate;
    public TextView tProtein;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_new_food_menu);

        closeButton = findViewById(R.id.close_button);
        saveButton = findViewById(R.id.button_save);

        eDescription = (EditText) findViewById(R.id.etDescription);
        eBrand = (EditText) findViewById(R.id.etBrand);
        eBarcode = (EditText) findViewById(R.id.etBarcode);
        measurementSelector = findViewById(R.id.measurementUnitsSelector);
        eServing = (EditText) findViewById(R.id.etServing);
        eCalories = (EditText) findViewById(R.id.etCalories);
        eFat = (EditText) findViewById(R.id.etFat);
        eCarbohydrate = (EditText) findViewById(R.id.etCarbohydrate);
        eProtein = (EditText) findViewById(R.id.etProtein);

        tDescription = (TextView) findViewById(R.id.tvDescription);
        tBrand = (TextView) findViewById(R.id.tvBrand);
        tBarcode = (TextView) findViewById(R.id.tvBarcode);
        tServing = (TextView) findViewById(R.id.tvServing);
        tMeasurement = (TextView) findViewById(R.id.tvMeasurement);
        tCalories = (TextView) findViewById(R.id.tvCalories);
        tFat = (TextView) findViewById(R.id.tvFat);
        tCarbohydrate = (TextView) findViewById(R.id.tvCarbohydrate);
        tProtein = (TextView) findViewById(R.id.tvProtein);

        asterisco = "*";



        closeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }

        });

        measurementSelector.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DialogFragment scd = new SingleChoiceDialog();
                scd.setCancelable(false);
                scd.show(getSupportFragmentManager(), "Single Choice Dialog");
            }
        });

        saveButton.setOnClickListener(new View.OnClickListener() {
            @Override

            public void onClick(View v) {

                sDescription = eDescription.getText().toString();
                sBrand = eBrand.getText().toString();
                sBarcode = eBarcode.getText().toString();
                sServing = eServing.getText().toString();
                sCalories = eCalories.getText().toString();
                sFat = eFat.getText().toString();
                sCarbohydrate = eCarbohydrate.getText().toString();
                sProtein = eProtein.getText().toString();

                verifyFields();

            }
        });

    }

    private void createItem(String description, String brand, String serving, String calories, String carbohydrates, String protein, String fats, TextView selector) {


        FoodItem item = new FoodItem(description, brand, serving, calories, carbohydrates, protein, fats, selector);

        Intent intent = new Intent();
        intent.putExtra("123", item);
        setResult(78, intent);

        finish();


    }

    public void verifyFields() {

        if (checkEmpty()) {
            if (sDescription.isEmpty()) {
                fieldStatusWrong(tDescription, "Description*");
            } else if (!sDescription.isEmpty()) {
                fieldStatusCorrect(tDescription, "Description");
            }

            if (sServing.isEmpty()) {
                fieldStatusWrong(tServing, "By serving of*");
            } else if (!sServing.isEmpty()) {
                fieldStatusCorrect(tServing, "By serving of");
            }

            if (sCalories.isEmpty()) {
                fieldStatusWrong(tCalories, "Calories (kcal)*");
            } else if (!sCalories.isEmpty()) {
                fieldStatusCorrect(tCalories, "Calories (kcal)");
            }

            if (sFat.isEmpty()) {
                fieldStatusWrong(tFat, "Fat (g)*");
            } else if (!sFat.isEmpty()) {
                fieldStatusCorrect(tFat, "Fat (g)");
            }

            if (sCarbohydrate.isEmpty()) {
                fieldStatusWrong(tCarbohydrate, "Carbohydrate (g)*");
            } else if (!sCarbohydrate.isEmpty()) {
                fieldStatusCorrect(tCarbohydrate, "Carbohydrate (g)");
            }

            if (sProtein.isEmpty()) {
                fieldStatusWrong(tProtein, "Protein (g)*");
            } else if (!sProtein.isEmpty()) {
                fieldStatusCorrect(tProtein, "Protein (g)");

            }
        }  if (!checkEmpty()) {
            createItem(sDescription, sBrand, sServing, sCalories, sFat, sCarbohydrate, sProtein, measurementSelector);
        }


    }

    private void fieldStatusWrong(TextView t, String text) {
        if (t.getText().toString().equals(text)) {
            t.setTextColor(Color.parseColor("#ff0000"));
        } else {
            t.setTextColor(Color.parseColor("#ff0000"));
            t.setText(text);
        }
    }
    private void fieldStatusCorrect(TextView t, String text) {

        if (t.getText().toString().equals(text)) {
            t.setTextColor(Color.parseColor("#C2C2C2"));
        } else {
            t.setTextColor(Color.parseColor("#C2C2C2"));
            t.setText(t.getText().toString().substring(0, t.length()-1));
        }

    }

    private boolean checkEmpty() {
        if (sDescription.isEmpty() || sServing.isEmpty() || sCalories.isEmpty() || sFat.isEmpty() || sCarbohydrate.isEmpty() || sProtein.isEmpty()) {
            return true;
        }
        return false;
    }


    @Override
    public void onPositiveButtonClicked(String[] list, int position) {
        measurementSelector.setText(list[position]);
    }

    @Override
    public void onNegativeButtonClicked() {

    }

}

FoodItem.class

package com.example.poop123;

import android.widget.TextView;

import org.w3c.dom.Text;

import java.io.Serializable;

public class FoodItem implements Serializable {

    String description, brand, serving, calories, carbohydrates, protein, fats;
    TextView measurementUnit;


    public FoodItem(String description, String brand, String serving, String calories, String carbohydrates, String protein, String fats, TextView measurementUnit) {
        this.description = description;
        this.brand = brand;
        this.serving = serving;
        this.calories = calories;
        this.carbohydrates = carbohydrates;
        this.protein = protein;
        this.fats = fats;
        this.measurementUnit = measurementUnit;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getServing() {
        return serving;
    }

    public void setServing(String serving) {
        this.serving = serving;
    }

    public String getCalories() {
        return calories;
    }

    public void setCalories(String calories) {
        this.calories = calories;
    }

    public String getCarbohydrates() {
        return carbohydrates;
    }

    public void setCarbohydrates(String carbohydrates) {
        this.carbohydrates = carbohydrates;
    }

    public String getProtein() {
        return protein;
    }

    public void setProtein(String protein) {
        this.protein = protein;
    }

    public String getFats() {
        return fats;
    }

    public void setFats(String fats) {
        this.fats = fats;
    }

    public TextView getMeasurementUnit() {
        return measurementUnit;
    }

    public void setMeasurementUnit(TextView measurementUnit) {
        this.measurementUnit = measurementUnit;
    }
}

FULL error message

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.poop123, PID: 23203
    java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.example.poop123.FoodItem)
        at android.os.Parcel.writeSerializable(Parcel.java:2113)
        at android.os.Parcel.writeValue(Parcel.java:1883)
        at android.os.Parcel.writeArrayMapInternal(Parcel.java:975)
        at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620)
        at android.os.Bundle.writeToParcel(Bundle.java:1303)
        at android.os.Parcel.writeBundle(Parcel.java:1044)
        at android.content.Intent.writeToParcel(Intent.java:10855)
        at android.app.IActivityTaskManager$Stub$Proxy.finishActivity(IActivityTaskManager.java:4260)
        at android.app.Activity.finish(Activity.java:6376)
        at android.app.Activity.finish(Activity.java:6412)
        at com.example.poop123.newFoodMenu.createItem(newFoodMenu.java:120)
        at com.example.poop123.newFoodMenu.verifyFields(newFoodMenu.java:165)
        at com.example.poop123.newFoodMenu$3.onClick(newFoodMenu.java:104)
        at android.view.View.performClick(View.java:7448)
        at android.view.View.performClickInternal(View.java:7425)
        at android.view.View.access$3600(View.java:810)
        at android.view.View$PerformClick.run(View.java:28305)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
     Caused by: java.io.NotSerializableException: com.google.android.material.textview.MaterialTextView
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1240)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:354)
        at android.os.Parcel.writeSerializable(Parcel.java:2108)
        at android.os.Parcel.writeValue(Parcel.java:1883) 
        at android.os.Parcel.writeArrayMapInternal(Parcel.java:975) 
        at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620) 
        at android.os.Bundle.writeToParcel(Bundle.java:1303) 
        at android.os.Parcel.writeBundle(Parcel.java:1044) 
        at android.content.Intent.writeToParcel(Intent.java:10855) 
        at android.app.IActivityTaskManager$Stub$Proxy.finishActivity(IActivityTaskManager.java:4260) 
        at android.app.Activity.finish(Activity.java:6376) 
        at android.app.Activity.finish(Activity.java:6412) 
        at com.example.poop123.newFoodMenu.createItem(newFoodMenu.java:120) 
        at com.example.poop123.newFoodMenu.verifyFields(newFoodMenu.java:165) 
        at com.example.poop123.newFoodMenu$3.onClick(newFoodMenu.java:104) 
        at android.view.View.performClick(View.java:7448) 
        at android.view.View.performClickInternal(View.java:7425) 
        at android.view.View.access$3600(View.java:810) 
        at android.view.View$PerformClick.run(View.java:28305) 
        at android.os.Handler.handleCallback(Handler.java:938) 
        at android.os.Handler.dispatchMessage(Handler.java:99) 
        at android.os.Looper.loop(Looper.java:223) 
        at android.app.ActivityThread.main(ActivityThread.java:7656) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 

DontReadThisTextJustFillingInSoStackOverflowAllowsMeToPostThisQuestionAsIHaveProvidedEnoughInformationAlready

  • Read your error messages. You don't show code of the one class that is the problem here. All other code is pretty much useless. – M. Prokhorov Jan 26 '22 at 10:21
  • No, not true at all, it is specfically these two classes where the transfer of the object occurs, there is no other class where this procedure takes place, in fact, whenever I remove the code to transfer the data, the app works fine, obviously without the feature I want. @M.Prokhorov – KingSwoozie Jan 26 '22 at 10:24
  • 1
    https://stackoverflow.com/questions/23142893/parcelable-encountered-ioexception-writing-serializable-object-getactivity Hope this helps. – Al-Amin Jan 26 '22 at 10:25
  • @KingSwoozie, again - read your error message. Exception happens when trying to (de)serialize a class called `FoodItem`, that you don't show the code for. All other classes where this supposedly happens inside are of no consequence, because you don't implement (de)serialization yourself, you just call system facilities to do it. – M. Prokhorov Jan 26 '22 at 10:26
  • @M.Prokhorov Ah, excuse my ignorance, how can I provide the remaining FoodItem class, do I have to remake this question or? – KingSwoozie Jan 26 '22 at 10:34
  • No, just edit this one. I'd say you can pretty much delete all the code except for `FoodItem` class and whatever other custom classes it has for fields. – M. Prokhorov Jan 26 '22 at 10:35
  • @KingSwoozie, so, seeing what your `FoodItem` looks like - you should replace `measurementUnit` property from `TextView` to simple `String`, and all else should work as expected (once you fix all compile errors appropriately, that is). In a rule of thumb, you shouldn't pass around UI Views like this. – M. Prokhorov Jan 26 '22 at 17:11
  • @M.Prokhorov, I appreciate your observation, I forgot to convert it to a String, but I'm still left with the same problems – KingSwoozie Jan 26 '22 at 17:21
  • @KingSwoozie, that shouldn't be possible if you converted the View to String and recompiled your code. Is it still the same exception even after a clean build with new `FoodItem` class version? – M. Prokhorov Jan 27 '22 at 15:13
  • Never mind! For some reason yesterday, whenever I compiled I still got the same problem, but now all is fine, thank you very much!! – KingSwoozie Jan 27 '22 at 16:43

1 Answers1

0

You have to make FoodItem implements Serializable for pass fooditem object from one activity to another.

try this.

public class FoodItem implements Serializable

Make sure to validate null safety on fooditem object for prevent app crash on object receiving activiy.

Kashyap Rathod
  • 275
  • 1
  • 9