Android Parcelable Issue - android

I had to pass a dataobject from one activity to another. The best way to do this is uing Parcelable.
The dataobject had some fields with setter and getter methods. After setting some fields and passing the object to another activity, wha tI observed is that the field values got interchanged to other field values.
The order of fields for writing to parcel and reading from parcel is the same.
public void writeToParcel(Parcel out, int flags) {
out.writeInt(id);
out.writeString(appNo);
out.writeString(this.policyNo);
out.writeInt((int)this.AppRcptDt.getTime());
out.writeString(this.currentStatus);
out.writeString(this.productCd);
out.writeDouble(this.sumAssured);
out.writeDouble(this.modalPremium);
out.writeDouble(this.annualPremium);
out.writeString(this.paymentMode);
out.writeString(this.branchCd);
out.writeString(this.branchName);
out.writeString(this.insuredName);
out.writeString(this.auraStatus);
out.writeString(this.ownerName);
out.writeString(this.agentCd);
out.writeString(this.billingMode);
}
private ApplicationTrackerDO(Parcel in) {
id=in.readInt();
this.appNo = in.readString();
this.policyNo = in.readString();
this.AppRcptDt = new Date(in.readLong());
this.currentStatus = in.readString();
this.productCd = in.readString();
this.sumAssured = in.readDouble();
this.modalPremium = in.readDouble();
this.annualPremium = in.readDouble();
this.paymentMode = in.readString();
this.branchCd = in.readString();
this.branchName = in.readString();
this.insuredName = in.readString();
this.auraStatus = in.readString();
this.ownerName = in.readString();
this.agentCd = in.readString();
this.billingMode = in.readString();
}

It is not the order but the data type that is not the same, from the first 4 lines you write int, string, string, int then you read int, string, string, long. I didn't check any further, you must match both order and datatype of read and write operations.

You are writing int
out.writeInt((int)this.AppRcptDt.getTime());
But reading long
this.AppRcptDt = new Date(in.readLong());

my solution to provide an date object with null
#Override
public void writeToParcel ( Parcel dest, int flags ) {
dest.writeInt((birthday != null) ? 1 : 0); // is birthday set?
dest.writeLong((birthday != null) ? birthday.getTime() : 0);
}
public void readFromParcel ( Parcel in ) {
if(in.readInt() == 1) {
birthday = new Date(in.readLong());
} else {
in.readLong(); // ignore stored value
birthday = null;
}
}

java.util.Date implements Serializable:
public class Date implements Serializable, Cloneable, Comparable<Date> {
private static final long serialVersionUID = 7523967970034938905L;
// Used by parse()
private static final int CREATION_YEAR = new Date().getYear();
private transient long milliseconds;
Use:
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeSerializable(myDateField);
}
private MyClass(Parcel in) {
myDateField = (Date)in.readSerializable();
}

Related

All queries in RoomDatabase return: The columns returned by the query does not have the fields

I have a problem with queries in RoomDatabase. I have a different queries and everything works good when I use SELECT statement with *. When I want to choose only name_product or amount it gives an error:
error: The columns returned by the query does not have the fields [id,amount,to_shop,cat_food,cat_package] in com.example.myapp.PojoClass even though they are annotated as non-null or primitive. Columns returned by the query: [name_product,amount]
LiveData<List<Items>> getItemNameAndAmount(int category);
One of my query:
#Query("SELECT name_product, amount FROM Table WHERE to_shop = 1 AND food_type = :category")
LiveData<List<Item_get>> getCategoryThingsToBuy(int category);
Problem is similar with this:
Android Room error: The columns returned by the query does not have the fields even though they are annotated as non-null or primitive
But I don't understand why this won't compile. Can somebody tell me?
In my PojoClass I have got a lot of different fields but only categories above are return as an error.
Why Android Studio doesn't throw me all of my Pojo fields as error? Not Only those above.
It throws errors in all queries statements not in one or two.
If it matter I have a empty constructor in my PojoClass.
EDIT:
My PojoClass
#Entity(tableName = "Table", indices = #Index(value = {"name_product"}, unique = true))
public class Item_get implements Parcelable {
#PrimaryKey(autoGenerate = true)
public int id;
#ColumnInfo(name = "name_product")
protected String name_product;
private String date_buy;
#ColumnInfo(name = "amount")
private int amount;
private Double price;
private Double value;
protected String date_exp;
protected String buy_place;
private String date_buy2;
private String buy_place2;
private Double price2;
private String date_buy3;
private String buy_place3;
private Double price3;
private int to_shop;
private int amount_toShop;
protected String actual_date;
private int cat_food;
protected int cat_package;
private int cat_packageToShop;
#TypeConverters(CategoriesConverter.class)
public Food_type food_type;
protected Item_get(Parcel in) {
id = in.readInt();
name_product = in.readString();
date_buy = in.readString();
amount = in.readInt();
if (in.readByte() == 0) {
price = null;
} else {
price = in.readDouble();
}
if (in.readByte() == 0) {
value = null;
} else {
value = in.readDouble();
}
date_exp = in.readString();
buy_place = in.readString();
date_buy2 = in.readString();
buy_place2 = in.readString();
if (in.readByte() == 0) {
price2 = null;
} else {
price2 = in.readDouble();
}
date_buy3 = in.readString();
buy_place3 = in.readString();
if (in.readByte() == 0) {
price3 = null;
} else {
price3 = in.readDouble();
}
to_shop = in.readInt();
actual_date = in.readString();
cat_food = in.readInt();
cat_package = in.readInt();
amount_toShop = in.readInt();
cat_packageToShop = in.readInt();
}
public static final Creator<Item_get> CREATOR = new Creator<Item_get>() {
#Override
public Item_get createFromParcel(Parcel in) {
return new Item_get(in);
}
#Override
public Item_get[] newArray(int size) {
return new Item_get[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(name_product);
dest.writeString(date_buy);
dest.writeInt(amount);
if (price == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeDouble(price);
}
if (value == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeDouble(value);
}
dest.writeString(date_exp);
dest.writeString(buy_place);
dest.writeString(date_buy2);
dest.writeString(buy_place2);
if (price2 == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeDouble(price2);
}
dest.writeString(date_buy3);
dest.writeString(buy_place3);
if (price3 == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeDouble(price3);
}
dest.writeInt(to_shop);
dest.writeString(actual_date);
dest.writeInt(cat_food);
dest.writeInt(cat_package);
dest.writeInt(amount_toShop);
dest.writeInt(cat_packageToShop);
}
public enum Food_type{
SWEETS(1),
VEGETABLES_FRUITS(2),
DRINKS(3),
OTHER(4);
private int code;
Food_type(int code){
this.code = code;
}
public int getCode(){
return code;
}
}
#TypeConverters(PackageTypeConverter.class)
public Package_type package_type;
public enum Package_type{
PACKAGE_BOX(1),
PIECE(2),
OTHER_PACK(3);
private int code;
Package_type(int code){
this.code = code;
}
public int getCode(){
return code;
}
}
public Item_get(){
}
To short of my code I didn't paste all constructors beacuse I use different in each class.
Also I skipped getters and setters. If it is necessarily I will paste it.

Parcelable object with enums in Android

In an android project i have a class with these fields:
public class TransactionHistoryDetail1 implements Parcelable, DatabaseEnabled{
private long id;
private static final String TABLE_NAME = "TransactionHistoryDetail";
private static final String EMPTY_STRING = "";
#XmlElement(name = "TxUd", required = true)
private String TxUd;
#XmlElement(name = "TxLclDtTm", required = true)
private Date TxLclDtTm;
#XmlElement(name = "CcyCd")
private CurrencyCode CcyCd;
#XmlElement(name = "Amt")
private BigDecimal Amt;
#XmlElement(name = "PmttpCd", required = true)
private PaymentTypeCode PmttpCd;
#XmlElement(name = "OprtnCd", required = true)
private OperationCode OprtnCd;
#XmlElement(name = "AppLabltpCd", required = true)
private AppLabelTypeCode AppLabltpCd;
#XmlElement(name = "PdSrl")
private String PdSrl;
#XmlElement(name = "PdBrndDsc")
private String PdBrndDsc;
#XmlElement(name = "UsrEml")
private String UsrEml;
#XmlElement(name = "CstmrAdr")
private String CstmrAdr;
#XmlElement(name = "TxDtlDsc")
private String TxDtlDsc;
#XmlElement(name = "TxRltdInd")
private boolean TxRltdInd;
#XmlElement(name = "TxSttsCd", required = true)
private TransactionStatusCode TxSttsCd;
#XmlElement(name = "UpdtDt", required = true)
private Date UpdtDt;
...
}
Im trying to Write and Read objects of this class as Parcelables but im not sure how to write and read the enums.
My writeToParcel method looks like this:
#Override
public void writeToParcel(Parcel dest, int flags) {
SimpleDateFormat sdf = new SimpleDateFormat(JsonBuilder.DateFormat);
dest.writeLong(id);
dest.writeDouble(Amt.doubleValue());
dest.writeString(PdSrl);
dest.writeString(PdBrndDsc);
dest.writeString(TxUd);
dest.writeString(PdSrl);
dest.writeString(UsrEml);
dest.writeString(CstmrAdr);
dest.writeString(TxDtlDsc);
dest.writeString((CcyCd == null) ? "" : CcyCd.name());
dest.writeString((PmttpCd == null) ? "" : PmttpCd.name());
dest.writeString((OprtnCd == null) ? "" : OprtnCd.name());
dest.writeString((AppLabltpCd == null) ? "" : AppLabltpCd.name());
dest.writeString(sdf.format(TxLclDtTm));
dest.writeString(sdf.format(UpdtDt));
dest.writeByte((byte) (TxRltdInd ? 1 : 0));
}
and my Constructor with Parcel looks like this
private TransactionHistoryDetail1(Parcel in) {
SimpleDateFormat sdf = new SimpleDateFormat(JsonBuilder.DateFormat);
try {
TxLclDtTm = sdf.parse(in.readString());
UpdtDt = sdf.parse(in.readString());
} catch (ParseException e) {
e.printStackTrace();
}
id = in.readLong();
TxUd = in.readString();
PdSrl = in.readString();
PdBrndDsc = in.readString();
UsrEml = in.readString();
CstmrAdr = in.readString();
TxDtlDsc = in.readString();
TxRltdInd = in.readByte() != 0;
Amt = new BigDecimal(in.readDouble());
CcyCd = CurrencyCode.valueOf(in.readString());
PmttpCd = PaymentTypeCode.valueOf(in.readString());
OprtnCd = OperationCode.valueOf(in.readString());
AppLabltpCd = AppLabelTypeCode.valueOf(in.readString());
TxSttsCd = TransactionStatusCode.fromValue(in.readString());
}
The writeToParcel i belive its working well, but the constructor is crashing at the "CcyCd" line.
My CurrencyCode class is a enum, (so are PaymentTypeCode,OperationCode and AppLabelTypeCode) that looks like this:
#XmlType(name = "CurrencyCode")
#XmlEnum
public enum CurrencyCode {
EUR;
public String value() {
return name();
}
public static CurrencyCode fromValue(String v) {
return valueOf(v);
}
}
Is there another way to deal with enums in Parcelables?
The exception i get is this:
java.lang.RuntimeException: Unable to start activity ComponentInfo{package/package.activities.ChildActivity}: java.lang.IllegalArgumentException: No enum constant package.data.apiClasses.CurrencyCode.��EUR����CASH������CLS����APP����2017-04-10T09:07:52.525Z������2017-04-10T09:07:52.528Z����������CHILD_12345������?
First of all you should read from the Parcel in the exact order that you wrote to it. Since Parcel just write and read data in order instead of actually serializing data you have to keep read and write in order else you gonna read wrong values and getting error..
It is the best if you treat Enum as int, write them to parcel like this:
dest.writeInt(this.CcyCd == null ? -1 : this.CurrencyCode.ordinal());
and read them like this:
int tmpCurrencyCode = in.readInt();
this.CcyCd = tmpCurrencyCode == -1 ? null : CurrencyCode.values()[tmpMState];
P.S: This code check for null values too ^^
I had problem parsing Nullable Enum. If this is your case, look up here
https://stackoverflow.com/a/58337932/5980046

Android Parcelable object return empty values

I am using parcelable to pass class to new activity. However, at receiving side, I get empty values. It is strange that I get empty values and not null values. However, I do expect some values in each attribute. I have checked that the attributes are not empty at the caller part. Why is this so?
Here is my implementation:
Call new activity
Intent intent = new Intent(ProductDetailsActivity.this, ShopActivity.class);
intent.putExtra(ShopActivity.KEY_COMPANY, products.get(currentTypePosition).companyDetails);
startActivity(intent);
Receive
Company company = getIntent().getParcelableExtra(KEY_COMPANY);
Parcelable
public class Company implements Parcelable {
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public Company createFromParcel(Parcel in) {
return new Company(in);
}
public Company[] newArray(int size) {
return new Company[size];
}
};
// TODO: Remove default values once backend is completed
public ArrayList<CompanyProduct> companyProducts = getDefaultCompanyProducts();
public String name = "hello";
public int icon = 0;
public int productCount = 100;
public int followerCount = 9000;
public String location = "hello";
public String contact = "400-23729";
public String description = "hello";
public int storeCount = 100;
public Company() {
super();
}
public Company(Parcel in) {
in.readTypedList(companyProducts, Status.CREATOR);
name = in.readString();
icon= in.readInt();
productCount = in.readInt();
followerCount = in.readInt();
location = in.readString();
contact = in.readString();
description = in.readString();
storeCount = in.readInt();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedList(companyProducts);
dest.writeString(name);
dest.writeInt(icon);
dest.writeInt(productCount);
dest.writeInt(followerCount);
dest.writeString(location);
dest.writeString(contact);
dest.writeString(description);
dest.writeInt(storeCount);
}
}

ClassNotFoundException when unmarshalling list of parcelable

I'm trying to send an object between two activities.
The order Object contains a list of item witch I implemented like this:
OrderItem Object:
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeParcelable(priceTableItem, flags);
dest.writeInt(qunatity);
dest.writeDouble(value); // quantity * unitValue
dest.writeDouble(discount);
}
protected OrderItem(Parcel in) {
id = in.readInt();
priceTableItem = in.readParcelable(PriceTableItem.class.getClassLoader());
quantity = in.readInt();
value = in.readDouble();
discount = in.readDouble();
}
At the PriceTableItem I have a situation where it can contais a product id or a "grade" id ("grade" is when the product have color and size) but never have both values.
so I implemented like this:
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeParcelable(priceTable, flags);
dest.writeValue(produto);
dest.writeValue(grade);
dest.writeDouble(unitPrice);
dest.writeByte((byte) (isActive ? 1 : 0));
}
protected PriceTableItem(Parcel in) {
id = in.readInt();
priceTable = in.readParcelable(PriceTable.class.getClassLoader());
product = (Product) in.readValue(Product.class.getClassLoader());
grade = (Grade) in.readValue(Grade.class.getClassLoader());
unitPrice = in.readDouble();
isactive = in.readByte() != 0;
}
The problem occur when I pass the order object from my OrderListActivity to OrderDetailActivity. It read all attributes before my list of item. When it try to read the PriceTable on OrderItem I get:
java.lang.RuntimeException: Unable to start activity ComponentInfo{br.com.intelecto.intesigmobile/br.com.intelecto.intesigmobile.activity.PedidoDetailActivity}: android.os.BadParcelableException: ClassNotFoundException when unmarshalling:
The problem line is:
priceTableItem = in.readParcelable(PriceTableItem.class.getClassLoader());
Any ideas on how to solve this?
Still don't know what caused the error, but I solved the problem like bellow
When I was passing the order value I was using only the Intent to do it, like this:
Intent i = new Intent(this, OrderDetailActivity.class);
i.putExtras("order", order);
startActivity(i);
And, to read it I was doing like this:
Order order = getIntent().getParcelableExtra("order");
So, I used a Bundle for pass the value.
Intent i = new Intent(this, OrderDetailActivity.class);
Bundle b = new Bundle();
b.putParcelable("order", order);
i.putExtras(b);
startActivity(i);
And
Bundle b = getIntent().getExtras();
Order order = b.getParcelable("order");
I had same error and the lines causing the error were these:
ingredients = in.readParcelable(Ingredient.class.getClassLoader());
and
public static final Parcelable.Creator<RecipeContent> CREATOR = new Parcelable.Creator<RecipeContent>() {
#Override
public RecipeContent createFromParcel(Parcel in) {
return new RecipeContent(in);
}
So, what I did and it helped was to arrange the in.read items in the same way as the values in the Parcel are arranged.
Here are the details:
public RecipeContent(int id, String recipeName, List<Ingredient> ingredients,
List<BakingStep> bakingSteps, String recipeImage) {
this.id = id;
this.recipeName = recipeName;
this.ingredients = ingredients;
this.bakingSteps = bakingSteps;
this.recipeImage = recipeImage;
}
And then using the same order for the in.read:
public RecipeContent(Parcel in) {
id = in.readInt();
recipeName = in.readString();
ingredients = in.readParcelable(Ingredient.class.getClassLoader());
bakingSteps = in.readParcelable(BakingStep.class.getClassLoader());
recipeImage = in.readString();
}
Hope this helps for you too.

How to implement Parcelable for a class with String[] and byte[] fields?

I'm attempting to implement parcelable for the a class with following fields. Im getting an exception when attempting to create the class from the parcel (put in a bundle) on the fields String mStyle[] and byte[] mImage .I'm not receiving any errors on these fields on writeToParcel-- what is the correct usage?. thanks much
private String mClothingItemName;
private String mColor;
private String mPrint;
private String mStyle[];
private String mMaterial;
private String mBrand;
private String mStorageLocation;
private String mOptionalDescription;
private byte[] mImage;
public void writeToParcel(Parcel out, int flags) {
out.writeString(mClothingItemName);
out.writeLong(mClothesId);
out.writeString(mColor);
out.writeString(mPrint);
//out.writeStringArray(mStyle);
out.writeString(mMaterial);
out.writeString(mBrand);
out.writeString(mStorageLocation);
out.writeString(mOptionalDescription);
// out.writeByteArray(mImage);
}
private Clothes(Parcel in) {
mClothingItemName = in.readString();
mClothesId = in.readLong();
mColor = in.readString();
mPrint = in.readString();
// in.readStringArray(mStyle);
mMaterial = in.readString();
mBrand = in.readString();
mStorageLocation = in.readString();
mOptionalDescription = in.readString();
//in.readByteArray(mImage);
}
I recommend you use the website link , from a class will generate the code to make it parceable.

Categories

Resources