Parcelling complex objects b/w activities in android - java

I have a complex class "Class11" containing Socket,PrintWriter class references.
I am getting exception while trying to pass it between activities.
public interface Interface11 extends Parcelable{
...........
}
public class Class11 implements Interface11 {
Socket clientSocket;
ServerSocket serverSocket;
PrintWriter writer;
BufferedReader reader;
private JChatConnection(Parcel in) {
Object [] objects= in.readArray(Object.class.getClassLoader());
clientSocket=(Socket) objects[0];
serverSocket=(ServerSocket) objects[1];
writer=(PrintWriter) objects[2];
reader=(BufferedReader) objects[3];
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
Object objects[] = new Object[4];
objects[0]=clientSocket;
objects[1]=serverSocket;
objects[2]=writer;
objects[3]=reader;
dest.writeArray(objects);
}
public static final Parcelable.Creator<Class11> CREATOR =
new Parcelable.Creator<Class11>() {
public Class11 createFromParcel(Parcel in) {
return new Class11(in);
}
public Class11[] newArray(int size) {
return new Class11[size];
}
};
};
though i have option of sharing it via static object reference,
but to reduce coupling i tried to pass it via intent,
& i got exception:
java.lang.RuntimeException: unable to marshall value Socket[address=/192.168.43.225,port=9990,localport=213234]
at android.os.Parcel.writeValue(Parcel.java:1137)
at android.os.Parcel.writeArray(Parcel.java: 543)........
is it because Socket ,PrintWriter are not parcellable or,
am i messing this code at writeToParcel() and private Class11(Parcel in)
anybody has idea that how to pass this object between activities ?

I suggest not pass your object instance as an argument to Activity. Make it a Singleton, or a member of Application class. That will allow you to access Class11 instance everywhere in your app.

Related

Creating a Generic method to load dataSet in cucumber using Poiji library

I have a class that loaded data from scenario steps
my first class is LoadUserStepDfn
public class LoadUserStepDfn extends LoadDataStepDfn<User> {
public LoadUserStepDfn(ReadingUserUsingPoiji readingUserUsingPoiji) {
super.readingExcelUsingPoiji = readingUserUsingPoiji;
}
#Given("^Data is loaded from \"([^\"]*)\"$")
public void data_is_loaded_from (String filePath) throws Throwable {
super.data_is_loaded_from(filePath);
}
and it call class named LoadDataStepDfn
public class LoadDataStepDfn<T> {
public List<T> data;
protected ReadingExcelUsingPoiji readingExcelUsingPoiji;
public void data_is_loaded_from (String filePath) throws Throwable {
data = readingExcelUsingPoiji.TransformExcelToClass(filePath);
}
and here is my class that reads excel and store it to java class
public abstract class ReadingExcelUsingPoiji<T> {
public List<T> TransformExcelToClass(String filePath){
PoijiOptions options = PoijiOptions.PoijiOptionsBuilder.settings().addListDelimiter(";").build();
List<T> data = Poiji.fromExcel(new File(filePath), getMyType(), options);
return data;
}
public abstract Class<T> getMyType();
}
the problem that I want to use one class I don't want it to be abstract and use another one wiche is this class
public class ReadingUserUsingPoiji extends ReadingExcelUsingPoiji<User> {
public Class<User> getMyType(){
return User.class;
}
I am trying to understand here, so you dont want #override, but rather 1 method that returns you the type of class to transform to??
Why can't it be that simple... You have a method that determines what class you should use to transform to...
I dont understand why you are using generics...your logic doesnt seem to really care for it? Especially if you have 1 ReadingExcelUsingPoiji class..it really shouldnt care.
public class ReadingExcelUsingPoiji<T> {
public List<T> transformExcelToClass(String filePath, Class<T> classToTransformTo) {
PoijiOptions options = PoijiOptions.PoijiOptionsBuilder.settings().addListDelimiter(";").build();
List<T> data = Poiji.fromExcel(new File(filePath), classToTransformTo, options);
return data;
}
public static void main(String [] args) {
ReadingExcelUsingPoiji genericConverter = new ReadingExcelUsingPoiji();
List<User> listOfUsers = genericConverter.transformExcelToClass("yourFilePath", User.class);
List<Car> listOfCars = genericConverter.transformExcelToClass("yourFilePath", Car.class);
}
}
public class LoadUserStepDfn extends LoadDataStepDfn<User> {
#Given("^Data is loaded from \"([^\"]*)\"$")
public void data_is_loaded_from (String filePath) throws Throwable {
super.data_is_loaded_from(filePath , User.class);
}
}
public class LoadDataStepDfn<T> {
public List<T> data;
protected ReadingExcelUsingPoiji readingExcelUsingPoiji;
protected void data_is_loaded_from(String filePath, Class<T> classToTransformTo) throws Throwable {
data = readingExcelUsingPoiji.transformExcelToClass(filePath, classToTransformTo);
}
}

How to add Java Socket object to Parcelable in Android

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.

How to use a different subclass for List elements in a super class

I'm looking for the proper way to implement generics (or some better solution with data structures) for the following four classes. I want to be able to use the method in the base class GetActivationResponse. The idea was to separate plain Java sources from sources which were dependent on the Android platform.
GetActivationResponse:
public class GetActivationResponse extends ResponseMessage {
protected List<Activation> mActivations;
public GetActivationResponse(JSONObject jsonObject) throws JSONException {
super(jsonObject);
mActivations = new ArrayList<>();
fromJson(jsonObject);
}
#Override
public void fromJson(JSONObject jsonObject) throws JSONException {
//get the response DATA.
if(jsonObject.has("DATA")) {
JSONArray dataArray = jsonObject.getJSONArray("DATA");
for(int i = 0; i < dataArray.length(); i++) {
mActivations.add(new Activation(dataArray.getJSONObject(i)));
}
}
}
}
GetActivationResponseAndroid:
public class GetActivationResponseAndroid extends GetActivationResponse implements Cacheable {
public GetActivationResponseAndroid(JSONObject jsonObject) throws JSONException {
super(jsonObject);
}
#Override
public List<ContentValues> getContentValuesList() {
List<ContentValues> values = new ArrayList<ContentValues>();
for(int i = 0; i < mActivations.size(); i++) {
values.add(((ActivationAndroid)(mActivations.get(i))).toContentValues());
}
return values;
}
}
I get a ClassCastException here, though:
((ActivationAndroid)(mActivations.get(i))).toContentValues()
ActivationAndroid is a subclass of Activation. My goal is to be able to use any subclass of Activation as well as Activation itself. I think this might involve generics. I've tried changing the List<Activation> mActivations to List<? extends Activation> mActivations, but then the compiler tells me that the line in GetActivationResponse which fills the List has an error on this line:
mActivations.add(new Activation(dataArray.getJSONObject(i)));
Apparently <? extends Activation> means you can ONLY use subclasses, but not the base class itself. I want to have the fromJSON method in the base class, seeing as how it works the same with Activation or any of its subclasses.
ActivationAndroid is a subclass of Activation which provides a convenience method for converting the object into a List<ContentValues> for use with Android database transactions:
Activation:
public class Activation {
protected String mApp;
protected boolean mActivated;
public Activation(String app, boolean activated) {
mApp = app;
mActivated = activated;
}
public Activation(JSONObject json) throws JSONException {
mApp = json.getString("APP");
mActivated = json.getBoolean("ACTIVATED");
}
}
ActivationAndroid:
public class ActivationAndroid extends Activation implements AndroidSerial {
public ActivationAndroid (String app, boolean activated) {
super(app, activated);
}
public ActivationAndroid (JSONObject jsonScale) throws JSONException {
super(jsonScale);
}
public ContentValues toContentValues() {
ContentValues cv = new ContentValues();
cv.put(DbSchema.ActivationSchema.COLUMN_ACTIVATED, mActivated);
cv.put(DbSchema.ActivationSchema.COLUMN_APP, mApp);
return cv;
}
}

Unable to create POJO with Retrofit and Java in android

I am getting following json response from one of the vendor.
{
"status": "success",
"data": {
"values": [
[
"2015-12-28T09:15:00+0530",
1386.4,
1388,
1381.05,
1385.1,
788
],
[
"2015-12-28T09:15:00+0530",
1386.4,
1388,
1381.05,
1385.1,
788
]
]
}
}
I would like to convert this to POJO.
I am using retrofit 2.0, rx java.
I have tried following
public class HistoricalDataContainer implements Parcelable{
public String status;
public CandleList data;
protected HistoricalDataContainer(Parcel in) {
status = in.readString();
data = in.readParcelable(CandleList.class.getClassLoader());
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(status);
dest.writeParcelable(data, flags);
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<HistoricalDataContainer> CREATOR = new Creator<HistoricalDataContainer>() {
#Override
public HistoricalDataContainer createFromParcel(Parcel in) {
return new HistoricalDataContainer(in);
}
#Override
public HistoricalDataContainer[] newArray(int size) {
return new HistoricalDataContainer[size];
}
};
}
And
public class CandleList implements Parcelable{
public ArrayList<ArrayList<String>> values = new ArrayList<>();// doesn't work
public ArrayList<String[]> values=new ArrayList<String[]>();// doesn't work
public ArrayList<String>[] values; // doesn't work
protected CandleList(Parcel in) {
}
#Override
public void writeToParcel(Parcel dest, int flags) {
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<CandleList> CREATOR = new Creator<CandleList>() {
#Override
public CandleList createFromParcel(Parcel in) {
return new CandleList(in);
}
#Override
public CandleList[] newArray(int size) {
return new CandleList[size];
}
};
}
But in the above code "value" is always null.
What am I missing.
You are missing the annotations style for Gson.
For example:
public class LiveStreamResponse extends BaseResponse{
#SerializedName("live_stream")
#Expose
private LiveStream liveStream;
#SerializedName("meta")
#Expose
private Meta meta;
public LiveStream getLiveStream() {
return liveStream;
}
public void setLiveStream(LiveStream liveStream) {
this.liveStream = liveStream;
}
public Meta getMeta() {
return meta;
}
public void setMeta(Meta meta) {
this.meta = meta;
}
}
That help Retrofit to match with all objects on your POJO, you have to define which object have to be matched with your "status": "success", "data", "values" from the Json File.
You can read more about following this tutorial. Consuming APIs with Retrofit
And also I give you this example using xml and Json.
First you need to identify the objects that are in the JSON structure, in this case there are two.1. The json that you are receiving and 2. data .
The option is to create a class for every object.
the first class contains the main object (json itself) with his main attributes: status and data.
public class HistoricalDataContainer implements Parcelable {
private string status;
private Data data;
setters - getters
...
}
data is an object, so you need to create his own class to handle his attributes, in this case is an array with string arrays
public class Data implements Parcelable {
private List<String> values;
setters - getters
...
}
To get an specific array inside values you are going to do something like:
List<String> myStringArray = historicalDataContainer.getData().values().get(index);
AND
Why are you using Parcelable?
...
I hope this answer is what you need!
You can try http://www.jsonschema2pojo.org/ for JSON Mapping. It's a great tool for creating models from existing JSON responses. And for quick implementation of Parcelable to existing class you can use http://www.parcelabler.com/

Java generics access error

I could need some help with a problem I have with Java's generics.
I constructed a little example for to show what I mean.
Handler
package generalizingTest;
public class Handler<S extends Server<?>> {
public S server;
public Handler(S server) {
this.server = server;
}
}
SubHandler
package generalizingTest;
public class SubHandler<S extends Server<?>> extends Handler<S> {
public SubHandler(S server) {
super(server);
}
public void subHandlerMethod() {
}
}
Server
package generalizingTest;
import java.util.ArrayList;
public class Server<H extends Handler<?>> {
public ArrayList<H> handlers;
public Server() {
handlers = new ArrayList<H>();
}
public void addHandler(H c) {
handlers.add(c);
}
}
SubServer
package generalizingTest;
public class SubServer<H extends Handler<?>> extends Server<H> {
public void subServerMethod() {
}
}
Startup
package generalizingTest;
public class Startup {
public static void main(String[] args) {
Server<Handler<?>> serverWHandler = new Server<Handler<?>>();
Server<SubHandler<?>> serverWSubHandler = new Server<SubHandler<?>>();
SubServer<Handler<?>> subServerWHandler = new SubServer<Handler<?>>();
SubServer<SubHandler<?>> subServerWSubHandler = new SubServer<SubHandler<?>>();
Handler<Server<?>> handlerWServer = new Handler<Server<?>>(serverWHandler);
Handler<SubServer<?>> handlerWSubServer = new Handler<SubServer<?>>(subServerWHandler);
SubHandler<Server<?>> subHandlerWServer = new SubHandler<Server<?>>(serverWSubHandler);
SubHandler<SubServer<?>> subHandlerWSubServer = new SubHandler<SubServer<?>>(subServerWSubHandler);
serverWHandler.addHandler(handlerWServer);
subServerWHandler.addHandler(handlerWSubServer);
serverWSubHandler.addHandler(subHandlerWServer);
subServerWSubHandler.addHandler(subHandlerWSubServer);
subServerWHandler.subServerMethod();
subServerWSubHandler.subServerMethod();
handlerWSubServer.server.subServerMethod();
subHandlerWSubServer.server.subServerMethod();
subHandlerWServer.subHandlerMethod();
subHandlerWSubServer.subHandlerMethod();
System.out.println(subHandlerWSubServer.server.handlers.get(0).getClass().getName()); // SubHandler
//produces an error:
/*
* Unresolved compilation problem:
* The method subHandlerMethod() is undefined for the type Handler<capture#9-of ?>
*/
//subHandlerWSubServer.server.handlers.get(0).subHandlerMethod();
}
}
I just started learning about generics. They seem to be efficient but I am not sure if I solved the problem of the generics loop () correctly with the wildcard and why those errors occur.
I really hope someone can help me out.
EDIT:
So it seems like I did not highlighted the initial problem enough.
The following should be possible in any depth:
subHandlerWSubServer.server.handlers.get(0).server.handlers.get(0).server.handlers.get(0). ... .server.handlers.get(0).subHandlerMethod();
EDIT:
So this problem seems not to be solvable due to an endless loop of definition or the missing self value, see Siguza’s anwser.
Here is the discussion between Siguza, user889742 and myself about this topic.
If I understood you correctly, if you have a Handler<S> you want all handlers on that server to be of type Handler<S>, right?
For that, S.add() would have to only accept objects of type Handler<S>. But in order to implement that in the base class Server, you would need S, so that:
public class Server<H>
{
public ArrayList<H<S>> handlers;
public Server()
{
handlers = new ArrayList<H<S>>();
}
public void addHandler(H<S> c)
{
handlers.add(c);
}
}
The only problem with this is that S is not defined, and you cannot easily define it. What you would need is something that, in the context of Server, means Server, and in the context of SubServer, means SubServer. Basically this.getClass(), but as a compile-time type expression. If Java had a keyword for that, say self, you could use it like this:
public class Server<H>
{
public ArrayList<H<self>> handlers;
public Server()
{
handlers = new ArrayList<H<self>>();
}
public void addHandler(H<self> c)
{
handlers.add(c);
}
}
Then Server.add() would take Handler<Server>, and SubServer.add() would take Handler<SubServer>.
Sadly, Java has no such thing, therefore what you're trying to do is not possible this way.
Java does many things well.
Generics aren't one of them.
It could work with a redesign like this. You would not be able to use Server as your starting point, since it would require generic arguments leading to a recursive definition again. Instead, start with ServerInfo. As you can check it works, but I think it might be a bit cumbersome and not intuitive.
class Server
{
}
class Handler
{
}
class SubServer extends Server
{
}
class SubHandler extends Handler
{
public void subHandlerMethod(){}
}
class HandlerInfo<S extends Server, H extends Handler>
{
ServerInfo<S,H> serverInfo;
H handler;
}
class ServerInfo<S extends Server, H extends Handler>
{
S server;
ArrayList<HandlerInfo<S,H>> handlerInfo = new ArrayList<>();
}
public class Example {
public static void main(String[] args) {
Server s = new Server();
SubHandler h = new SubHandler();
ServerInfo<Server,SubHandler> serverInfo = new ServerInfo<>();
HandlerInfo<Server,SubHandler> handlerInfo = new HandlerInfo<>();
handlerInfo.serverInfo = serverInfo;
handlerInfo.handler = h;
serverInfo.server = s;
serverInfo.handlerInfo.add(handlerInfo);
serverInfo.handlerInfo.get(0).serverInfo.handlerInfo.get(0).handler.subHandlerMethod();
}
}
Edit:
You could simply restrict SubServers to only accept SubHandlers
Subserver<H extends SubHandler> extends Server<H>
When you do that you will see that the compilation error goes away.
But I understand you want to define some Servers that allow only subHandlers, and some subHandlers that allow only Servers. ( Seems strange to me ), and then reflexive relationship H<->S gives you trouble, leading to generic type recursion.
While I think it's strange to mix Server->Subhandler and Handler->SubServer , you could accomplish an unrestricted 2 way relationship as you want by extracting interfaces like this: ( try it, it works )
interface IHandler
{
}
interface IServer
{
}
interface ISubServer extends IServer
{
public void subServerMethod();
}
interface ISubHandler extends IHandler
{
public void subHandlerMethod();
}
class Handler<S extends IServer> implements IHandler {
public S server;
public Handler(S server) {
this.server = server;
}
}
class SubHandler<S extends IServer> extends Handler<S> implements ISubHandler {
public SubHandler(S server) {
super(server);
}
public void subHandlerMethod() {
}
}
class Server<H extends IHandler> implements IServer{
public ArrayList<H> handlers;
public Server() {
handlers = new ArrayList<H>();
}
public void addHandler(H c) {
handlers.add(c);
}
}
class SubServer<H extends IHandler> extends Server<H> implements ISubServer {
public void subServerMethod() {
}
}
public class Example {
public static void main(String[] args) {
Server<IHandler> serverWHandler = new Server<IHandler>();
Server<ISubHandler> serverWSubHandler = new Server<ISubHandler>();
SubServer<IHandler> subServerWHandler = new SubServer<IHandler>();
SubServer<ISubHandler> subServerWSubHandler = new SubServer<ISubHandler>();
Handler<IServer> handlerWServer = new Handler<IServer>(serverWHandler);
Handler<ISubServer> handlerWSubServer = new Handler<ISubServer>(subServerWHandler);
SubHandler<Server<ISubHandler>> subHandlerWServer = new SubHandler<Server<ISubHandler>>(serverWSubHandler);
SubHandler<SubServer<ISubHandler>> subHandlerWSubServer = new SubHandler<SubServer<ISubHandler>>(subServerWSubHandler);
serverWHandler.addHandler(handlerWServer);
subServerWHandler.addHandler(handlerWSubServer);
serverWSubHandler.addHandler(subHandlerWServer);
subServerWSubHandler.addHandler(subHandlerWSubServer);
subServerWHandler.subServerMethod();
subServerWSubHandler.subServerMethod();
handlerWSubServer.server.subServerMethod();
subHandlerWSubServer.server.subServerMethod();
subHandlerWServer.subHandlerMethod();
subHandlerWSubServer.subHandlerMethod();
System.out.println(subHandlerWSubServer.server.handlers.get(0).getClass().getName()); // SubHandler
//no longer produces an error:
subHandlerWSubServer.server.handlers.get(0).subHandlerMethod();
}
}
and remember, anytime your problem is a reflexive relationship A<->B , not just with generics, you can extract IA and IB so that A->IB and B-> IA

Categories