Open Pdf at Previous Page Number where it user left - java

I am tring to open the recent pdf file at page number from firebase How to Pick Up Reading Where User Left it.
I am Creating a Model Class of Mutiple PDF book and fetch online.
how i can open the recent page that i left in firebase.
public class ModelPdf implements Parcelable {
private String images;
private String name;
private String url;
public ModelPdf() {
}
public ModelPdf(String images, String name, String url) {
//parameterized constructor
}
protected ModelPdf(Parcel in) {
images = in.readString();
name = in.readString();
url = in.readString();
}
public static final Creator<ModelPdf> CREATOR = new Creator<ModelPdf>() {
#Override
public ModelPdf createFromParcel(Parcel in) {
return new ModelPdf(in);
}
#Override
public ModelPdf[] newArray(int size) {
return new ModelPdf[size];
}
};
// rest getter and setter methods of class attribute
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(images);
dest.writeString(name);
dest.writeString(url);
}
}

You can use SharedPreferences to store current page value and then use it.

Related

How to pass a Parcelable class which contains a list of another parcelable class?

I'm trying to pass a Parcelable class from one Activity to another. I do it like this:
Intent intent = new Intent(ClosedChatActivity.this, AdminProfileActivity.class);intent.putExtra("adminProfile", adminProfile);
startActivity(intent);
And then get it in the other Activity like this:
adminProfile = (AdminProfile) getIntent().getExtras().getParcelable("adminProfile");
This is the AdminProfile class and the WebLink class it has inside:
public class AdminProfile implements Parcelable {
public static final Creator<AdminProfile> CREATOR = new Creator<AdminProfile>() {
#Override
public AdminProfile createFromParcel(Parcel in) {
return new AdminProfile(in);
}
#Override
public AdminProfile[] newArray(int size) {
return new AdminProfile[size];
}
};
public Long idUser;
public String name;
public String professio;
public String description;
public List<WebLink> webLinks;
public Long idOficina;
protected AdminProfile(Parcel in) {
idUser = in.readLong();
name = in.readString();
professio = in.readString();
description = in.readString();
webLinks = in.createTypedArrayList(WebLink.CREATOR);
idOficina = in.readLong();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeLong(idUser);
parcel.writeString(name);
parcel.writeString(professio);
parcel.writeString(description);
parcel.writeLong(idOficina);
parcel.writeTypedList(webLinks);
}
}
public class WebLink implements Parcelable {
public static final Creator<WebLink> CREATOR = new Creator<WebLink>() {
#Override
public WebLink createFromParcel(Parcel in) {
return new WebLink(in);
}
#Override
public WebLink[] newArray(int size) {
return new WebLink[size];
}
};
public String name;
public String url;
protected WebLink(Parcel in) {
name = in.readString();
url = in.readString();
}
#Override
public boolean equals(#Nullable Object obj) {
WebLink webLink = (WebLink) obj;
assert webLink != null;
return this.name.equals(webLink.name) && this.url.equals(webLink.url);
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(name);
parcel.writeString(url);
}
}
When I get the object, the two Strings in it aren't the same I sent. Why is that?
The weird thing is that I have another Parcelable class which contains an AdminProfile, and when sending that class it does send fine with the Weblinks included, but if I send only an AdminProfile somewhere in the way it fails.
When you read and write Parcelable classes, you need to make sure that the order of the elements is exactly the same.
You are writing idOficina followed by WebLinks, but you are reading them in the opposite order.

How to pass objects within objects between activities with parcelable

Im pretty new in Android Studio.
I'm trying to pass an ArrayList from one activity to another using parcelable. Within the class Recipe I declare another ArrayList which I cannot get a hold of when starting the other activity.
Recipe.java:
public class Recipe implements Parcelable {
String name;
ArrayList<Ingredient> ingredients;
public Recipe(String name){
this.name = name;
this.ingredients = new ArrayList<>();
}
protected Recipe(Parcel in) {
name = in.readString();
}
public static final Creator<Recipe> CREATOR = new Creator<Recipe>() {
#Override
public Recipe createFromParcel(Parcel in) {
return new Recipe(in);
}
#Override
public Recipe[] newArray(int size) {
return new Recipe[size];
}
};
public void addIngredients(String[] amountList, String[] ingredientList, String[] unitList) {
for (int i = 0; i < ingredientList.length; i++) {
ingredients.add(new Ingredient(ingredientList[i], Double.parseDouble(amountList[i]), unitList[i]));
}
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(name);
}
}
Ingredient.java:
public class Ingredient implements Parcelable {
private String ingrdnt;
private double amount;
private String unit;
private String cat;
private boolean checkedItem;
public Ingredient(String ingrdnt, double amount, String unit) {
this.ingrdnt = ingrdnt;
this.amount = amount;
this.unit = unit;
//this.cat = category;
this.checkedItem = false;
}
protected Ingredient(Parcel in) {
ingrdnt = in.readString();
amount = in.readDouble();
unit = in.readString();
cat = in.readString();
checkedItem = in.readByte() != 0;
}
public static final Creator<Ingredient> CREATOR = new Creator<Ingredient>() {
#Override
public Ingredient createFromParcel(Parcel in) {
return new Ingredient(in);
}
#Override
public Ingredient[] newArray(int size) {
return new Ingredient[size];
}
};
public double getAmount() {
return amount;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(ingrdnt);
parcel.writeDouble(amount);
parcel.writeString(unit);
parcel.writeString(cat);
parcel.writeByte((byte) (checkedItem ? 1 : 0));
}
}
In main:
private ArrayList<Recipe> recipes = new ArrayList<>();
//recipes obviously holds a bunch of recipes so it's not empty.
intent.putExtra("recipes", recipes);
System.out.println(recipes.get(0).ingredients.get(0).getAmount());
System.out: 2.0
In second activity:
recipes = this.getIntent().getParcelableArrayListExtra("recipes");
//Same print as above
System.out.println(recipes.get(0).ingredients.get(0).getAmount());
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference
Have I implemented the parcelable in a wrong way or why can I not get a hold of the Ingredient objects?
I've read about other ways to pass objects between activities but it seems like parcelable might be the best way to do it.
Yes, you basically forgot to write the ingredients of the Recipe to the output Parcel which is given to the Recipe.writeToParcel method.
You can write the ArrayList<Parcelable> with writeTypedList and read it back with readTypedList.
So your Recipe constructor which accepts a Parcel should be like:
protected Recipe(Parcel in) {
name = in.readString();
ingredients = new ArrayList<>();
in.readTypedList(ingredients, Ingredient.CREATOR);
}
while your writeToParcel of the Recipe should become:
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(name);
parcel.writeTypedList(ingredients);
}
The NullPointerException you are seeing is caused by the fact that you do not allocate a new ArrayList in the constructor of Recipe which accepts a Parcel, so when you call recipes.get(0).ingredients.get(0).getAmount() in the second Activity the ingredients ArrayList is null, thus the Exception.
Also note (but not related to the problem) that there exist a writeBoolean and a readBoolean with which you can write and read values of type boolean (I am saying this for the Ingredient class implementation).
Try those out and let us know if it worked properly.

How to pass a custom object with a 2D ArrayList field using Parcelable

Inside my Exercise class, I have a 2D ArrayList. I have managed to pass all of the fields from Activity to another using Parcelable. However, I cannot figure out how to pass the 2D ArrayList within my object using Parcelable.
public class Exercise implements Parcelable{
private String name, equipmentRequired;
private ArrayList musclesWorked;
private HashMap personalBest;
private boolean selected;
private float minAccelLevel, minAccelChanges;
private ArrayList<ArrayList<Double>> sets = new ArrayList<>();
...
private Exercise(Parcel in) {
name = in.readString();
equipmentRequired = in.readString();
musclesWorked = in.readArrayList(ArrayList.class.getClassLoader());
personalBest = in.readHashMap(HashMap.class.getClassLoader());
selected = in.readInt() != 0;
// sets = ???????
}
public static final Parcelable.Creator<Exercise> CREATOR = newParcelable.Creator<Exercise>() {
public Exercise createFromParcel(Parcel in) {
return new Exercise(in);
}
public Exercise[] newArray(int size) {
return new Exercise[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(equipmentRequired);
dest.writeList(musclesWorked);
dest.writeMap(personalBest);
dest.writeInt(selected ? 1 : 0);
// ?????
}
}
According to Google Documentation and this other question, I would suggest going with
private Exercise(Parcel in) {
name = in.readString();
equipmentRequired = in.readString();
musclesWorked = in.readArrayList(ArrayList.class.getClassLoader());
personalBest = in.readHashMap(HashMap.class.getClassLoader());
selected = in.readInt() != 0;
sets = in.readArrayList(null);
}
This would be because, as the doc states:
The given class loader will be used to load any enclosed Parcelables.
Managed to solve the problem myself. Thanks.
...
private Exercise(Parcel in) {
...
sets = in.readArrayList(ArrayList.class.getClassLoader());
}
#Override
public void writeToParcel(Parcel dest, int flags) {
...
dest.writeList(sets);
}
}

Parcelable is really usefull?

I tried to send a parcel from the mainActivity to a fragment and i noticed a strange effect.
When you implement parcelable, android require to implement "writeToParcel" and "describeContents".
The strange effect is, if you write something inside "writeToParcel" or nothing, it doesn't matter. Android never call it.
Why these functions are required ?
Here is a working source code :
public class Movie implements Parcelable {
private String title;
private Float score;
public Movie(String title, float score) {
this.title = title;
this.score = score;
}
...... Getter and Setter......
//Parcelable Methods
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
// Don't need to write anything in this area
/*
dest.writeString(title);
dest.writeFloat(score);
*/
}
public static final Parcelable.Creator<Movie> CREATOR = new Parcelable.Creator<Movie>() {
//--------------> You can return null, it's never called and work perfectly!
public Movie createFromParcel(Parcel in) {
return null;//new Movie(in);
}
public Movie[] newArray(int size) {
return null;//new Movie[size];
}
};
}
Any idear ?
Regards,

putParcelableArrayListExtra and black screen

I have custom class that implements Parcelable and I use it as custom arraylist.
When I use putParcelableArrayListExtra and 400 rows it works fine, but 1000 rows it does not. I have black screen and app locks up. What is wrong?
EDIT:
I sent it here and I don't use it in another Activity.
Intent intent = new Intent().setClass(getApplicationContext(), ArtActivity.class);
intent.putParcelableArrayListExtra ("mylist", list);
startActivityForResult(intent, SECONDARY_ACTIVITY_REQUEST_CODE);
My array:
ArrayList<Piece> list = new ArrayList<Piece>();
It is my Class:
public class Piece implements Parcelable {
private String id;
private String name;
private int type;
private String text;
private String mp3;
public Piece (String id,String name,int type)
{
this.id=id;
this.name=name;
this.type=type;
}
public Piece(Piece ele)
{
this.id=ele.id;
this.name=ele.name;
this.type=ele.type;
this.text=ele.text;
}
public Piece (Parcel in)
{
id = in.readString ();
name = in.readString ();
type = in.readInt();
text= in.readString();
mp3=in.readString();
}
public static final Parcelable.Creator<Piece> CREATOR
= new Parcelable.Creator<Piece>()
{
public Piece createFromParcel(Parcel in)
{
return new Piece(in);
}
public Piece[] newArray (int size)
{
return new Piece[size];
}
};
public void makeText(String text)
{
this.text=text;
}
public void makeMp3(String mp3)
{
this.mp3= mp3;
}
public String getMp3()
{
return this.mp3;
}
public String getId()
{
return id;
}
public String getName()
{
return name;
}
public int getType()
{
return type;
}
public String getText()
{
return text;
}
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeString (id);
dest.writeString (name);
dest.writeInt(type);
dest.writeString (text);
dest.writeString (mp3);
}
}
I do not believe you should be using parcelable in this case. I would either access the data statically (if you only intend to have one persistent instance of the data), or use a caching system to hold onto the data.
This is an example of a publicly available static variable:
public static List<Piece> list;
It is accessible from everywhere in your app that has visibility of the class.
However, doing this is very messy and is considered a bad practice. Alternatively, you can create an object to manage the data for you as a static class or singleton:
public class MyListManager {
private static List<Piece> mList;
public static List<Piece> getMyList() {
return mList;
}
public static void setList(List<Piece> list) {
mList = list;
}
}
Alternatively, you can implement some kind of a caching system to manage your data.

Categories