Mobile: Accessing remote data

wheatprisonΚινητά – Ασύρματες Τεχνολογίες

10 Δεκ 2013 (πριν από 3 χρόνια και 6 μήνες)

52 εμφανίσεις

Mobile: Accessing remote data

CS569 Selected Topics in Software Engineering

Spring 2012


Integrating remote content into

native mobile apps

1.
User opens mobile app

2.
App calls up the server, sends URL

3.
Server figures out how to handle request


Maybe just sends a file back


Maybe calls some custom code (JSP or servlet)

4.
Server sends HTML/XML/JSON to app

5.
App interprets data

6.
User interacts with app and is happy

Big picture

App

Server

Servlet

Data store

URL

Request

Query,
etc

Data

HTML/XML/JSON

HTML/XML/JSON

Zooming into the app

App

UI

Server

Servlet

Data store

URL

Request

Query,
etc

Data

HTML/XML/JSON

HTML/XML/JSON

App

JS

UI event

updates

Very simple example: just get html


var

url

= "http:/
/
www.google.com
/"
;

var

client =
Ti.Network.createHTTPClient
({


// function called when the response data is available


onload

: function(e) {


alert('success:'+
this.responseText
);


},


// function called when an error occurs, including a timeout


onerror

: function(e) {


alert('
error
'+
e.error
);


},


timeout

: 5000
/* in
milliseconds

*/


});


client.open("GET
",
url
);


client.send
();



Ti.UI.createWindow().open
();



1.
Make a servlet that
returns some HTML

2.
Hit the URL


Debugging
iOS

apps locally on a Mac

iOS

apps in simulator often can’t access GAE. Here’s a hideous workaround.


1.
Open Terminal (spotlight > Terminal)

2.
Map 127.0.0.1 to a fake hostname


vi /
etc
/hosts


arrow key down to the end of the document, type letter “a” to append


add the line: 127.0.0.1 www.cs569.com



to save, type: escape :w! escape :q

3.
Download Burp
proxy from

http
://
portswigger.net
/burp/
downloadfree.html

4.
Unzip Burp proxy, move files some place safe

5.
Set Burp as your Mac’s proxy (Apple Symbol in top left corner > System preferences > Advanced >
Proxies; check both Web Proxy and Secure Web Proxy, set the
ip

address to 127.0.0.1 and port to
8080)

6.
Go to Terminal and start up Burp


cd wherever you saved those Burp files


java
-
jar
-
Xmx2g burpsuite_v1.4.01.
jar

7.
Now that Burp is running, go to your regular browser and try to hit

http://www.cs569.com:8888/_ah/admin

8.
By default, Burp will block access. Go to the Burp window, proxy tab, and click “Intercept” button
to turn intercept off. Now the hostname should nicely map to your GAE admin console

9.
In your Titanium code, you should now be able to successfully retrieve data from GAE through
the fake hostname.

Debugging Android apps locally


Very simple: just
use 10.0.2.2
in your app to
refer to your own computer

Example: Getting HTML from GAE
running locally (
iOS
)

<%= (1+1) %>


var

url

=
"
http://www.cs569.com:8888/lectures/
mobileremote
/test1.jsp
"
;

var

client =
Ti.Network.createHTTPClient
({


// function called when the response data is available


onload

: function(e) {


alert('success:'+
this.responseText
);


},


// function called when an error occurs, including a timeout


onerror

: function(e) {


alert('
error
'+
e.error
);


},


timeout

: 5000
/* in
milliseconds

*/


});


client.open("GET
",
url
);


client.send
();



Ti.UI.createWindow().open
();



1.
Make a servlet that
returns some HTML

2.
In
iOS

app, create an http
client, with specified

onload
” and “
onerror

handlers.

3.
Open, send request.


Getting fancier: posting data

just like a browser would

you sent me a total of

<%=
Integer.parseInt
(
request.getParameter
("a")) +


Integer.parseInt
(
request.getParameter
("b")) %
>


var

url

= "http://www.cs569.com:8888/lectures/
mobileremote
/test2.jsp";

var

client =
Ti.Network.createHTTPClient
({


// function called when the response data is available


onload

: function(e) {


alert('success:'+
this.responseText
);


},


// function called when an error occurs, including a timeout


onerror

: function(e) {


alert('
error
'+
e.error
);


},


timeout

: 5000
/* in
milliseconds

*/


});


client.open("POST
",
url
);


client.send({a:1,b:2});



Ti.UI.createWindow().open
();


1.
Make a servlet that
returns some HTML

2.
In
iOS

app, create an http
client, with specified

onload
” and “
onerror

handlers.

3.
Open, send
POST request
with parameters.


GET
vs

POST


“idempotent operation”: means that an
operation can be repeated (or not) without any
side
-
effects


Idempotent operations are safe to repeat, or not



GET: use only for idempotent operations


Such as retrieving data


GET requests might be cached on the network or
repeated within the network multiple times or
performed automatically (e.g., by search engines)


POST: use for all other operations

Now you have some options…

… for what your servlet does with the data…



Use it for some computations


Store it in the
datastore


Forward it to another server (e.g.,
webservice
)

And some options for what to send
back…


HTML


Pros: No need to write a separate servlet


Cons: Very inefficient to send and parse HTML


XML


Pros: Compatible with many other systems


Cons: Moderately inefficient to send and parse


JSON


Pros: Highly efficient to send and parse


Cons: More work for you, in many cases

JSP for sending back XML

<%


// Note: there can be NO blank space at the top of the page

// The header (below) MUST be the first thing in the document


response.setContentType
("text/xml");

out.write
("<?xml version=
\
"1.0
\
" ?>");


%>

<
mydocument
>


<%


for (
int

i = 0; i < 10; i++)



out.write
("<
myelement

cnt
=
\
""+
i
+"
\
" />");


%>

</
mydocument
>

JS for reading XML in Titanium




onload

: function(e)
{


var

xml =
this.responseXML
;


var

els

=
xml.getElementsByTagName
("
myelement
");


var sum = 0;


for (var i = 0; i <
els.length
; i++) {



var
vl

=
parseFloat
(
els.item
(i).
getAttribute
("
cnt
"));



if (!isNaN(vl) && vl > 0) sum += vl;


}


alert("the sum is "+sum);


},




Welcome to JSON


“JavaScript Object Notation”


looks very
similar to how objects are defined in JS


However, it’s just a
notation
, and it’s
supported in other languages, too.


Example
:

{
"
title"
:
"
blah

blah blah",




"id"
:110,"emails":null
,



"
notes":""
,



"
somechildobjct
"
:
{"nm":
"
rufus
"
}

}



JS for reading JSON in Titanium




onload

: function(e)
{



Ti.API.info
("Received text: " +
this.responseText
);


var

json

= null;


try
{



json

=
JSON.parse
(
this.responseText
);



alert
('success'+
json
);


}
catch (err) {



alert
('unable to parse
json
:'+
this.responseText
);


}


},




Parsing JSON on the server is a little
more of a hassle


Import the JSON Simple library


1. Download
JAR from
http://code.google.com/p/json
-
simple
/


2.
Drag+drop

JAR into war/WEB
-
INF/lib/


3. Right
-
click project > Build Path > Add libraries >
User Library > User Libraries > New > Add JARs


Instantiate structured object with the library,
serialize it to client (see example on next slide)

Generating JSON object from server

<%@ page import="
org.json.simple.JSONObject
" %
>

… // load some data from the data store

JSONObject

json

= new
JSONObject
();

json.put
(”id"
,
data.someValue
(
));

json.put
("title",
data.someOtherValue
(
));

json.put
("emails",
data.someEmailProperty
(
));

json.put
("notes",
whatever(
));





JSONObject

someSubObject

=
new
JSONObject
();


someSubObject.put
("blahblah",111222)
;

json.put
("
psomeobj
"
,
someSubObject

)
;






out.write
(
json.toString
());


Other features of the JSON simple
library


Generating JSON arrays

{"
myarr
":[1,2,4,6,8]}


(
Can be a property, or a top
-
level object)



Parsing string back to JSON object


Including partial parse: you can start a parse and
then pause or cancel parsing depending on what
you find in the JSON stream

Some cautions and caveats: Reliability


Mobile network connections are unreliable


You need exception handlers


You can proactively retrieve data and cache it so
it’s available later, even if no network is present


You can buffer data that is destined for the server,
and flush it later on


Some cautions and caveats: Usability


Mobile network connections are slow


If you do network operations synchronously, you
will lock up the user interface


Do everything you can to perform network
operations asynchronously (as I have shown you)


Try to minimize the number of times the user has
to wait for network operations to complete


E.g., do operations in background while user can
continue working in the user interface


Another example: have the user log in just once, and
with the option to stay logged in for a week

Some cautions and caveats:
Performance


Mobile network connections are slow (
contd
)


Try to avoid repeatedly downloading the same
data or code


E.g., display the user interface and only transmit data;
don’t repeatedly download the UI (as in a web page)


Avoid transmitting data unnecessarily


E.g., define your JSP to accept a “verbose” parameter
that tells how much of a dataset should be sent


Minimize network
roundtrips

Some cautions and caveats: Security


Mobile network connections are insecure


Consider using https: all data are encrypted


Although this does require more CPU and does impose
more network overhead


Consider selectively encrypting some parameters


Ditto, but not quite as bad; could be a good
compromise between https and no encryption at all


Be sure to encrypt any usernames or passwords
that you store on the user’s device!


I’ll return to these caveats with more
concrete advice


In the mean time…


Get the “install and configure” part of your mobile
How
-
To finished this week


Take a look at the pure
-
JS libraries available for
retrieving data in a web application (i.e., outside
of a mobile app)


A.k.a. “AJAX” (Asynchronous
Javascript

And XML),
though the data do not need to be in XML format.


http://www.w3schools.com/
ajax
/
ajax_intro.asp