a little experience on mobile ajax api

本文介绍了一个包含流式Atom API、JSON解析API、表达式语言API和异步I/O API的移动Ajax API。核心部分为异步I/O API,提供异步HTTP Get和Post功能、HTTP基本认证、多部分MIME数据发送及进度监听等功能。
mobile ajax api ¶

Table of Contents

1. Introduction
2. How to invoke request
1. 1) asynchronism mode
2. 2) synchronism mode
3. How to arouse event
4. How to invoke response
1. 1) asynchronism mode
2. 2) synchronism mode
5. Summarize the issues
1. How to do http authentication
2. How to send request with post method
1. 1) Send simple message
2. 2) Upload file data(use multipartBoundary)
1. (1) General
2. (2) Special for Flickr API
3.
3. If we can set http header attribute when send request
4. How to get header attribute from response
5. How to download file/image
1. 1) Send parameters to obtain file list
2. 2) Parse the response from server
3. 3) Obtain each file's property
4. 4) Send url to download file
6. The usages, relathionships of main classes and interfaces in asyncrhonous …
1. 1) Aid class usages
2. 2) Interface usages
3. 3) Main class usages
7. The usages of all PUBLIC API/interface and related arguments in …
1. 1) Result class, ResultException? class
2. 2) Other classes
8. Progress listeners
9. See Also

Introduction ¶

Mobile Ajax API are made of 4 parts:a streaming Atom API, A JASON parser API, An Expression Language API and Asynchronous I/O API, the core are A JASON parser API, An Expression Language API and Asynchronous I/O API.The very important core is asynchronous I/O.And Expression Languange is used for invoke JASON parser to parse the data from server and obtain the result;Asynchronous I/O is very important,it offers these functions:

* Asynchronous versions of HTTP Get and Post
* HTTP Basic Authentication
* Multipart MIME (sender only)
* Progress listeners

How to invoke request ¶

It's very simple for user to invoke Mobile Ajax API, just like below
1) asynchronism mode ¶

private void doGetFriends(){
...
Request.get(
final String url, //http address
final Arg[] inputArgs, //parameters behind url
final Arg[] httpArgs, //HTTP headers
final RequestListener listener, //event listener, monitor progress listener and response listener
final Object context); //the UI display
}

or

private void doPostFriends(){
...
Request.post(
final String url, //http address,for example "http://twitter.com/statuses/friends.json"
final Arg[] inputArgs, //parameters behind url
final Arg[] httpArgs, //HTTP headers
final RequestListener listener, //event listener, monitor progress listener and response listener
final PostData multiPart, //HTTP POST method post data
final Object context); //the UI display
}

2) synchronism mode ¶

private void doGetFriends(){
...
Response response = Response.get(
final String url, //http address
final Arg[] inputArgs, //parameters behind url
final Arg[] httpArgs, //HTTP headers
final RequestListener listener); //event listener, monitor progress listener and response listener
...
}

or

private void doPostFriends(){
...
Response response = Response.post(
final String url, //http address
final Arg[] inputArgs, //parameters behind url
final Arg[] httpArgs, //HTTP headers
final RequestListener listener, //event listener, monitor progress listener and response listener
final PostData multiPart) //HTTP POST method post data
...
}

How to arouse event ¶

Arouse event by implements CommandAction? interface, when click button, commandAction'll invoke accordingly method, for example

public void commandAction(Command c, Displayable d){
...
if(c == getFriendsCommand){
doGetFriends();
}
}

How to invoke response ¶
1) asynchronism mode ¶

Need implements the method of RequestListener?,below is one of method we implement.

public void done(final Object context, final Response response) throws Exception {
...
handleGetFriendsResponse(response); //parse data from server
}

2) synchronism mode ¶

private void doGetFriends(){
...
Response response = Response.get(
final String url, //http address
final Arg[] inputArgs, //parameters behind url
final Arg[] httpArgs, //HTTP headers
final RequestListener listener); //event listener, monitor progress listener and response listener
handleGetFriendsResponse(response); //parse data from server
}

Summarize the issues ¶
How to do http authentication ¶

private Arg[] getHttpArgs(String tag){
String credentials = "Basic " + BasicAuth.encode(user, password);
Arg authArg = new Arg(Arg.AUTHORIZATION, credentials);
Arg[] argTag = {authArg};
return tag==null?argTag:null;
}
Request.get(url, null, getHttpArgs(null), this, context);

How to send request with post method ¶
1) Send simple message ¶

Arg[] args = {new Arg("source", "twister")};
Request.post(url, args, getHttpArgs(null), this, null, context);

2) Upload file data(use multipartBoundary) ¶
(1) General ¶

byte[] photoBits = ... //obtain the file data
final Arg apiKeyArg = new Arg("api_key", API_KEY);
final Arg photoArg = new Arg("photo", "img" + Long.toString(System.currentTimeMillis(), 16) + ".jpg");
final Arg[] apiKeyArgs = {new Arg(Arg.CONTENT_DISPOSITION, "form-data; name=" + apiKeyArg.getKey())};
final Arg[] photoArgs = {
new Arg(Arg.CONTENT_TYPE, "image/jpeg"),
new Arg(Arg.CONTENT_DISPOSITION, "form-data; name=" + photoArg.getKey() + "; filename=" + photoArg.getValue())
};
final String multipartBoundary = Long.toString(System.currentTimeMillis(), 16) + "--" + getClass().getName();
final Arg[] httpArgs = {
new Arg("MIME-Version", "1.0"),
new Arg("Content-Type", "multipart/form-data; boundary=" + multipartBoundary)
};
final Part[] postData = {
new Part(apiKeyArg.getValue().getBytes(), apiKeyArgs),
new Part(photoBits, photoArgs)};
final PostData mp = new PostData(postData, multipartBoundary);
Request.post(url, null, httpArgs, this, mp, context);

(2) Special for Flickr API ¶

Add a new Arg to httpArgs, that is apiSigArg, it role is security.At client side, the sign() method dealed with it's value; at server side also do the same thing like sign() method, and then compare them, if different, server'll refuse request; if the same, accept request.

byte[] photoBits = ... //obtain the file data
final Arg apiKeyArg = new Arg("api_key", API_KEY);
final Arg photoArg = new Arg("photo", "img" + Long.toString(System.currentTimeMillis(), 16) + ".jpg");
final Arg apiSigArg = new Arg("api_sig", null);
final Arg[] postArgs = { apiKeyArg, photoArg, apiSigArg};
final Arg[] apiKeyArgs = {new Arg(Arg.CONTENT_DISPOSITION, "form-data; name=" + apiKeyArg.getKey())};
final Arg[] photoArgs = {
new Arg(Arg.CONTENT_TYPE, "image/jpeg"),
new Arg(Arg.CONTENT_DISPOSITION, "form-data; name=" + photoArg.getKey() + "; filename=" + photoArg.getValue())
};
final String multipartBoundary = Long.toString(System.currentTimeMillis(), 16) + "--" + getClass().getName();
final Arg[] httpArgs = {
new Arg("MIME-Version", "1.0"),
new Arg("Content-Type", "multipart/form-data; boundary=" + multipartBoundary)
};
Arg signedArg = sign(postArgs); //obtain apiSigArg
final Arg[] apiSigArgs = {new Arg(Arg.CONTENT_DISPOSITION, "form-data; name=" + signedArg.getKey())};
final Part[] postData = {
new Part(apiKeyArg.getValue().getBytes(), apiKeyArgs),
new Part(photoBits, photoArgs)},
new Part(signedArg.getValue().getBytes(), apiSigArgs)};
final PostData mp = new PostData(postData, multipartBoundary);
Request.post(url, null, httpArgs, this, mp, context);

Sign() method used for combine all the httpArgs's keys and values,except apiSigArg and postData, then MD5 encryption

private static Arg sign(final Arg[] args) throws Exception {
if (args == null) {
throw new IllegalArgumentException("args cannot be null");
}
if (args.length == 0) {
throw new IllegalArgumentException("args must not be empty");
}
final StringBuffer concat = new StringBuffer();
// first append the shared secret
concat.append(SHARED_SECRET);
// now append the args, which are assumed to be sorted by key
for (int i=0; i < args.length; i++) {
if (args[i] != null) {
// do not include the signature or the photo arg in the signature computation
final String key = args[i].getKey();
if ("api_sig".equals(key) || "photo".equals(key)) {
continue;
}
if (key != null) {
concat.append(key);
}
final String value = args[i].getValue();
if (value != null) {
concat.append(value);
}
}
}
final byte[] input = concat.toString().getBytes();
// an md5 hash is 128 bits = 16 bytes
final byte[] hash = new byte[16];
final java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
md.update(input, 0, input.length);
md.digest(hash, 0, hash.length);
final StringBuffer sig = new StringBuffer(hash.length);
for (int i=0; i < hash.length; i++) {
sig.append(Integer.toHexString((hash[i] & 0xf0) >>> 4));
sig.append(Integer.toHexString((hash[i] & 0x0f)));
}
// the sig arg, whose value should be null (a placeholder), is replaced with the sig
int sigIndex = -1;
for (int i=0; i < args.length; i++) {
if ("api_sig".equals(args[i].getKey())) {
if (args[i].getValue() != null) {
throw new IllegalArgumentException("the api_sig arg must be null to replace with the actual signature");
}
sigIndex = i;
}
}
if (sigIndex < 0) {
throw new IllegalArgumentException("the api_sig arg must be present");
}
return args[sigIndex] = new Arg("api_sig", sig.toString());
}

If we can set http header attribute when send request ¶

final Arg[] httpArgs = {
new Arg("MIME-Version", "1.0"),
new Arg("Content-Type", "multipart/form-data; boundary=" + multipartBoundary)
};
Request.post(url, null, httpArgs, this, mp, context);

How to get header attribute from response ¶

Arg[] headers = response.getHeaders();

How to download file/image ¶
1) Send parameters to obtain file list ¶

Arg[] args = {
new Arg("api_key", API_KEY),
new Arg("format", "json"),
...
};
Request.get(url, args, null, this, context);

2) Parse the response from server ¶

Result result = response.getResult();
Photo[] photos = new Photo[result.getSizeOfArray("photos.photo")]; //inner class, saved data
for (int i=0; i < photos.length; i++) {
Photo foto = new Photo();
String root = "photos.photo[" + i + "].";
foto.id = result.getAsString(root + "id");
foto.owner = result.getAsString(root + "owner");
...
photos[i] = foto;
}

3) Obtain each file's property ¶

for (int i=0; i < photos.length; i++) {
final Photo foto = photos[i];
final Image thumb = getImage(foto, "t");
}
Image getImage(Foto foto,String size){
String imageLoc = "http://farm" + foto.farm + ".static.flickr.com/" +...;
return loadImage(imageLoc);
}

4) Send url to download file ¶

private Image loadImage(String location){
HttpConnection conn = null;
InputStream is = null;
conn = (HttpConnection) Connector.open(location);
conn.setRequestProperty("accept", "image/*");
final int responseCode = conn.getResponseCode();
if (responseCode != HttpConnection.HTTP_OK) {
// TODO: handle redirects
return null;
}
int totalToReceive = conn.getHeaderFieldInt(Arg.CONTENT_LENGTH, 0);
is = new ProgressInputStream(conn.openInputStream(), totalToReceive, this, null, 1024);
ByteArrayOutputStream bos = new ByteArrayOutputStream(Math.max(totalToReceive, 8192));
byte[] buffer = new byte[4096];
for (int nread = is.read(buffer); nread >= 0; nread = is.read(buffer)) {
bos.write(buffer, 0, nread);
}
return Image.createImage(new ByteArrayInputStream(bos.toByteArray()));
}

The usages, relathionships of main classes and interfaces in asyncrhonous I/O ¶
1) Aid class usages ¶

BasicAuth? class see How to do http authentication

Arg, Part, PostData? class see How to send request with post method

ProgressInputStream? class see Send url to download file

Response class see Parse the response from server

2) Interface usages ¶

RequestListener? interface extends ProgressListener? interface and user implements RequestListener?

include readProgress() method, writeProgress() method, done() method, for example

public void done(final Object context, final Response response) throws Exception {
...
if(context==home){ //the UI displayed
handleGetFriendsResponse(response); //parse data from server
}
}

3) Main class usages ¶

Request class see

*How to do http authentication
*How to send request with post method
*If we can set http header attribute when send request
*How to get header attribute from response

The usages of all PUBLIC API/interface and related arguments in asynchronous I/O ¶
1) Result class, ResultException? class ¶

Result result = response.getResult();
try {
Photo[] photos = new Photo[result.getSizeOfArray("photos.photo")]; //inner class, save data
int maxPage = Integer.valueOf(result.getAsString("photos.pages")).intValue();
for (int i=0; i < photos.length; i++) {
Photo foto = new Photo();
String root = "photos.photo[" + i + "].";
foto.id = result.getAsString(root + "id");
foto.owner = result.getAsString(root + "owner");
...
photos[i] = foto;
}
for (int i=0; i < photos.length; i++) {
Photo foto = photos[i];
status.setText("Loading " + foto.id);
...
}
} catch (ResultException jex) {
return;
}

2) Other classes ¶

*The usages, relathionships of main classes and interfaces in asyncrhonous I/O
Progress listeners ¶

Implements ProgressListener? and handle logic at implemented methods

public void readProgress(final Object context, final int bytes, final int total) {
status.setText(total > 0 ? (((bytes * 100) / total) + "%") : Integer.toString(bytes)); //a StringItem display percentage
}
public void writeProgress(final Object context, final int bytes, final int total) {
status("Uploading... " + (total > 0 ? (((bytes * 100) / total) + "%") : Integer.toString(bytes))); //a StringItem display percentage
}

See Also ¶

NONE
虽然提供的引用内容中未提及Arduino LittleFS的API具体介绍,但可依据LittleFS的特性与使用场景推测其常见API功能。 LittleFS是为微控制器设计的轻量级、可靠且高性能的文件系统,通过简单的API调用可进行文件的创建、打开、读取、写入和删除等操作 [^2]。以下是可能存在的API类别及功能推测: ### 文件操作API - `File open(const char* path, const char* mode)`:用于打开指定路径的文件,`mode`参数可指定打开模式,如只读、只写、追加等。 - `bool create(const char* path)`:创建指定路径的文件。 - `bool remove(const char* path)`:删除指定路径的文件。 ### 目录操作API - `bool mkdir(const char* path)`:创建指定路径的目录。 - `bool rmdir(const char* path)`:删除指定路径的目录。 ### 文件读写API - `size_t read(void* buf, size_t size)`:从当前文件指针位置读取指定大小的数据到缓冲区。 - `size_t write(const void* buf, size_t size)`:将缓冲区中的数据写入到当前文件指针位置。 ### 文件指针操作API - `void seek(size_t pos)`:将文件指针移动到指定位置。 - `size_t tell()`:返回当前文件指针的位置。 ### 文件系统操作API - `bool begin()`:初始化LittleFS文件系统。 - `bool format()`:格式化LittleFS文件系统。 以下是一个简单的使用示例: ```cpp #include <LittleFS.h> void setup() { // 初始化LittleFS if (!LittleFS.begin()) { Serial.println("LittleFS mount failed"); return; } // 创建文件并写入数据 File file = LittleFS.open("/test.txt", "w"); if (file) { file.println("Hello, LittleFS!"); file.close(); Serial.println("File written successfully"); } else { Serial.println("Error opening file for writing"); } // 读取文件数据 file = LittleFS.open("/test.txt", "r"); if (file) { while (file.available()) { Serial.write(file.read()); } file.close(); } else { Serial.println("Error opening file for reading"); } } void loop() { // 主循环可以为空 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值