I want to send an object from an activity to another using Parcelable in the class. I have a Parcelable class that has two strings and an Exception as attributes.
public class ReportErrorVO implements Parcelable {
private String titleError;
private String descriptionError;
private Exception exceptionError;
public ReporteErrorVO(Parcel in) {
titleError = in.readString();
descriptionError = in.readString();
exceptionError = ????; //What do I put here?
}
public ReporteErrorVO() {
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(titleError);
dest.writeString(descriptionError);
dest.writeException(exceptionError);
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public ReportErrorVO createFromParcel(Parcel in) {
return new ReportErrorVO(in);
}
public ReportErrorVO[] newArray(int size) {
return new ReportErrorVO[size];
}
};
#Override
public int describeContents() {
return 0;
}
//Getter and setters atributes...
}
What can I do to set the exception in the parcelable attribute?
You can use readException method in.readException() and this method will throw the exception if it had been written to the parcel, so you may catch it and save to your variable.
try {
in.readException();
} catch (Exception e){
exceptionError = e;
}
Note that this method only supports limited types of exceptions
The supported exception types are:
* BadParcelableException
* IllegalArgumentException
* IllegalStateException
* NullPointerException
* SecurityException
* NetworkOnMainThreadException
Ok, doing it this way helped me to get things working: Send the exception on an array.
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mTitleError);
dest.writeString(mDescriptionError);
Exception[] exceptions = new Exception[1];
exceptions[0] = mExceptionError;
dest.writeArray(exceptions);
}
public ReportErrorVO(Parcel in) {
mTitleError = in.readString();
mDescriptionError = in.readString();
Object[] exceptions = in.readArray(Exception.class.getClassLoader());
mExceptionError = (Exception) exceptions[0];
}
Related
New to this topic and right now I'm stuck at a brick wall. I have 2 classes, parent class: Controller.java and subclass: GreenhouseControls.java. I need to serialize a GreenhouseControls object but also an instance variable (eventList) from its superclass Controller.java.
My serialization happens when an inner class of GreenhouseControls.java throws a custom ControllerException, which is caught in the main method. Before terminating the program, the GreenhouseControls object should be saved (including the field from its superclass).
Why is a NotSerializableException thrown by the inner class WindowMalfunction of GreenhouseControls? Anyone have any ideas, as I am seriously stuck?
What I tried is the following:
Implement serializable on Controller.java. This is because if the superclass is serializable, then subclass is automatically serializable, however this throws java.io.NotSerializableException: GreenhouseControls$WindowMalfunction, (WindowMalfunction is the inner class that throws the initial exception to begin the serialization processs).
Implement serializable on GreenhouseControls.java and implement custom serialization by overriding writeObject() and readObject() to save the field from the superclass. This approach yet again throws the same exception as the approach 1.
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(super.eventList);
}
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
Object obj = in.readObject();
List<Event> x = cast(obj);
super.eventList = x;
}
Controller.java
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
public class Controller {
// THIS IS THE VARIABLE I NEED TO SAVE
protected List<Event> eventList = new ArrayList<Event>();
public void addEvent(Event c) {
eventList.add(c);
}
public void run() throws ControllerException {
while (eventList.size() > 0)
// Make a copy so you're not modifying the list
// while you're selecting the elements in it:
for (Event e : new ArrayList<Event>(eventList))
if (e.ready()) {
System.out.println(e);
e.action();
eventList.remove(e);
}
}
public static void shutDown() { }
}
GreenhouseControls.java class (note I have removed the inner classes and other code from it and only left related info)
public class GreenhouseControls extends Controller implements Serializable {
private int errorcode = 0;
public class WindowMalfunction extends Event {
public WindowMalfunction(long delayTime) {
super(delayTime);
}
public void action() throws ControllerException {
windowok = false;
throw new ControllerException("Window malfunction");
}
public String toString() {
return "Window malfunction";
}
}
public class PowerOut extends Event {
public PowerOut(long delayTime) {
super(delayTime);
}
public void action() throws ControllerException {
poweron = false;
throw new ControllerException("Power out");
}
public String toString() {
return "Power out";
}
}
// Various other inner classes that extend event exist
public static void serializeObject(GreenhouseControls gc) {
FileOutputStream fileOut;
ObjectOutputStream out;
try {
fileOut = new FileOutputStream("dump.out");
out = new ObjectOutputStream(fileOut);
out.writeObject(gc);
System.out.println("WERRROR code: " + gc.getError());
out.close();
fileOut.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(super.eventList);
}
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
Object obj = in.readObject();
List<Event> x = cast(obj);
super.eventList = x;
}
#SuppressWarnings("unchecked")
public static <T extends List<?>> T cast(Object obj) {
return (T) obj;
}
public int getError() {
return errorcode;
}
public Fixable getFixable(int errorcode) {
switch (errorcode) {
case 1:
return new FixWindow();
case 2:
return new PowerOn();
default:
return null;
}
}
public static void main(String[] args) {
GreenhouseControls gc = null;
try {
String option = args[0];
String filename = args[1];
if (!(option.equals("-f")) && !(option.equals("-d"))) {
System.out.println("Invalid option");
printUsage();
}
// gc = new GreenhouseControls();
if (option.equals("-f")) {
gc = new GreenhouseControls();
gc.addEvent(gc.new Restart(0, filename));
}
gc.run();
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Invalid number of parameters");
printUsage();
} catch (ControllerException e) {
String errormsg;
if (e.getMessage().equals("Window malfunction")) {
gc.errorcode = 1;
errormsg = "Window malfunction event occurred Error code: " + gc.errorcode;
} else {
gc.errorcode = 2;
errormsg = "Power out event occurred Error code: " + gc.errorcode;
}
logError(errormsg);
serializeObject(gc);
gc.displayEventList();
shutDown();
}
}
}
Event.java
public abstract class Event {
private long eventTime;
protected final long delayTime;
public Event(long delayTime) {
this.delayTime = delayTime;
start();
}
public void start() { // Allows restarting
eventTime = System.currentTimeMillis() + delayTime;
}
public boolean ready() {
return System.currentTimeMillis() >= eventTime;
}
public abstract void action() throws ControllerException;
Event has to be Serializable too.
Change
public abstract class Event {
to
public abstract class Event implements Serializable {
I am new to Java and trying my hands on the exception handling code. Everything was fine to me until I get unhandled exception error. Can anyone please help me to correct the code and tell my mistake so that I can never commit again?
Exception Class - Created this to retrieve message for different exceptions
// Implement user defined exception classes
class InvalidAgeException extends Exception{
public InvalidAgeException(String message) {
super(message);
}
}
class InvalidJobProfileException extends Exception{
public InvalidJobProfileException(String message) {
super(message);
}
}
class InvalidNameException extends Exception{
public InvalidNameException(String message) {
super(message);
}
}
Applicant Class - Class to set and get attributes of Applicant
class Applicant {
private String name;
private String jobProfile;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getJobProfile() {
return jobProfile;
}
public void setJobProfile(String jobProfile) {
this.jobProfile = jobProfile;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Validator Class - Class to check if the Applicant has a name or not
class Validator{
//Implement your code here
public boolean validateName(String name) throws Exception
{
if(getName().length()>0)
{
return true;
}
else{
return false;
}
}
public boolean validateJobProfile(String jobProfile) throws Exception
{
if (getJobProfile().equalsIgnoreCase("Associate") || getJobProfile().equalsIgnoreCase("Clerk") ||
getJobProfile().equalsIgnoreCase("Executive") || getJobProfile().equalsIgnoreCase("Officer"))
{
return true;
}
else{
return false;
}
}
public boolean validateAge(int age) throws Exception
{
if(getAge()>=18 && getAge()<=30)
{
return true;
}
else{
return false;
}
}
public void validate(Applicant applicant) throws Exception
{
if(validateName(getName())==false)
{
throw new InvalidNameException("Invalid Name");
}
if (validateJobProfile(getJobProfile())==false)
{
throw new InvalidJobProfileException("Invalid job post");
}
if (validateAge(getAge())==false)
{
throw new InvalidAgeException("Invalid Age");
}
}
}
Tester Class - Main Class where objects of different classes are created
class Tester {
public static void main(String[] args) {
try {
Applicant applicant= new Applicant();
applicant.setName("Jenny");
applicant.setJobProfile("Clerk");
applicant.setAge(25);
Validator validator = new Validator();
validator.validate(applicant);
System.out.println("Application submitted successfully!");
}
catch (InvalidNameException|InvalidJobProfileException|InvalidAgeException e) {
System.out.println(e.getMessage());
}
}
}
Your method declares that it throws Exception. Thus, you have to actually catch Exception. If you only want to have to catch either of the three custom exceptions, you need to declare your method as only throwing those three via throws InvalidNameException, InvalidJobProfileException, InvalidAgeException
Plus, your validateAge is declared as throwing an exception, but never actually does throw anything.
Your methods need to specify which exceptions they are actually throwing. At the moment you are simply writing that they throw the general Exception, which you then don't catch in your main.
Change
public void validate(Applicant applicant) throws Exception{...}
to
public void validate(Applicant applicant) throws InvalidNameException, InvalidJobProfileException, InvalidAgeException{...}
For the other methods you need to do it similarly.
I want to pass a Java Socket object from one activity to another. I thought of using Parcelable for passing but cannot add the object to the parcel
public class NetworkInformation implements Parcelable {
private String ipAddress;
private String portNo;
private Socket networkSocket;
protected NetworkInformation(Parcel in) {
}
public static final Creator<NetworkInformation> CREATOR = new Creator<NetworkInformation>() {
#Override
public NetworkInformation createFromParcel(Parcel in) {
return new NetworkInformation(in);
}
#Override
public NetworkInformation[] newArray(int size) {
return new NetworkInformation[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(ipAddress);
dest.writeString(portNo);
//How to add the Socket to parcelable here ?
}
}
I'm not sure if this will work, but you might try:
private String ipAddress;
private String portNo;
private Socket networkSocket;
protected NetworkInformation(Parcel in) {
ipAddress = in.readString();
portNo = in.readString();
networkSocket = new Socket(makeRealIP(ipAddress),makeRealPortNo(portNo));
}
Of course, you would have to write your own makeRealIP and makeRealPortNo to convert the strings back into useful parameters for a new Socket();
Bundle myBundle = new Bundle();
NetworkInformation myNetworkInfo;
myBundle.putParceable("myNetworkInfo",myNetworkInfo);
myNetworkInfo = (NetworkInformation)myBundle.getParceable("myNetworkInfo");
I've not tried this, and I'll bet the other folks that answered were quite correct to warn about mucking around at the socket layer. It can get a bit tricky. Good Luck.
I am very beginner in Android and Parcelable interface . I just want to send
private XMPPTCPConnection xmpptcpConnection;
this above XMPPTCPConnection object from one Activity to another Activity.But I am error getting error as:
java.lang.RuntimeException: Parcel: unable to marshal value org.jivesoftware.smack.tcp.XMPPTCPConnection#342f1d60
at android.os.Parcel.writeValue(Parcel.java:1337)
at com.example.rahul.samplesmack.Def.writeToParcel(Def.java:31)
Below is my java code:
public class Def implements Parcelable {
private XMPPTCPConnection xmpptcpConnection;
public void setXmpptcpConnection(XMPPTCPConnection xmpptcpConnection)
{
this.xmpptcpConnection = xmpptcpConnection;
}
public XMPPTCPConnection getXmpptcpConnection()
{
return xmpptcpConnection;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(xmpptcpConnection); //I am getting Error here!!!!!
}
public Def(){}
protected Def(Parcel in) {
xmpptcpConnection = (XMPPTCPConnection) in.readValue(XMPPTCPConnection.class.getClassLoader());
}
public static final Creator<Def> CREATOR = new Creator<Def>() {
#Override
public Def createFromParcel(Parcel in) {
return new Def(in);
}
#Override
public Def[] newArray(int size) {
return new Def[size];
}
};
}
Wrote a class that helps pass my object, was working fine until i wanted to pass a more generic object myself.
public class StepParceble implements Parcelable {
private Step mStep;
private JSONObject mStepData;
private onScreen mOnScreen;
public StepParceble(Step step, JSONObject stepData, onScreen onScreen) {
setmStep(step);
setmStepData(stepData);
setmOnScreen(onScreen);
}
public StepParceble(Parcel parcel){
}
public onScreen getmOnScreen() {
return mOnScreen;
}
public void setmOnScreen(onScreen mOnScreen) {
this.mOnScreen = mOnScreen;
}
public void setmStep(Step mStep) {
this.mStep = mStep;
}
public void setmStepData(JSONObject mStepData) {
this.mStepData = mStepData;
}
public JSONObject getmStepData() {
return mStepData;
}
public Step getmStep() {
return mStep;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
try {
dest.writeArray(new Object[]{mStep, mStepData,mOnScreen});
} catch (Exception e) {
}
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public StepParceble createFromParcel(Parcel in) {
return new StepParceble(in);
}
public StepParceble[] newArray(int size) {
return new StepParceble[size];
}
};
}
it return a null pointer on getting any of those values.
Passing the data as
StepParceble stepParceble = new StepParceble(step, stepData, onScreen);
Intent uiIntent = new Intent(context, UIActivity.class).putExtra(UiControlTrier.STEP_KEY,stepParceble);
You didn't provide means to read fields from your parcelable when you've overridden the constructor
public StepParceble(Parcel parcel){
//add methods to populate fields from parcel
}
You can use Android Studio plugins to do this for you:
https://github.com/mcharmas/android-parcelable-intellij-plugin
Also, if your class has complex-type fields (like Step in your case), those should be Parcelable too