CS 491 Lecture 9 – On Today and JSON
Agenda
- what ?s
- tracking memories on this day in history
- database
- getting and putting memories through $_REQUEST
- exchanging data with JSON
- an Android client
Code
schema.sql
DROP TABLE IF EXISTS memory;
CREATE TABLE memory (
id INT AUTO_INCREMENT PRIMARY KEY,
year INT,
month INT,
day INT,
log TEXT
);
put.php
<?php
require_once('globals.php');
$feedback = array();
$_REQUEST = json_decode(file_get_contents("php://input"), true);
$db = new mysqli('localhost', 'twodeeor_vanuser', PASSWORD, 'twodeeor_ontoday');
if ($db->connect_errno) {
$feedback['ok'] = false;
$feedback['error'] = $db->connect_errno;
} else {
// Editing existing...
if ($_REQUEST['id'] < 0) {
$statement = $db->prepare("INSERT INTO memory (year, month, day, log) VALUES (?, ?, ?, ?)");
if ($statement) {
$statement->bind_param('iiis', $_REQUEST['year'], $_REQUEST['month'], $_REQUEST['day'], $_REQUEST['log']);
}
}
// Adding new...
else {
$statement = $db->prepare("UPDATE memory SET year = ?, month = ?, day = ?, log = ? WHERE id = ?");
if ($statement) {
$statement->bind_param('iiisi', $_REQUEST['year'], $_REQUEST['month'], $_REQUEST['day'], $_REQUEST['log'], $_REQUEST['id']);
}
}
if (!$statement) {
$feedback['ok'] = false;
$feedback['error'] = $db->error;
} else {
$ok = $statement->execute();
$statement->free_result();
$feedback['ok'] = true;
}
$db->close();
}
echo json_encode($feedback);
?>
get.php
<?php
require_once('globals.php');
$feedback = array();
$_REQUEST = json_decode(file_get_contents("php://input"), true);
$db = new mysqli('localhost', 'twodeeor_vanuser', PASSWORD, 'twodeeor_ontoday');
if ($db->connect_errno) {
$feedback['ok'] = false;
$feedback['error'] = $db->connect_errno;
} else {
$statement = $db->prepare("SELECT * FROM memory WHERE month = ? AND day = ? ORDER BY year DESC");
if (!$statement) {
$feedback['ok'] = false;
$feedback['error'] = $db->error;
} else {
$statement->bind_param('ii', $_REQUEST['month'], $_REQUEST['day']);
$ok = $statement->execute();
$statement->bind_result($id, $year, $month, $day, $log);
$feedback['memories'] = array();
while ($statement->fetch()) {
$memory = array();
$memory['id'] = $id;
$memory['year'] = $year;
$memory['month'] = $month;
$memory['day'] = $day;
$memory['log'] = $log;
array_push($feedback['memories'], $memory);
}
$statement->free_result();
$feedback['ok'] = true;
}
$db->close();
}
echo json_encode($feedback);
?>
edit.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/logEditor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Enter memory..."
android:lines="5"
android:inputType="textMultiLine">
<requestFocus />
</EditText>
</LinearLayout>
activity_main.xml
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<DatePicker
android:id="@+id/datePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="18dp" />
<Button
android:id="@+id/addTodayButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/datePicker"
android:layout_marginTop="20dp"
android:text="Add today's memory" />
<ListView
android:id="@+id/logView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_below="@+id/addTodayButton"></ListView>
</RelativeLayout>
Memory.java
package org.twodee.ontoday;
import org.json.JSONException;
import org.json.JSONObject;
public class Memory {
private int id;
private int year;
private int month;
private int day;
private String log;
public Memory(int id,
int year,
int month,
int day,
String log) {
super();
this.id = id;
this.year = year;
this.month = month;
this.day = day;
this.log = log;
}
public int getId() {
return id;
}
public int getYear() {
return year;
}
public int getMonth() {
return month;
}
public int getDay() {
return day;
}
public String getLog() {
return log;
}
public void setLog(String log) {
this.log = log;
}
public String toString() {
return year + " - " + log;
}
public JSONObject toJSON() {
JSONObject object = new JSONObject();
try {
object.put("id", id);
object.put("year", year);
object.put("month", month);
object.put("day", day);
object.put("log", log);
} catch (JSONException e) {
e.printStackTrace();
}
return object;
}
public String getDateString() {
return String.format("%d/%d/%d", year, month, day);
}
}
MainActivity.java
package org.twodee.ontoday;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Scanner;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.DatePicker.OnDateChangedListener;
import android.widget.EditText;
import android.widget.ListView;
public class MainActivity extends Activity {
private ListView logView;
private ArrayAdapter<Memory> logAdapter;
private DatePicker datePicker;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
datePicker = (DatePicker) findViewById(R.id.datePicker);
logView = (ListView) findViewById(R.id.logView);
final Button addButton = (Button) findViewById(R.id.addTodayButton);
addButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
edit(new Memory(-1, datePicker.getYear(), datePicker.getMonth() + 1, datePicker.getDayOfMonth(), ""));
}
});
logAdapter = new ArrayAdapter<Memory>(this, android.R.layout.simple_list_item_1);
logView.setAdapter(logAdapter);
final Calendar today = Calendar.getInstance();
datePicker.init(today.get(Calendar.YEAR), today.get(Calendar.MONTH), today.get(Calendar.DAY_OF_MONTH), new OnDateChangedListener() {
@Override
public void onDateChanged(DatePicker picker,
int year,
int month,
int day) {
load(month + 1, day);
}
});
load(10, 1);
}
protected void load(final int month,
final int day) {
new AsyncTask<Void, Void, ArrayList<Memory>>() {
@Override
protected ArrayList<Memory> doInBackground(Void... args) {
ArrayList<Memory> memories = new ArrayList<Memory>();
try {
JSONObject json = new JSONObject();
json.put("month", month);
json.put("day", day);
json = makeRequest("http://www.twodee.org/ontoday/get.php", json);
if (json.has("memories")) {
JSONArray memoriesJSON = json.getJSONArray("memories");
for (int i = 0; i < memoriesJSON.length(); ++i) {
JSONObject memoryJSON = memoriesJSON.getJSONObject(i);
memories.add(new Memory(memoryJSON.getInt("id"),
memoryJSON.getInt("year"),
memoryJSON.getInt("month"),
memoryJSON.getInt("day"),
memoryJSON.getString("log")));
}
}
} catch (JSONException e) {
Log.d("FOO", "Bad JSON Parsing");
}
return memories;
}
@Override
protected void onPostExecute(ArrayList<Memory> memories) {
logAdapter.clear();
logAdapter.addAll(memories);
}
}.execute();
}
private void edit(final Memory memory) {
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setTitle("Memory for " + memory.getDateString());
View body = LayoutInflater.from(this).inflate(R.layout.edit, null);
final EditText logEditor = (EditText) body.findViewById(R.id.logEditor);
dialog.setView(body);
dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
memory.setLog(logEditor.getText().toString());
upload(memory);
}
});
dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
dialog.cancel();
}
});
dialog.show();
}
private void upload(final Memory memory) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... arg0) {
makeRequest("http://www.twodee.org/ontoday/put.php", memory.toJSON());
return null;
}
@Override
protected void onPostExecute(Void result) {
load(datePicker.getMonth() + 1, datePicker.getDayOfMonth());
}
}.execute();
}
private JSONObject makeRequest(String url, JSONObject json) {
try {
URI uri = new URI(String.format(url));
HttpPost post = new HttpPost(uri);
StringEntity entity = new StringEntity(json.toString());
Log.d("FOO", "sending " + json.toString());
entity.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(entity);
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(post);
Scanner in = new Scanner(response.getEntity().getContent());
in.useDelimiter("\\Z");
String body = in.next();
in.close();
Log.d("FOO", body);
return new JSONObject(body);
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
}
Haiku
Mom feared the teen years
“Grow, but let’s not stop talking.”
She named me JSON
“Grow, but let’s not stop talking.”
She named me JSON