├── .gitignore
├── ExampleGlobalParcelable
├── .settings
│ └── org.eclipse.jdt.core.prefs
├── AndroidManifest.xml
├── ic_launcher-web.png
├── libs
│ └── android-support-v4.jar
├── proguard-project.txt
├── project.properties
├── res
│ ├── drawable-hdpi
│ │ └── ic_launcher.png
│ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ │ └── ic_launcher.png
│ ├── layout
│ │ ├── activity_main.xml
│ │ └── activity_next.xml
│ ├── menu
│ │ └── main.xml
│ ├── values-sw600dp
│ │ └── dimens.xml
│ ├── values-sw720dp-land
│ │ └── dimens.xml
│ ├── values-v11
│ │ └── styles.xml
│ ├── values-v14
│ │ └── styles.xml
│ └── values
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
└── src
│ └── com
│ └── example
│ └── exampleglobalparcelable
│ ├── GlobalParcelable.java
│ ├── MainActivity.java
│ ├── NextActivity.java
│ ├── ObjectA_User.java
│ └── ObjectB_ToDo.java
├── GlobalParcelable.java
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .classpath
2 | # built application files
3 | *.apk
4 | *.ap_
5 |
6 | # files for the dex VM
7 | *.dex
8 |
9 | # Java class files
10 | *.class
11 |
12 | # generated files
13 | bin/
14 | gen/
15 |
16 | # Local configuration file (sdk path, etc)
17 | local.properties
18 |
19 | # Eclipse project files
20 | .classpath
21 | .project
22 |
23 | # Android Studio
24 | .idea/
25 | .gradle
26 | /*/local.properties
27 | /*/out
28 | /*/*/build
29 | /*/*/production
30 | *.iml
31 | *.iws
32 | *.ipr
33 | *~
34 | *.swp
35 |
36 | # Mac files
37 | *.DS_Store
38 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
3 | org.eclipse.jdt.core.compiler.compliance=1.6
4 | org.eclipse.jdt.core.compiler.source=1.6
5 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awadalaa/Android-Global-Parcelable/fbc5df522c53ee096c49e7422f73e8413926b3f6/ExampleGlobalParcelable/ic_launcher-web.png
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awadalaa/Android-Global-Parcelable/fbc5df522c53ee096c49e7422f73e8413926b3f6/ExampleGlobalParcelable/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-17
15 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awadalaa/Android-Global-Parcelable/fbc5df522c53ee096c49e7422f73e8413926b3f6/ExampleGlobalParcelable/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awadalaa/Android-Global-Parcelable/fbc5df522c53ee096c49e7422f73e8413926b3f6/ExampleGlobalParcelable/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awadalaa/Android-Global-Parcelable/fbc5df522c53ee096c49e7422f73e8413926b3f6/ExampleGlobalParcelable/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awadalaa/Android-Global-Parcelable/fbc5df522c53ee096c49e7422f73e8413926b3f6/ExampleGlobalParcelable/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
6 |
11 |
16 |
20 |
21 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/res/layout/activity_next.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
13 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/res/values-sw600dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/res/values-sw720dp-land/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | 128dp
8 |
9 |
10 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 | 25dp
8 | 150dp
9 | 30dp
10 | 25sp
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ExampleGlobalParcelable
5 | Settings
6 |
7 | Enter Username
8 | Enter Name
9 | Next
10 |
11 | Enter Todo Item
12 | Select Todo Type
13 | Select Todo Type
14 | Add
15 |
16 |
17 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/src/com/example/exampleglobalparcelable/GlobalParcelable.java:
--------------------------------------------------------------------------------
1 | package com.example.exampleglobalparcelable;
2 | import java.lang.reflect.Constructor;
3 | import java.lang.reflect.Field;
4 | import java.lang.reflect.Member;
5 | import java.lang.reflect.Method;
6 | import java.util.Arrays;
7 | import java.util.Comparator;
8 | import java.util.Date;
9 | import android.os.Parcel;
10 | import android.os.Parcelable;
11 | import android.util.Log;
12 |
13 | public abstract class GlobalParcelable implements Parcelable {
14 |
15 |
16 | public GlobalParcelable() {
17 | // TODO Auto-generated constructor stub
18 |
19 | }
20 |
21 | public GlobalParcelable(Parcel in) {
22 | String className = in.readString();
23 | Log.i("GlobalParcelable","Constructor: " + this.getClass().getSimpleName() + "; In parcel: " + className);
24 | try {
25 | rehydrate(this, in);
26 | } catch (IllegalArgumentException e) {
27 | // TODO Auto-generated catch block
28 | e.printStackTrace();
29 | } catch (IllegalAccessException e) {
30 | // TODO Auto-generated catch block
31 | e.printStackTrace();
32 | }
33 | }
34 |
35 |
36 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
37 | public GlobalParcelable createFromParcel(Parcel in) {
38 | // get class from first parcelled item
39 | Class> parceledClass;
40 | try {
41 | parceledClass = Class.forName(in.readString());
42 | Log.i("GlobalParcelable","Creator: " + parceledClass.getSimpleName());
43 | // create instance of that class
44 | GlobalParcelable model = (GlobalParcelable) parceledClass.newInstance();
45 | rehydrate(model, in);
46 | return model;
47 | } catch (ClassNotFoundException e) {
48 | // TODO Auto-generated catch block
49 | e.printStackTrace();
50 | } catch (InstantiationException e) {
51 | // TODO Auto-generated catch block
52 | e.printStackTrace();
53 | } catch (IllegalAccessException e) {
54 | // TODO Auto-generated catch block
55 | e.printStackTrace();
56 | }
57 | return null;
58 | }
59 |
60 | public GlobalParcelable[] newArray(int size) {
61 | return new GlobalParcelable[size];
62 | }
63 | };
64 |
65 |
66 |
67 | @Override
68 | public void writeToParcel(Parcel dest, int flags) {
69 | dest.writeString(this.getClass().getName());
70 | try {
71 | dehydrate(this, dest);
72 | } catch (IllegalArgumentException e) {
73 | // TODO Auto-generated catch block
74 | e.printStackTrace();
75 | } catch (IllegalAccessException e) {
76 | // TODO Auto-generated catch block
77 | e.printStackTrace();
78 | }
79 | }
80 |
81 |
82 | @Override
83 | public int describeContents() {
84 | // TODO Auto-generated method stub
85 | return 0;
86 | }
87 |
88 | // writes fields of a GlobalParcelable to a parcel
89 | // does not include the first parcelled item -- the class name
90 | protected static void dehydrate(GlobalParcelable model, Parcel out) throws IllegalArgumentException, IllegalAccessException {
91 | Log.i("GlobalParcelable","dehydrating... " + model.getClass().toString());
92 | // get the fields
93 | Field[] fields = model.getClass().getDeclaredFields();
94 | // sort the fields so it is in deterministic order
95 | Arrays.sort(fields, compareMemberByName);
96 | // populate the fields
97 | for (Field field : fields){
98 | field.setAccessible(true);
99 | if (field.getType().equals(int.class)) {
100 | out.writeInt(field.getInt(model));
101 | } else if (field.getType().equals(double.class)) {
102 | out.writeDouble(field.getDouble(model));
103 | } else if (field.getType().equals(float.class)) {
104 | out.writeFloat(field.getFloat(model));
105 | } else if (field.getType().equals(long.class)) {
106 | out.writeLong(field.getLong(model));
107 | } else if (field.getType().equals(String.class)) {
108 | out.writeString((String) field.get(model));
109 | } else if (field.getType().equals(boolean.class)) {
110 | out.writeByte(field.getBoolean(model) ? (byte) 1 : (byte) 0);
111 | } else if (field.getType().equals(Date.class)) {
112 | Date date = (Date) field.get(model);
113 | if (date != null) {
114 | out.writeLong(date.getTime());
115 | } else {
116 | out.writeLong(0);
117 | }
118 | } else if (GlobalParcelable.class.isAssignableFrom(field.getType())) {
119 | // why did this happen?
120 | Log.e("GlobalParcelable", "GlobalParcelable F*ck up: " + " (" + field.getType().toString() + ")");
121 | out.writeParcelable((GlobalParcelable) field.get(model), 0);
122 | } else {
123 | // wtf
124 | Log.e("GlobalParcelable", "Could not write field to parcel: " + " (" + field.getType().toString() + ")");
125 | }
126 | }
127 | }
128 |
129 | // reads the parcelled items and put them into this object's fields
130 | // must be run after getting the first parcelled item -- the class name
131 | protected static void rehydrate(GlobalParcelable model, Parcel in) throws IllegalArgumentException, IllegalAccessException {
132 | Log.i("GlobalParcelable","rehydrating... " + model.getClass().toString());
133 | // get the fields
134 | Field[] fields = model.getClass().getDeclaredFields();
135 | // sort the fields so it is in deterministic order
136 | Arrays.sort(fields, compareMemberByName);
137 | // populate the fields
138 | for (Field field : fields){
139 | field.setAccessible(true);
140 | if (field.getType().equals(int.class)) {
141 | field.set(model, in.readInt());
142 | } else if (field.getType().equals(double.class)) {
143 | field.set(model, in.readDouble());
144 | } else if (field.getType().equals(float.class)) {
145 | field.set(model, in.readFloat());
146 | } else if (field.getType().equals(long.class)) {
147 | field.set(model, in.readLong());
148 | } else if (field.getType().equals(String.class)) {
149 | field.set(model, in.readString());
150 | } else if (field.getType().equals(boolean.class)) {
151 | field.set(model, in.readByte() == 1);
152 | } else if (field.getType().equals(Date.class)) {
153 | Date date = new Date(in.readLong());
154 | field.set(model, date);
155 | } else if (GlobalParcelable.class.isAssignableFrom(field.getType())) {
156 | Log.e("GlobalParcelable", "read GlobalParcelable: " + " (" + field.getType().toString() + ")");
157 | field.set(model, in.readParcelable(field.getType().getClassLoader()));
158 | } else {
159 | // wtf
160 | Log.e("GlobalParcelable", "Could not read field from parcel: " + field.getName() + " (" + field.getType().toString() + ")");
161 | }
162 | }
163 | }
164 |
165 |
166 | /*
167 | * Comparator object for Members, Fields, and Methods
168 | */
169 | private static Comparator compareMemberByName =
170 | new CompareMemberByName();
171 |
172 | private static class CompareMemberByName implements Comparator {
173 | public int compare(Object o1, Object o2) {
174 | String s1 = ((Member)o1).getName();
175 | String s2 = ((Member)o2).getName();
176 |
177 | if (o1 instanceof Method) {
178 | s1 += getSignature((Method)o1);
179 | s2 += getSignature((Method)o2);
180 | } else if (o1 instanceof Constructor) {
181 | s1 += getSignature((Constructor)o1);
182 | s2 += getSignature((Constructor)o2);
183 | }
184 | return s1.compareTo(s2);
185 | }
186 | }
187 |
188 |
189 | /**
190 | * Compute the JVM signature for the class.
191 | */
192 | private static String getSignature(Class clazz) {
193 | String type = null;
194 | if (clazz.isArray()) {
195 | Class cl = clazz;
196 | int dimensions = 0;
197 | while (cl.isArray()) {
198 | dimensions++;
199 | cl = cl.getComponentType();
200 | }
201 | StringBuffer sb = new StringBuffer();
202 | for (int i = 0; i < dimensions; i++) {
203 | sb.append("[");
204 | }
205 | sb.append(getSignature(cl));
206 | type = sb.toString();
207 | } else if (clazz.isPrimitive()) {
208 | if (clazz == Integer.TYPE) {
209 | type = "I";
210 | } else if (clazz == Byte.TYPE) {
211 | type = "B";
212 | } else if (clazz == Long.TYPE) {
213 | type = "J";
214 | } else if (clazz == Float.TYPE) {
215 | type = "F";
216 | } else if (clazz == Double.TYPE) {
217 | type = "D";
218 | } else if (clazz == Short.TYPE) {
219 | type = "S";
220 | } else if (clazz == Character.TYPE) {
221 | type = "C";
222 | } else if (clazz == Boolean.TYPE) {
223 | type = "Z";
224 | } else if (clazz == Void.TYPE) {
225 | type = "V";
226 | }
227 | } else {
228 | type = "L" + clazz.getName().replace('.', '/') + ";";
229 | }
230 | return type;
231 | }
232 |
233 |
234 | /*
235 | * Compute the JVM method descriptor for the method.
236 | */
237 | private static String getSignature(Method meth) {
238 | StringBuffer sb = new StringBuffer();
239 |
240 | sb.append("(");
241 |
242 | Class[] params = meth.getParameterTypes(); // avoid clone
243 | for (int j = 0; j < params.length; j++) {
244 | sb.append(getSignature(params[j]));
245 | }
246 | sb.append(")");
247 | sb.append(getSignature(meth.getReturnType()));
248 | return sb.toString();
249 | }
250 |
251 | /*
252 | * Compute the JVM constructor descriptor for the constructor.
253 | */
254 | private static String getSignature(Constructor cons) {
255 | StringBuffer sb = new StringBuffer();
256 |
257 | sb.append("(");
258 |
259 | Class[] params = cons.getParameterTypes(); // avoid clone
260 | for (int j = 0; j < params.length; j++) {
261 | sb.append(getSignature(params[j]));
262 | }
263 | sb.append(")V");
264 | return sb.toString();
265 | }
266 | }
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/src/com/example/exampleglobalparcelable/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.exampleglobalparcelable;
2 |
3 |
4 | import java.util.Date;
5 |
6 | import android.app.Activity;
7 | import android.content.Intent;
8 | import android.os.Bundle;
9 | import android.util.Log;
10 | import android.view.Menu;
11 | import android.view.View;
12 | import android.view.View.OnClickListener;
13 | import android.widget.Button;
14 | import android.widget.EditText;
15 |
16 | public class MainActivity extends Activity {
17 | // Values for User class
18 | private ObjectA_User user;
19 | private String mUsername;
20 | private String mFirstName;
21 | private Date mCreatedOn;
22 |
23 | // UI references.
24 | private EditText mUsernameView;
25 | private EditText mFirstNameView;
26 |
27 |
28 | @Override
29 | protected void onCreate(Bundle savedInstanceState) {
30 | super.onCreate(savedInstanceState);
31 | setContentView(R.layout.activity_main);
32 | mUsernameView = (EditText) findViewById(R.id.username);
33 | mFirstNameView = (EditText) findViewById(R.id.firstName);
34 | Button nextBtn = (Button) findViewById(R.id.btn_next);
35 | nextBtn.setOnClickListener(new OnClickListener() {
36 | @Override
37 | public void onClick(View v) {
38 | goToNextPage();
39 | }
40 | });
41 | }
42 |
43 | private void goToNextPage() {
44 | Log.i("clicks","You Clicked Next Button on ManActivity");
45 |
46 | mUsername = mUsernameView.getText().toString();
47 | if (mUsername == "") mUsername = "anyonymous";
48 |
49 | mFirstName = mFirstNameView.getText().toString();
50 | if (mFirstName == "") mFirstName = "anyonymous";
51 |
52 | mCreatedOn = new Date();
53 |
54 | user = new ObjectA_User(mUsername,mFirstName,mCreatedOn);
55 |
56 | // pass user to NextActivity through Intent
57 | Intent intent = new Intent(getBaseContext(), NextActivity.class);
58 | intent.putExtra("com.example.exampleglobalparcelable.ObjectA", user);
59 | startActivity(intent);
60 | }
61 |
62 |
63 | @Override
64 | public boolean onCreateOptionsMenu(Menu menu) {
65 | // Inflate the menu; this adds items to the action bar if it is present.
66 | getMenuInflater().inflate(R.menu.main, menu);
67 | return true;
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/src/com/example/exampleglobalparcelable/NextActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.exampleglobalparcelable;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.view.Menu;
6 | import android.widget.TextView;
7 |
8 | public class NextActivity extends Activity {
9 |
10 | @Override
11 | protected void onCreate(Bundle savedInstanceState) {
12 | super.onCreate(savedInstanceState);
13 | setContentView(R.layout.activity_next);
14 | TextView mTitleView = (TextView) findViewById(R.id.firstName);
15 |
16 | Bundle b = getIntent().getExtras();
17 | ObjectA_User objA = b.getParcelable("com.example.exampleglobalparcelable.ObjectA");
18 |
19 | mTitleView.setText(objA.getFirstName() + "'s Todo List");
20 |
21 | }
22 |
23 | @Override
24 | public boolean onCreateOptionsMenu(Menu menu) {
25 | // Inflate the menu; this adds items to the action bar if it is present.
26 | getMenuInflater().inflate(R.menu.main, menu);
27 | return true;
28 | }
29 |
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/src/com/example/exampleglobalparcelable/ObjectA_User.java:
--------------------------------------------------------------------------------
1 | package com.example.exampleglobalparcelable;
2 |
3 | import java.util.Date;
4 |
5 |
6 | public class ObjectA_User extends GlobalParcelable {
7 | private Date createdOn;
8 | private String username;
9 | private String firstName;
10 |
11 | public ObjectA_User() {}
12 |
13 | public ObjectA_User(String username, String firstName, Date createdOn) {
14 | this.username = username;
15 | this.firstName = firstName;
16 | this.createdOn = createdOn;
17 | }
18 |
19 | public Date getCreatedOn() {
20 | return createdOn;
21 | }
22 |
23 | public void setCreatedOn(Date createdOn) {
24 | this.createdOn = createdOn;
25 | }
26 |
27 | public String getUsername() {
28 | return username;
29 | }
30 |
31 | public void setUsername(String name) {
32 | this.username = name;
33 | }
34 |
35 | public String getFirstName() {
36 | return firstName;
37 | }
38 |
39 | public void setFirstName(String firstName) {
40 | this.firstName = firstName;
41 | }
42 |
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/ExampleGlobalParcelable/src/com/example/exampleglobalparcelable/ObjectB_ToDo.java:
--------------------------------------------------------------------------------
1 | package com.example.exampleglobalparcelable;
2 |
3 | import java.util.Date;
4 |
5 | public class ObjectB_ToDo extends GlobalParcelable {
6 |
7 | public enum Type {
8 | PRODUCTIVITY,
9 | TASKS,
10 | REMINDERS,
11 | }
12 |
13 | public enum Status {
14 | NEW,
15 | HALFDONE,
16 | DONE,
17 | }
18 |
19 | public ObjectB_ToDo() {
20 | super();
21 | }
22 |
23 | public ObjectB_ToDo(ObjectA_User createdBy, Date createdOn, Type type, Status status, boolean isPushedToServer) {
24 | super();
25 | this.setCreatedBy(createdBy);
26 | this.setCreatedOn(createdOn);
27 | this.setType(type);
28 | this.setStatus(status);
29 | }
30 |
31 | private long id;
32 |
33 | private ObjectA_User createdBy;
34 |
35 | private String createdByUsername;
36 |
37 | private Date createdOn;
38 |
39 | private Type type;
40 |
41 | private Status status;
42 |
43 |
44 |
45 | /*
46 | * Getters and Setters
47 | */
48 | public long getId() {
49 | return id;
50 | }
51 |
52 | public void setId(long id) {
53 | this.id = id;
54 | }
55 |
56 | public ObjectA_User getCreatedBy() {
57 | return createdBy;
58 | }
59 |
60 | public void setCreatedBy(ObjectA_User createdBy) {
61 | this.createdBy = createdBy;
62 | this.createdByUsername = createdBy.getUsername();
63 | }
64 |
65 | public Date getCreatedOn() {
66 | return createdOn;
67 | }
68 |
69 | public void setCreatedOn(Date createdOn) {
70 | this.createdOn = createdOn;
71 | }
72 |
73 | public String getCreatedByUsername() {
74 | return createdByUsername;
75 | }
76 |
77 | public void setCreatedByUsername(String createdByUsername) {
78 | this.createdByUsername = createdByUsername;
79 | }
80 |
81 | public Type getType() {
82 | return type;
83 | }
84 |
85 | public void setType(Type type) {
86 | this.type = type;
87 | }
88 |
89 | public Status getStatus() {
90 | return status;
91 | }
92 |
93 | public void setStatus(Status status) {
94 | this.status = status;
95 | }
96 |
97 |
98 |
99 | }
--------------------------------------------------------------------------------
/GlobalParcelable.java:
--------------------------------------------------------------------------------
1 |
2 | import java.lang.reflect.Constructor;
3 | import java.lang.reflect.Field;
4 | import java.lang.reflect.Member;
5 | import java.lang.reflect.Method;
6 | import java.util.Arrays;
7 | import java.util.Comparator;
8 | import java.util.Date;
9 | import android.os.Parcel;
10 | import android.os.Parcelable;
11 | import android.util.Log;
12 |
13 | public abstract class GlobalParcelable implements Parcelable {
14 |
15 |
16 | public GlobalParcelable() {
17 | // TODO Auto-generated constructor stub
18 |
19 | }
20 |
21 | public GlobalParcelable(Parcel in) {
22 | String className = in.readString();
23 | Log.i("GlobalParcelable","Constructor: " + this.getClass().getSimpleName() + "; In parcel: " + className);
24 | try {
25 | rehydrate(this, in);
26 | } catch (IllegalArgumentException e) {
27 | // TODO Auto-generated catch block
28 | e.printStackTrace();
29 | } catch (IllegalAccessException e) {
30 | // TODO Auto-generated catch block
31 | e.printStackTrace();
32 | }
33 | }
34 |
35 |
36 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
37 | public GlobalParcelable createFromParcel(Parcel in) {
38 | // get class from first parcelled item
39 | Class> parceledClass;
40 | try {
41 | parceledClass = Class.forName(in.readString());
42 | Log.i("GlobalParcelable","Creator: " + parceledClass.getSimpleName());
43 | // create instance of that class
44 | GlobalParcelable model = (GlobalParcelable) parceledClass.newInstance();
45 | rehydrate(model, in);
46 | return model;
47 | } catch (ClassNotFoundException e) {
48 | // TODO Auto-generated catch block
49 | e.printStackTrace();
50 | } catch (InstantiationException e) {
51 | // TODO Auto-generated catch block
52 | e.printStackTrace();
53 | } catch (IllegalAccessException e) {
54 | // TODO Auto-generated catch block
55 | e.printStackTrace();
56 | }
57 | return null;
58 | }
59 |
60 | public GlobalParcelable[] newArray(int size) {
61 | return new GlobalParcelable[size];
62 | }
63 | };
64 |
65 |
66 |
67 | @Override
68 | public void writeToParcel(Parcel dest, int flags) {
69 | dest.writeString(this.getClass().getName());
70 | try {
71 | dehydrate(this, dest);
72 | } catch (IllegalArgumentException e) {
73 | // TODO Auto-generated catch block
74 | e.printStackTrace();
75 | } catch (IllegalAccessException e) {
76 | // TODO Auto-generated catch block
77 | e.printStackTrace();
78 | }
79 | }
80 |
81 |
82 | @Override
83 | public int describeContents() {
84 | // TODO Auto-generated method stub
85 | return 0;
86 | }
87 |
88 | // writes fields of a GlobalParcelable to a parcel
89 | // does not include the first parcelled item -- the class name
90 | protected static void dehydrate(GlobalParcelable model, Parcel out) throws IllegalArgumentException, IllegalAccessException {
91 | Log.i("GlobalParcelable","dehydrating... " + model.getClass().toString());
92 | // get the fields
93 | Field[] fields = model.getClass().getDeclaredFields();
94 | // sort the fields so it is in deterministic order
95 | Arrays.sort(fields, compareMemberByName);
96 | // populate the fields
97 | for (Field field : fields){
98 | field.setAccessible(true);
99 | if (field.getType().equals(int.class)) {
100 | out.writeInt(field.getInt(model));
101 | } else if (field.getType().equals(double.class)) {
102 | out.writeDouble(field.getDouble(model));
103 | } else if (field.getType().equals(float.class)) {
104 | out.writeFloat(field.getFloat(model));
105 | } else if (field.getType().equals(long.class)) {
106 | out.writeLong(field.getLong(model));
107 | } else if (field.getType().equals(String.class)) {
108 | out.writeString((String) field.get(model));
109 | } else if (field.getType().equals(boolean.class)) {
110 | out.writeByte(field.getBoolean(model) ? (byte) 1 : (byte) 0);
111 | } else if (field.getType().equals(Date.class)) {
112 | Date date = (Date) field.get(model);
113 | if (date != null) {
114 | out.writeLong(date.getTime());
115 | } else {
116 | out.writeLong(0);
117 | }
118 | } else if (GlobalParcelable.class.isAssignableFrom(field.getType())) {
119 | // why did this happen?
120 | Log.e("GlobalParcelable", "GlobalParcelable F*ck up: " + " (" + field.getType().toString() + ")");
121 | out.writeParcelable((GlobalParcelable) field.get(model), 0);
122 | } else {
123 | // wtf
124 | Log.e("GlobalParcelable", "Could not write field to parcel: " + " (" + field.getType().toString() + ")");
125 | }
126 | }
127 | }
128 |
129 | // reads the parcelled items and put them into this object's fields
130 | // must be run after getting the first parcelled item -- the class name
131 | protected static void rehydrate(GlobalParcelable model, Parcel in) throws IllegalArgumentException, IllegalAccessException {
132 | Log.i("GlobalParcelable","rehydrating... " + model.getClass().toString());
133 | // get the fields
134 | Field[] fields = model.getClass().getDeclaredFields();
135 | // sort the fields so it is in deterministic order
136 | Arrays.sort(fields, compareMemberByName);
137 | // populate the fields
138 | for (Field field : fields){
139 | field.setAccessible(true);
140 | if (field.getType().equals(int.class)) {
141 | field.set(model, in.readInt());
142 | } else if (field.getType().equals(double.class)) {
143 | field.set(model, in.readDouble());
144 | } else if (field.getType().equals(float.class)) {
145 | field.set(model, in.readFloat());
146 | } else if (field.getType().equals(long.class)) {
147 | field.set(model, in.readLong());
148 | } else if (field.getType().equals(String.class)) {
149 | field.set(model, in.readString());
150 | } else if (field.getType().equals(boolean.class)) {
151 | field.set(model, in.readByte() == 1);
152 | } else if (field.getType().equals(Date.class)) {
153 | Date date = new Date(in.readLong());
154 | field.set(model, date);
155 | } else if (GlobalParcelable.class.isAssignableFrom(field.getType())) {
156 | Log.e("GlobalParcelable", "read GlobalParcelable: " + " (" + field.getType().toString() + ")");
157 | field.set(model, in.readParcelable(field.getType().getClassLoader()));
158 | } else {
159 | // wtf
160 | Log.e("GlobalParcelable", "Could not read field from parcel: " + field.getName() + " (" + field.getType().toString() + ")");
161 | }
162 | }
163 | }
164 |
165 |
166 | /*
167 | * Comparator object for Members, Fields, and Methods
168 | */
169 | private static Comparator compareMemberByName =
170 | new CompareMemberByName();
171 |
172 | private static class CompareMemberByName implements Comparator {
173 | public int compare(Object o1, Object o2) {
174 | String s1 = ((Member)o1).getName();
175 | String s2 = ((Member)o2).getName();
176 |
177 | if (o1 instanceof Method) {
178 | s1 += getSignature((Method)o1);
179 | s2 += getSignature((Method)o2);
180 | } else if (o1 instanceof Constructor) {
181 | s1 += getSignature((Constructor)o1);
182 | s2 += getSignature((Constructor)o2);
183 | }
184 | return s1.compareTo(s2);
185 | }
186 | }
187 |
188 |
189 | /**
190 | * Compute the JVM signature for the class.
191 | */
192 | private static String getSignature(Class clazz) {
193 | String type = null;
194 | if (clazz.isArray()) {
195 | Class cl = clazz;
196 | int dimensions = 0;
197 | while (cl.isArray()) {
198 | dimensions++;
199 | cl = cl.getComponentType();
200 | }
201 | StringBuffer sb = new StringBuffer();
202 | for (int i = 0; i < dimensions; i++) {
203 | sb.append("[");
204 | }
205 | sb.append(getSignature(cl));
206 | type = sb.toString();
207 | } else if (clazz.isPrimitive()) {
208 | if (clazz == Integer.TYPE) {
209 | type = "I";
210 | } else if (clazz == Byte.TYPE) {
211 | type = "B";
212 | } else if (clazz == Long.TYPE) {
213 | type = "J";
214 | } else if (clazz == Float.TYPE) {
215 | type = "F";
216 | } else if (clazz == Double.TYPE) {
217 | type = "D";
218 | } else if (clazz == Short.TYPE) {
219 | type = "S";
220 | } else if (clazz == Character.TYPE) {
221 | type = "C";
222 | } else if (clazz == Boolean.TYPE) {
223 | type = "Z";
224 | } else if (clazz == Void.TYPE) {
225 | type = "V";
226 | }
227 | } else {
228 | type = "L" + clazz.getName().replace('.', '/') + ";";
229 | }
230 | return type;
231 | }
232 |
233 |
234 | /*
235 | * Compute the JVM method descriptor for the method.
236 | */
237 | private static String getSignature(Method meth) {
238 | StringBuffer sb = new StringBuffer();
239 |
240 | sb.append("(");
241 |
242 | Class[] params = meth.getParameterTypes(); // avoid clone
243 | for (int j = 0; j < params.length; j++) {
244 | sb.append(getSignature(params[j]));
245 | }
246 | sb.append(")");
247 | sb.append(getSignature(meth.getReturnType()));
248 | return sb.toString();
249 | }
250 |
251 | /*
252 | * Compute the JVM constructor descriptor for the constructor.
253 | */
254 | private static String getSignature(Constructor cons) {
255 | StringBuffer sb = new StringBuffer();
256 |
257 | sb.append("(");
258 |
259 | Class[] params = cons.getParameterTypes(); // avoid clone
260 | for (int j = 0; j < params.length; j++) {
261 | sb.append(getSignature(params[j]));
262 | }
263 | sb.append(")V");
264 | return sb.toString();
265 | }
266 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Android-Global-Parcelable
2 | =========================
3 |
4 | Serialization in Java was far too slow for Android, so they created the Parcelable class that android developers use to serialize data. The Parcelable approach requires that you explicitly serialize the members of your class, but in the end, you get a much faster serialization of your objects. The problem is you have to do this with every class you create. In a large project with many classes with many objects this becomes tedious violating the rules of code reusability. The solution is to create the Global Parcelable class that all other classes can extend.
5 |
--------------------------------------------------------------------------------