In Activity A, I pass array using this code
ArrayList<SearchResults> results = new ArrayList<SearchResults>();
Intent i=new Intent(getApplication(),B.class);
i.putExtra("results", results);
startActivity(i);
In Activity B, receive results
ArrayList result;
result = (ArrayList<SearchResults>)getIntent().getSerializableExtra("results");
Toast.makeText(getApplicationContext(),result+"",Toast.LENGTH_LONG).show();
SearchResult
public class SearchResults {
private String weather = "";
private String date = "";
private String status = "";
private String timeIn="";
private String timeOut="";
private String project="";
private String description="";
private String progress="";
public void setWeather(String weather) {
this.weather = weather;
}
public String getWeather() {
return weather;
}
public void setDate(String date) {
this.date = date;
}
public String getDate() {
return date;
}
public void setStatus(String status) {
this.status = status;
}
public String getStatus() {
return status;
}
public void setTimeIn(String timeIn) {
this.timeIn = timeIn;
}
public String getTimeIn() {
return timeIn;
}
public void setTimeOut(String timeOut){
this.timeOut=timeOut;
}
public String getTimeOut()
{
return timeOut;
}
public void setProject(String project){
this.project=project;
}
public String getProject()
{
return project;
}
public void setProgress(String progress){
this.progress=progress;
}
public String getProgress()
{
return progress;
}
public void setDescription(String description){
this.description=description;
}
public String getDescription()
{
return description;
}
}
Error LogCat
Process: com.example.project.myapplication, PID: 2698
java.lang.RuntimeException: Parcel: unable to marshal value com.example.project.myapplication.bean.SearchResults#94c2757
at android.os.Parcel.writeValue(Parcel.java:1397)
at android.os.Parcel.writeList(Parcel.java:738)
at android.os.Parcel.writeValue(Parcel.java:1344)
And this line
startActivity(i);
How do I use serializable for passing bean objects and also make the bean class implements serializable ? Thanks a lot.
In the same activity, I want the results saved to database.
btnSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
WD.insertWorkDetails(result,a); //a is pass from Activtity a too
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
Toast.makeText(getApplication(),"DONE",Toast.LENGTH_LONG).show();
}
});
WorkDetails
public long insertWorkDetails(ArrayList<SearchResults> listItems, long id)
{
database=dbHelper.getWritableDatabase();
ContentValues values=new ContentValues();
for(SearchResults s:listItems) {
String Project = s.getProject();
String temp = s.getDescription();
String[] ReceiveDescription = temp.split(":");
String Progress = s.getProgress();
String[] ReceiveProgress = Progress.split(":");
String TimeIn = s.getTimeIn();
String[] ReceiveTimeIn = TimeIn.split(":");
String TimeOut = s.getTimeOut();
String[] ReceiveTimeOut = TimeOut.split(":");
values.put(MyDatabaseHelper.Project,Project);
values.put(MyDatabaseHelper.WorkDescription,ReceiveDescription[1]);
values.put(MyDatabaseHelper.Percentage,ReceiveProgress[1]);
values.put(MyDatabaseHelper.TimeIn,ReceiveTimeIn[1]);
values.put(MyDatabaseHelper.TimeOut,ReceiveTimeOut[1]);
values.put("Twd_id",id);
database.insert(MyDatabaseHelper.TABLE_WORKDETAILS, null, values);
}
database.close();
return 0 ;
}
When I check my db, no listView item is added.
java.lang.RuntimeException: Parcel: unable to marshal value
com.example.project.myapplication.bean.SearchResults#94c2757
you are using getSerializableExtra to retrieve your ArrayList. This implies that SearchResults implements Serializable which is not the case. If you want an easy fix just let SearchResults implement the Serializable interface. In the case of SearchResults serialization will work out of the box. Or you could learn about Parcelable (read more about it here) and use it instead of Serializable. If you don't need to save the objects on your permanent storage, Parcelable is way more efficient than Serializable
Related
I have 3 classes: MainActivity, homePage and createPage; and a list List<Recipe> recipeList = new ArrayList<>() in MainActivity.
The user enters the homePage from the MainActivity. From homePage, the user can enter createPage and create a new recipe. This new recipe is intended to be passed back to MainActivity.
I've searched online and came across parcels. But when I tried, I get a NullPointerException.
Code for createPage where the list is passed on
ArrayList<Recipe> rList = new ArrayList<>();
Recipe r = new Recipe(...);
rList.add(r)
Intent i = new Intent();
Bundle b = new Bundle();
b.putParcelableArrayList("recipe", (ArrayList<? extends Parcelable>) rList);
i.putExtras(b);
i.setClass(createPage.this, homePage.class);
startActivity(i);
Code for homePage where the list is received.
Is there something wrong with the getIntent()? Because when moving from MainActivity to homePage, it doesn't receive a bundle. Is this causing the error?
Intent intent = getIntent();
Bundle b = this.getIntent().getExtras();
if (b != null) {
Recipe r = b.getParcelable("recipe");
recipeList.add(r);
}
Code for Recipe class
public class Recipe implements Parcelable {
private String name;
private String description;
private String ingredients;
private int duration;
private String steps;
private int thumbnail;
protected Recipe(Parcel in) {
name = in.readString();
description = in.readString();
ingredients = in.readString();
duration = in.readInt();
steps = in.readString();
thumbnail = in.readInt();
}
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 String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getIngredients() {
return ingredients;
}
public void setIngredients(String ingredients) {
this.ingredients = ingredients;
}
public int getDuration() {
return duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
public String getSteps() { return steps; }
public void setSteps(String steps) { this.steps = steps; }
public int getThumbnail() { return thumbnail; }
public Recipe() {}
public Recipe(String name, int duration, String ingredients, String description, String steps, int thumbnail) {
this.name = name;
this.description = description;
this.ingredients = ingredients;
this.duration = duration;
this.steps = steps;
this.thumbnail = thumbnail;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(name);
parcel.writeString(description);
parcel.writeString(ingredients);
parcel.writeInt(duration);
parcel.writeString(steps);
parcel.writeInt(thumbnail);
}
}
you are writing into Parcelable whole array under "recipe" key
b.putParcelableArrayList("recipe", (ArrayList<? extends Parcelable>) rList);
but on onther side you are looking not for list but for single Recipe item under same key
Recipe r = b.getParcelable("recipe");
you should use getParcelableArrayList or if you have only one Recipe for passing to another Activity just use putParcelable (not list)
Alternatively you can use serializable, that will be less complex.
For reference : https://stackoverflow.com/a/2736612/9502601
Eventhough parcellables are more faster but if you want a less complex solution then you can go for it.
For Comparison between Serializable and Parcelable.
https://stackoverflow.com/a/23647471/9502601
You can use this gson Lib for this
implementation 'com.google.code.gson:gson:2.8.9'
Send Data with Intent
Recipe r = new Recipe(...);
String recipeString = new Gson().toJson(r);
intent.putExtra("recipe",recipeString);
// For ArrayList
ArrayList<Recipe> recipeList = new ArrayList<>();
String recipeString = new Gson().toJson(recipeList);
intent.putExtra("recipeList",recipeString);
Receive Data From Intent
Recipe r = new Gson().fromJson(intent.getStringExtra("recipe"), Recipe.class);
// For Array List
Type listType = new TypeToken<ArrayList<Recipe>>(){}.getType();
ArrayList<Recipe> recipeList = new Gson().fromJson(intent.getStringExtra("recipeList"),listType);
am using retrofit for insert data to my webservice, I have made it before but without uploading the image and the insert is successful, the input field through the model class not in interface,how I add an input field fot uploading files through the model so that it can be sent to my web services storage folder?
I have tried but failed please help
for my insert in activity
btnsubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String tanggal = textdate.getText().toString();
SimpleDateFormat formatter1=new SimpleDateFormat("dd/MM/yyyy");
Date date1= null;
try {
date1 = formatter1.parse(tanggal);
} catch (ParseException e) {
e.printStackTrace();
}
SwabtestModel sw = new SwabtestModel();
sw.sethasil(texthasil.getText().toString());
sw.settanggal(date1);
sw.settempat(texttempat.getText().toString());
sw.setuserid(Integer.valueOf(txtuserid.getText().toString()));
sw.setFile_name(new File(txturi.getText().toString()));
save(sw);
}
});
public void save(SwabtestModel sw){
Call<SwabtestModel> call = swabtestService.addswab(sw);
call.enqueue(new Callback<SwabtestModel>() {
#Override
public void onResponse(Call<SwabtestModel> call, Response<SwabtestModel> response) {
if(response.isSuccessful()){
String status = response.body().getStatus();
Toast.makeText(SwabtestActivity.this, status, Toast.LENGTH_LONG).show(); }
}
#Override
public void onFailure(Call<SwabtestModel> call, Throwable t) {
Log.e("ERROR: ", t.getMessage());
}
});
}
for my file chooser
public void onActivityResult(int request_code, int result_code, Intent data){
super.onActivityResult(request_code,result_code,data);
if(request_code==request_code && result_code== Activity.RESULT_OK){
if(data==null){
return;
}
uri= data.getData();
filePath = uri.getPath();
txturi.setText(filePath);
}
}
public void openfilechooser(){
Intent intent= new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
startActivityForResult(intent,request_code);
}
for my model class
public class SwabtestModel {
#SerializedName("hasil")
#Expose
private String hasil;
#SerializedName("tanggal")
#Expose
private Date tanggal;
#SerializedName("tempat")
#Expose
private String tempat;
#SerializedName("file_name")
#Expose
private File file_name;
#SerializedName("user_id")
#Expose
private Integer user_id;
String data;
String status;
public SwabtestModel(String hasil, Date tanggal, String tempat){
this.hasil = hasil;
this.tanggal = tanggal;
this.tempat = tempat;
}
public void sethasil(String hasil) {
this.hasil = hasil;
}
public String gethasil(){
return hasil;
}
public void settanggal(Date tanggal) {
this.tanggal = tanggal;
}
public Date gettanggal(){
return tanggal;
}
public void settempat(String tempat) {
this.tempat = tempat;
}
public String gettempat(){
return tempat;
}
public void setuserid(Integer user_id) {
this.user_id = user_id;
}
public Integer getuserid(){
return user_id;
}
public void setFile_name( File file_name) {
this.file_name =file_name ;
}
public File getfilename(){
return file_name;
}
public String getData() {
return data;
}
public String getStatus() {
return status;
}
}
my interface
public interface swabtestService
{
#GET("hasil-antigen-list")
Call<List<SwabtestModel>> getUsers();
#POST("insert-hantigen")
Call<SwabtestModel> addswab(#Body SwabtestModel swabtest);
}
To upload files you should use Multipart, Please refer to this post for example and please ping me if you have any queries https://stackoverflow.com/a/39953566
Take a data in list like #Part List<MultipartBody.Part> partFile
private List<MultipartBody.Part> getMapPartListSave(List<PojoAttachDocList> fields) {
List<MultipartBody.Part> mapPart = new ArrayList<>();
for (int i = 0; i < fields.size(); i++) {
**PojoAttachDocList** attachDoc = fields.get(i);
if (!attachDoc.isAttached() && attachDoc.getDocFile() != null && attachDoc.getDocFile().exists()
&& attachDoc.getDocFile().length() > 0) {
String fileParam = PARAMS_DOCUMENT + "[" + i + "]";
mapPart.add(MultipartBody.Part.createFormData(fileParam, attachDoc.getDocFile().getName(),
RequestBody.create(MediaType.parse("*/*"), attachDoc.getDocFile())));
}
}
return mapPart;
}
Convert it to MultipartBody
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
I am trying to call login API using Retrofit2.
But in onResponse i alwasy get null as response.
Login API endpoint
#FormUrlEncoded
#POST("/api/login/{mobile}")
Call<ResObj> userLogin( #Field("phoneNumber") String mobile );
And the API implementation
private void doLogin(final String mobile){
Call<ResObj> call = userService.login(mobile);
call.enqueue(new Callback<ResObj>() {
#Override
public void onResponse(Call<ResObj> call, Response<ResObj> response) {
ResObj resObj = response.body(); // here i am getting null response.body()
if(resObj.getMessage().equals("true")){
Intent intent = new Intent(Login.this, ListActivity.class);
intent.putExtra("mobile", mobile);
startActivity(intent);
} else{
Toast.makeText(Login.this, "Phone Number is incorrect!", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<ResObj> call, Throwable t) {
Toast.makeText(Login.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
ResObj class:
public class ResObj {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
I just want to know what causes the error and what are possible solutions.
UPDATE
POSTMAN
You are getting null response in your login API. It may be due to many reasons. You can check your API is working as expected or not using POSTMAN.
And inside your code, you can prevent this type of exception by checking OBJECT is null or not. like the following.
#Override
public void onResponse(Call<ResObj> call, Response<ResObj> response) {
ResObj resObj = response.body();
if(resObj != null){ // checking object is not null
if(resObj.getStatus()){
Intent intent = new Intent(Login.this, ListActivity.class);
intent.putExtra("mobile", mobile);
startActivity(intent);
} else{
Toast.makeText(Login.this, "Phone Number is incorrect!", Toast.LENGTH_SHORT).show();
}
}else{
// handle null response here.
}
}
Update:
According to your Response JSON, Your Model(ResObj) class should be like the following.
public class ResObj
{
private String date;
private String address;
private String accountName;
private String contactPerson;
private String timeOut;
private String problem;
private String srNo;
private String fieldEngineer;
private String joNo;
private String irNo;
private String designation;
private String email;
private String timeIn;
private String productType;
private boolean status;
private String contactNo;
public String getDate ()
{
return date;
}
public void setDate (String date)
{
this.date = date;
}
public String getAddress ()
{
return address;
}
public void setAddress (String address)
{
this.address = address;
}
public String getAccountName ()
{
return accountName;
}
public void setAccountName (String accountName)
{
this.accountName = accountName;
}
public String getContactPerson ()
{
return contactPerson;
}
public void setContactPerson (String contactPerson)
{
this.contactPerson = contactPerson;
}
public String getTimeOut ()
{
return timeOut;
}
public void setTimeOut (String timeOut)
{
this.timeOut = timeOut;
}
public String getProblem ()
{
return problem;
}
public void setProblem (String problem)
{
this.problem = problem;
}
public String getSrNo ()
{
return srNo;
}
public void setSrNo (String srNo)
{
this.srNo = srNo;
}
public String getFieldEngineer ()
{
return fieldEngineer;
}
public void setFieldEngineer (String fieldEngineer)
{
this.fieldEngineer = fieldEngineer;
}
public String getJoNo ()
{
return joNo;
}
public void setJoNo (String joNo)
{
this.joNo = joNo;
}
public String getIrNo ()
{
return irNo;
}
public void setIrNo (String irNo)
{
this.irNo = irNo;
}
public String getDesignation ()
{
return designation;
}
public void setDesignation (String designation)
{
this.designation = designation;
}
public String getEmail ()
{
return email;
}
public void setEmail (String email)
{
this.email = email;
}
public String getTimeIn ()
{
return timeIn;
}
public void setTimeIn (String timeIn)
{
this.timeIn = timeIn;
}
public String getProductType ()
{
return productType;
}
public void setProductType (String productType)
{
this.productType = productType;
}
public boolean getStatus ()
{
return status;
}
public void setStatus (boolean status)
{
this.status = status;
}
public String getContactNo ()
{
return contactNo;
}
public void setContactNo (String contactNo)
{
this.contactNo = contactNo;
}
}
You are passing parameter as raw data(according to your screen-shot). So your API endpoint would be like below.
#Headers("Content-Type: application/json")
#POST("/api/login")
Call<ResObj> userLogin(#Body JsonObject jsonObject);
And call your API like this
private void doLogin(final String mobile){
try {
JsonObject paramObject = new JsonObject();
paramObject.addProperty("mobile", mobile);
} catch (JSONException e) {
e.printStackTrace();
}
Call<ResObj> call = userService.login(paramObject);
call.enqueue(new Callback<ResObj>() {
//your rest of code
});
}
UPDATE-2:
To send object from one Activity to another using intent you have to make your model class Percelable. like this
// implements Parcelable
public class ResObj implements Parcelable {
// ...........your previous code here
// just simply add the following methods
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(date);
dest.writeString(address);
dest.writeString(accountName);
dest.writeString(contactPerson);
dest.writeString(timeOut);
dest.writeString(problem);
dest.writeString(srNo);
dest.writeString(fieldEngineer);
dest.writeString(joNo);
dest.writeString(irNo);
dest.writeString(designation);
dest.writeString(email);
dest.writeString(timeIn);
dest.writeString(productType);
dest.writeByte((byte) (status ? 1 : 0));
dest.writeString(contactNo);
}
public static final Parcelable.Creator<ResObj> CREATOR
= new Parcelable.Creator<ResObj>() {
public ResObj createFromParcel(Parcel in) {
return new ResObj(in);
}
public ResObj[] newArray(int size) {
return new ResObj[size];
}
};
protected ResObj(Parcel in) {
date = in.readString();
address = in.readString();
accountName = in.readString();
contactPerson = in.readString();
timeOut = in.readString();
problem = in.readString();
srNo = in.readString();
fieldEngineer = in.readString();
joNo = in.readString();
irNo = in.readString();
designation = in.readString();
email = in.readString();
timeIn = in.readString();
productType = in.readString();
status = in.readByte() != 0;
contactNo = in.readString();
}
}
Now pass your object via intent like the following.
if(resObj != null){
if(resObj.getStatus()){
Intent intent = new Intent(Login.this, ListActivity.class);
intent.putExtra("your_key", resObj); // pass resObj and use same key to get data
startActivity(intent);
} else{
Toast.makeText(Login.this, "Phone Number is incorrect!", Toast.LENGTH_SHORT).show();
}
}
Get data from your ListActivity like this
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
final ResObj yourObject = getIntent().getParcelableExtra("your_key"); // make sure you use same key like data.
// Now you can use your data like that
yourEditText.setText(yourObject.getEmail());
}
I am trying to save an enum 'Status' into a custom class that implements parcelable. I have found online how I can save Strings, ints or enums in one class that implements parcelable, but not how I can save these three things all at once. I am sorry if the solution is obvious, but I just can't figure it out.
Here is what my enum looks like:
public enum Status {
INITIALIZED, UPDATED, DELETED
}
And this is what I have so far:
public class Recipe implements Parcelable{
private String id;//this should be an int, same problem
private String recipeName;
private String recipePreperation;
private Status status;
private final static int MAX_PREVIEW = 50;
public Recipe(int parId, String parRecipeName, String parRecipePreperation) {
this.id = "" + parId;
this.recipeName = parRecipeName;
this.recipePreperation = parRecipePreperation;
this.status = Status.INITIALIZED;
}
public Recipe(Parcel in){
String[] data = new String[4];
in.readStringArray(data);
this.id = data [0];
this.recipeName = data[1];
this.recipePreperation = data[2];
this.status = data[3];//what I intend to do, I know this is wrong
}
public int GetId() {
return Integer.parseInt(id);
}
public String GetRecipeName() {
return this.recipeName;
}
public void SetRecipeName(String parRecipeName) {
this.recipeName = parRecipeName;
}
public String GetRecipePreperation() {
return this.recipePreperation;
}
public void SetRecipePreperation(String parRecipePreperation) {
this.recipePreperation = parRecipePreperation;
}
public Status GetStatus() {
return this.status;
}
public void SetStatus(Status parStatus) {
this.status = parStatus;
}
public String toString() {
String recipe = this.recipeName + "\n" + this.recipePreperation;
String returnString;
int maxLength = MAX_PREVIEW;
if (recipe.length() > maxLength) {
returnString = recipe.substring(0, maxLength - 3) + "...";
} else {
returnString = recipe;
}
return returnString;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int arg1) {
dest.writeStringArray(new String [] {
this.id,
this.recipeName,
this.recipePreperation,
this.status//what I intend to do, I know this is wrong
});
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public Recipe createFromParcel(Parcel in) {
return new Recipe(in);
}
public Recipe[] newArray(int size) {
return new Recipe[size];
}
};
}
How do I save an int, an array of strings and an enum into a class that implements the parcelable, so it can writeToParcel()?
There's no need to read and write to/from string array. Just write each string and finally the status as Serializable. This is how I fix it.
public Recipe(Parcel in){
this.id = in.readString();
this.recipeName = in.readString();
this.recipePreperation = in.readString();
this.status = (Status) in.readSerializable();
}
public void writeToParcel(Parcel dest, int arg1) {
dest.writeString(this.id);
dest.writeString(this.recipeName);
dest.writeString(this.recipePreperation);
dest.writeSerializable(this.status);
}
As a follow on from my last question: Passing Arraylist between activities? Using Parcelable
I'm now attempting to pass my ArrayList via Parcelable. However, when it's gotten from the other activity it returns null. I can't seem to figure out why. I've got the following...
ResultsList.java
public class ResultsList extends ArrayList<SearchList> implements Parcelable {
/**
*
*/
private static final long serialVersionUID = -78190146280643L;
public ResultsList(){
}
public ResultsList(Parcel in){
readFromParcel(in);
}
#SuppressWarnings({ "rawtypes" })
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public ResultsList createFromParcel(Parcel in) {
return new ResultsList(in);
}
public Object[] newArray(int arg0) {
return null;
}
};
private void readFromParcel(Parcel in) {
this.clear();
//First we have to read the list size
int size = in.readInt();
//Reading remember that we wrote first the Name and later the Phone Number.
//Order is fundamental
for (int i = 0; i < size; i++) {
String title = in.readString();
String Des = in.readString();
String message = in.readString();
SearchList c = new SearchList(title,Des,link);
this.add(c);
}
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
int size = this.size();
//We have to write the list size, we need him recreating the list
dest.writeInt(size);
//We decided arbitrarily to write first the Name and later the Phone Number.
for (int i = 0; i < size; i++) {
SearchList c = this.get(i);
dest.writeString(c.gettitle());
dest.writeString(c.getDescription());
dest.writeString(c.getmessage());
}
}
}
SearchList.java
public class SearchList {
private String title;
private String description;
private String message;
public SearchList(String name, String phone, String mail) {
super();
this.title = name;
this.description = phone;
this.message = mail;
}
public String gettitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getmessage() {
return message;
}
public void setmessage(String link) {
this.message = message;
}
}
listOfResults is declared as ResultsList listOfResults = new ResultsList(); and filled earlier in the code It's then sent with...
Intent intent = new Intent(this ,newthing.class);
Bundle b = new Bundle();
b.putParcelable("results", listOfResults);
startActivityForResult(intent,0);
Receiving...
Bundle extras = getIntent().getExtras();
ResultsList results = extras.getParcelable("results");
I'd like to point out I'm testing this null thing by checking the size() of the Arraylist going into the Bundle and then it coming out. It goes in fine and comes out null.
Didn't attach bundle to intent! (doh!) was pointed out by a kind gent on IRC! #android-dev