Creating a Facebook Clone - Part XL - Transcript.pdf
1. Creating a Facebook Clone - Part XL
We’re proceeding with the image & video integration
2. public class Post implements PropertyBusinessObject {
public final Property<String, Post> id = new Property<>("id");
public final Property<User, Post> user = new Property<>("user",
User.class);
public final LongProperty<Post> date = new LongProperty<>("date");
public final Property<String, Post> title = new Property<>("title");
public final Property<String, Post> content = new Property<>("content");
public final Property<String, Post> visibility =
new Property<>("visibility");
public final Property<String, Post> styling = new Property<>("styling");
public final ListProperty<Comment, Post> comments =
new ListProperty<>("comments", Comment.class);
public final ListProperty<User, Post> likes =
new ListProperty<>("likes", User.class);
public final MapProperty<String, String, Post> attachments =
new MapProperty<>("attachments", String.class, String.class);
private final PropertyIndex idx = new PropertyIndex(this, "Post",
id, user, date, title, content, visibility, styling, comments,
likes, attachments);
@Override
Post
The changes to the client side Post class are trivial.
We added the map entry for the attachments
3. public class Post implements PropertyBusinessObject {
public final Property<String, Post> id = new Property<>("id");
public final Property<User, Post> user = new Property<>("user",
User.class);
public final LongProperty<Post> date = new LongProperty<>("date");
public final Property<String, Post> title = new Property<>("title");
public final Property<String, Post> content = new Property<>("content");
public final Property<String, Post> visibility =
new Property<>("visibility");
public final Property<String, Post> styling = new Property<>("styling");
public final ListProperty<Comment, Post> comments =
new ListProperty<>("comments", Comment.class);
public final ListProperty<User, Post> likes =
new ListProperty<>("likes", User.class);
public final MapProperty<String, String, Post> attachments =
new MapProperty<>("attachments", String.class, String.class);
private final PropertyIndex idx = new PropertyIndex(this, "Post",
id, user, date, title, content, visibility, styling, comments,
likes, attachments);
@Override
Post
and added it to the list of properties. This will automatically parse it from JSON and generate it to JSON when we send a server request.
4. public static boolean uploadContacts(Contact[] contacts) {
Response<String> s = post("user/contacts").
body(contactsToJSON(contacts)).getAsString();
return "OK".equals(s.getResponseData());
}
public static MultipartRequest uploadMedia(String mime, String role,
String visibility, String fileName, byte[] data,
SuccessCallback<String> callback) {
MultipartRequest mp = new MultipartRequest() {
private String mediaId;
@Override
protected void readResponse(InputStream input)
throws IOException {
mediaId = Util.readToString(input);
}
@Override
protected void postResponse() {
callback.onSucess(mediaId);
}
};
mp.setUrl(BASE_URL + "media/upload");
mp.addRequestHeader("auth", token);
mp.addRequestHeader("Accept", "application/json");
ServerAPI
We'll need one small change from ServerAPI, this is the last "infrastructure" change before we start "wiring everything together"...
When we submit an image post we'll upload the media before the post is written. This shouldn't be a problem for small images but anything larger or on a slow
connection could be a problem. So the right thing to do is show a progress indicator for the upload process. Unfortunately the upload method in ServerAPI doesn't allow
us to do this.
Furthermore, in one case we have a file path with no byte array data. Obviously we can load it ourselves but the multipart API already has support for that so we'll
leverage it in the API.
5. public static boolean uploadContacts(Contact[] contacts) {
Response<String> s = post("user/contacts").
body(contactsToJSON(contacts)).getAsString();
return "OK".equals(s.getResponseData());
}
public static MultipartRequest uploadMedia(String mime, String role,
String visibility, String fileName, byte[] data,
SuccessCallback<String> callback) {
MultipartRequest mp = new MultipartRequest() {
private String mediaId;
@Override
protected void readResponse(InputStream input)
throws IOException {
mediaId = Util.readToString(input);
}
@Override
protected void postResponse() {
callback.onSucess(mediaId);
}
};
mp.setUrl(BASE_URL + "media/upload");
mp.addRequestHeader("auth", token);
mp.addRequestHeader("Accept", "application/json");
ServerAPI
We now return the MultipartRequest so we can bind a progress indicator to it
6. }
@Override
protected void postResponse() {
callback.onSucess(mediaId);
}
};
mp.setUrl(BASE_URL + "media/upload");
mp.addRequestHeader("auth", token);
mp.addRequestHeader("Accept", "application/json");
mp.addArgument("role", role);
mp.addArgument("visibility", visibility);
if(data == null) {
try {
mp.addData("file", fileName, mime);
} catch(IOException err) {
Log.e(err);
throw new RuntimeException(err);
}
} else {
mp.addData("file", data, mime);
}
mp.setFilename("file", fileName);
addToQueue(mp);
return mp;
}
ServerAPI
If there is no data byte array we'll fallback to a file now, I didn't want to get into the IOException issue and just converted it to RuntimeException.
This is a simple change and the final piece before the upload code.