Deprecated: Creation of dynamic property wpdb::$categories is deprecated in /var/www/twodee/blog/wp-includes/wp-db.php on line 668

Deprecated: Creation of dynamic property wpdb::$post2cat is deprecated in /var/www/twodee/blog/wp-includes/wp-db.php on line 668

Deprecated: Creation of dynamic property wpdb::$link2cat is deprecated in /var/www/twodee/blog/wp-includes/wp-db.php on line 668

Deprecated: Return type of WP_Theme::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 554

Deprecated: Return type of WP_Theme::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 595

Deprecated: Return type of WP_Theme::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 535

Deprecated: Return type of WP_Theme::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 544

Deprecated: Return type of WP_REST_Request::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 960

Deprecated: Return type of WP_REST_Request::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 980

Deprecated: Return type of WP_REST_Request::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 992

Deprecated: Return type of WP_REST_Request::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 1003

Deprecated: Return type of WP_Block_List::current() should either be compatible with Iterator::current(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 151

Deprecated: Return type of WP_Block_List::next() should either be compatible with Iterator::next(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 175

Deprecated: Return type of WP_Block_List::key() should either be compatible with Iterator::key(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 164

Deprecated: Return type of WP_Block_List::valid() should either be compatible with Iterator::valid(): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 186

Deprecated: Return type of WP_Block_List::rewind() should either be compatible with Iterator::rewind(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 138

Deprecated: Return type of WP_Block_List::offsetExists($index) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 75

Deprecated: Return type of WP_Block_List::offsetGet($index) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 89

Deprecated: Return type of WP_Block_List::offsetSet($index, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 110

Deprecated: Return type of WP_Block_List::offsetUnset($index) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 127

Deprecated: Return type of WP_Block_List::count() should either be compatible with Countable::count(): int, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 199

Deprecated: Creation of dynamic property Automattic\Jetpack\Connection\Manager::$error_handler is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-connection/src/class-manager.php on line 91

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Instagram_Gallery::$is_wpcom is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-instagram-gallery.php on line 23

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Mailchimp::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-mailchimp.php on line 17

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Tweetstorm_Gather::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-tweetstorm-gather.php on line 21

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Tweetstorm_Gather::$is_wpcom is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-tweetstorm-gather.php on line 22

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Gutenberg_Available_Extensions::$wpcom_is_site_specific_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/gutenberg-available-extensions.php on line 20

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Memberships::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php on line 23

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Memberships::$wpcom_is_site_specific_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php on line 24

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Subscribers::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/subscribers.php on line 15

Deprecated: Creation of dynamic property Automattic\Jetpack\Sync\Queue::$random_int is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-sync/src/class-queue.php on line 38

Deprecated: Creation of dynamic property Automattic\Jetpack\Sync\Queue::$random_int is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-sync/src/class-queue.php on line 38

Deprecated: Creation of dynamic property WPCOM_Widget_Goodreads::$shelves is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/modules/widgets/goodreads.php on line 33

Deprecated: DateTime::__construct(): Passing null to parameter #1 ($datetime) of type string is deprecated in /var/www/twodee/blog/wp-includes/script-loader.php on line 348

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$toolbar_classic_block is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 347

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$toolbar_block is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 349

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$toolbar_block_side is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 350

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$panels_block is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 351

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$used_block_buttons is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 354

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198
» CS 491 Lecture 13 – Wevents Part II

teaching machines

CS 491 Lecture 13 – Wevents Part II

October 20, 2011 by . Filed under
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383
cs491 mobile, fall 2011, lectures.

Agenda

Ice Cream Sandwich

It was unveiled yesterday.

Asynchronous networking

Okay, our database backend is in order. Our PHP scripts will serve as the bridge between the database and clients, who will perform all transactions through HTTP. Let’s make our Android client, starting with an activity for authentication. It uses a simple TableLayout. On button-click, we’d like to pass the username and password off the authenticate PHP script. If the PHP script reports success, we can move to our main activity. Otherwise, we sit tight.

We’ve got to ship stuff off to our PHP script. That means a trip over the network. That means don’t do it in the main thread. We could do it in a thread in our Activity, but Activitys can get destroyed if they’re not focused. Let’s farm our network tasks out to a Service. And not just any service. An IntentService, which is ideal for handling asynchronous tasks:

public class WeventsService extends IntentService {
  public WeventsService() {
    super("WebGetService");
  }

  @Override
  protected void onHandleIntent(final Intent intent) {
    // perform some task
  }
}

That onHandleIntent method will get called whenever startService is issued. Our service will ultimately have many clients, all of whose requests will funnel into onHandleIntent. So, we need some means of specifying the action we’d like the service to perform. Let’s create some constants for these actions:

public static final String ACTION_GET_ALL = "org.twodee.wevents.ACTION_GET_ALL";
public static final String ACTION_AUTHENTICATE = "org.twodee.wevents.ACTION_AUTHENTICATE";
public static final String ACTION_UPDATE_WIDGET = "org.twodee.wevents.ACTION_UPDATE_WIDGET";

We can issue a request in AuthenticateActivity with:

Intent intent = new Intent(WeventsApplication.ACTION_AUTHENTICATE, null, AuthenticateActivity.this, WeventsService.class);
startService(intent);

We’re using the only Intent constructor that lets us specify both an action and an explicit intent-satisfier. It’d be a good idea to Toast the action in onHandleIntent before moving on:

Toast.makeText(this, intent.getAction(), Toast.LENGTH_SHORT).show();

Reading from a network

On these actions, we want our service to go out and make an HTTP request. For this, Android ships with Apache’s HTTP API, which Google recommends over Java’s. A simple fetch looks like:

private Bundle fetch(String url) {
  int resultCode = 0;
  String content = null;

  HttpClient client = new DefaultHttpClient();
  HttpGet request = new HttpGet(url);

  try {
    ResponseHandler<String> handler = new BasicResponseHandler();
    content = client.execute(request, handler);
  } catch (ClientProtocolException e) {
    resultCode = 1;
    content = "client protocol error";
  } catch (IOException e) {
    resultCode = 1;
    content = "I/O error";
  }
  client.getConnectionManager().shutdown();

  Bundle bundle = new Bundle();
  bundle.putString("content", content);
  bundle.putInt("resultCode", resultCode);

  return bundle;
}

Don’t forget! Service code runs in the main thread. We need to spawn a new fetch thread to avoid ANRs. But once fetched, what do we do with the result?

Communicating back to clients

We’d seen in Lonely Phone that apps can bind a service and access it via a local binder. But what if we want the service to push data to an Activity? For that, we need a ResultReceiver. This class imposes a callback onReceiveResult that gets called when someone sends something to it. Unfortunately, it’s a class, not an interface. Since Java doesn’t support multiple inheritance, let’s create another class which advertises its own interface and passes the results along:

public class WeventsReceiver extends ResultReceiver {
  private Receiver receiver;

  public WeventsReceiver(Handler handler) {
    super(handler);
  }

  public void setReceiver(Receiver receiver) {
    this.receiver = receiver;
  }

  @Override
  protected void onReceiveResult(int resultCode, Bundle resultData) {
    if (receiver != null) {
      receiver.onReceiveResult(resultCode, resultData);
    }
  }

  public interface Receiver {
    public void onReceiveResult(int resultCode, Bundle resultData);
  }
}

Now our client Activitys can implement WeventsReceiver.Receiver. They can handle the content however they choose:

public class AuthenticateActivity extends Activity implements WeventsReceiver.Receiver {
  // ...

  @Override
  public void onReceiveResult(int resultCode,
                              Bundle resultData) {
     // ...
  }
}

The last step is pass our receiver along when we issue the intent to the service:

intent.putExtra("receiver", receiver);

On receiving the intent, the service can run a thread like this:

new Thread(new Runnable() {
  @Override
  public void run() {
    ResultReceiver receiver = intent.getParcelableExtra("receiver");
    Bundle bundle = fetch("http://www.uwec.edu/");
    receiver.send(bundle.getInt("resultCode"), bundle);
    stopSelf();
  }
}).start();

Passing parameters via HTTP

To authenticate with the database server, we need to get our username and password to the PHP script. HTTP defines two commands, GET and POST that can help. Both request types can pass along parameters to the web server. GET embeds them in the URL, while POST sends them along after the header. Mostly they are equivalent for our purposes. We’ll use POST.

Our AuthenticateActivity needs to send along the form values via the Intent. The service then picks them off and creates a list of NameValuePairs (Apache’s creation):

ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("username", intent.getStringExtra("username")));
postParameters.add(new BasicNameValuePair("password", intent.getStringExtra("password")));

Our fetch routine changes a bit:

private Bundle fetch(String url,
                     ArrayList<NameValuePair> postParameters) {
  int resultCode = 0;
  String content = null;

  HttpClient client = new DefaultHttpClient();
  HttpPost request = new HttpPost(url);

  try {
    UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(postParameters);
    request.setEntity(formEntity);
    ResponseHandler<String> handler = new BasicResponseHandler();
    content = client.execute(request, handler);
  } catch (UnsupportedEncodingException e1) {
    resultCode = 1;
    content = "bad encoding";
  } catch (ClientProtocolException e) {
    resultCode = 1;
    content = "client protocol error";
  } catch (IOException e) {
    resultCode = 1;
    content = "I/O error";
  }
  client.getConnectionManager().shutdown();

  Bundle bundle = new Bundle();
  bundle.putString("content", content);
  bundle.putInt("resultCode", resultCode);

  return bundle;
}

In PHP, we use our POST data instead of hardcoded values:

<?php
$db = pg_connect("dbname=databasename user=${_POST['username']} password=${_POST['password']}");
if ($db) {
  echo 'ok';
} else {
  echo 'boo';
}
?>

Now, we pass the result back to the AuthenticateActivity. Neat.

Wevents List

After authentication, we probably want to pop up a view with the list of events. It’ll need to ask the service to perform a query asynchronously and await the results, which will be a JSON structure. Let’s translate the set of events to a bulleted list:

static String jsonEventsToList(String json) {
  StringBuilder builder = new StringBuilder();

  try {
    JSONArray jsonArray = new JSONArray(json);
    builder.append("<ol>");
    for (int i = 0; i < jsonArray.length(); ++i) {
      JSONObject jsonObject = jsonArray.getJSONObject(i);
      builder.append("&#8226; ");
      builder.append(jsonObject.getString("description"));
      builder.append("<br/>");
    }
    builder.append("</ol>");
  } catch (JSONException e) {
    builder.append("Couldn't parse result!");
  }
    
  return builder.toString();
}

Gotcha

There’s an issue we need to address yet. If a client Activity changes configurations or closes while the service is performing an operation, we’re going to run into trouble.