2011年7月20日 星期三

搜尋Flickr上相關照片

本篇會針對如何使用 Flickr API 做相片搜尋的動作,以及如何在 Android 平台上取用這些資料。

簡介
簡單的來講 Flickr API 是一種 WEB API,呼叫的方式是透過 Flickr 提供的網址,並在網址後面接上所需的參數;要使用這些功能前必須先向 Flickr 申請一份 key ,除了申請的 key 之外 Flickr 還會給予一個密鑰,不過在這個搜尋的過程中我們並不會使用到這個密鑰,只會使用到 Flickr 所給予的 key。申請 key 前必須先擁有 Flickr 帳號。

API KEY 申請頁面

要使用 Flickr API 除了可以直接使用 Flickr 本身提供的方式之外,也可以利用第三方所開發的 framework 做使用,在 Flickr 頁面上有提供一些第三方工具連結,但官方是宣稱不保證使用的風險,除此之外這邊所用到的 API 並不多,所以還是直接利用 Flickr 所提供的方式。

Flickr 的要求格式分別為 REST、XML-RPC 與 SOAP 三種不同的方式,在這邊我們所使用的是 REST 方式,也就是剛剛提到的直接將所需參數接在網址後面;並且使用 REST 方式呼叫的話,預設也將以 REST 的格式回覆,但回覆的格式可以利用 format 參數做設定。

回覆的格式有五種 : REST、XML-RPC、SOAP、JSON 及 PHP。
此處使用的是 JSON 格式,一方面再使用 PHP 及 JavaScript 開發時較方便,另一方面也可以讓 PHP 程式收到的 JSON 格式資料,直接轉送至 Android 平台裝置上,而不需加做其他處理。

在這個搜尋照片並顯示在 Android 裝置上的程式規劃,將會是利用行動裝置發送需求至 AP server ,經由 AP server 向 Flickr 要求資料,並將接收到的回覆轉送回行動裝置。利用 AP server 而不直接使用行動裝置做要求的規畫,在於考慮到未來使用者大量的傳送要求時,我們可以針對 AP server 做必要的設定或更改,像是建立資料庫快取或是過濾等動作。




PHP
首先來看 PHP 方面的動作

<?php

$target_url = 'http://api.flickr.com/services/rest/?';
$data = array(
'method' => 'flickr.people.findByUsername' ,
'format' => 'json' ,
'nojsoncallback' => 1 ,
'api_key' => &#API KEY; ,
'username' => 'kuso.dir'
);
$target_url .= http_build_query( $data );
$user_id_JSONdata = startQuery($target_url);
$user_id_decode = json_decode($user_id_JSONdata,true);
$user_id = $user_id_decode[user][id];


$target_url = 'http://api.flickr.com/services/rest/?';
$data = array(
'method' => 'flickr.photos.search' ,
'format' => 'json' ,
'nojsoncallback' => 1 ,
'api_key' => 'API KEY; ,
'per_page' => 5 ,
'text' => 'nchu' ,
'user_id' => $user_id
);

$target_url .= http_build_query( $data );
$photos_data = startQuery($target_url);
print_r( $photos_data );
exit;

function startQuery($url){
$ch = curl_init();
curl_setopt( $ch , CURLOPT_URL , $url );
curl_setopt( $ch , CURLOPT_RETURNTRANSFER , true );
$d = curl_exec( $ch );
curl_close( $ch );
return $d;
}

?>
$target_url 為要求 API 的網址,$data 放的是需求的參數。

$data = array(
'method' => '要呼叫哪個 method' ,
'format' => '回覆格式設定' ,
'nojsoncallback' =&gt 設定1代表僅回覆原始JSON; ,
'api_key' => &#API KEY; ,
'username' => '使用者名稱'
);

我們呼叫的是 flickr.people.findByUsername 這支 method ,主要功能為搜尋符合的使用者名稱並回傳其 id 值,回覆的格式設定為 JSON 格式,並僅回覆最原始 JSON 資料。

startQuery() 是一個自訂函式,負責的功能為接收一個需要 query 的網址,並透過 curl 取得並回傳網頁資料;因為傳回的資料為 JSON 格式,所以可以利用 json_decode() 將之解碼為陣列,並取得使用者 id,接著可以利用此 id 搜尋此人擁有的照片。

依照同樣的方式,這次呼叫 flickr.photos.search 用來搜尋照片,這裡利用了 per_page 參數設定每頁有幾張圖,參數 text 及 user_id 分別為要搜尋的內文及使用者,最後將 Flickr 回傳的資料印出,以便 Android 抓取。




Android端
在取得 JSON 資料後首先要做的就是把需要的資料解析出來,所以必須要清楚這個回傳的資料格式長的如何,這裡先來看一下 flickr.photos.search 回傳的資料格式。

JSON回傳格式:
{
"photos":
{
"page":1,
"pages":3,
"perpage":5,
"total":"12",
"photo":
[
{"id":"5933477491", "owner":"15942951@N05",
"secret":"6db77e1e7d", "server":"6130",
"farm":7, "title":"\u4e2d\u8208\u9d5d",
"ispublic":1, "isfriend":0, "isfamily":0},

{"id":"5934040444", "owner":"15942951@N05",
"secret":"7cfb1ed29a", "server":"6141",
"farm":7, "title":"\u4e2d\u8208\u9d5d",
"ispublic":1, "isfriend":0, "isfamily":0},
]
},
"stat":"ok"
}


解析 JSON 時應注意 :
{} 為 Object
[] 為 Array

所以我們可以從下面的程式碼中解析出需要的資料,由於索取的資訊並不是照片本身,而是存放位置的相關訊息,所以我們必須再額外的做一些處理才能取得相片,而負責這些處理的功能就是程式碼中的 makeImg() 這個自定函式。

解析JSON原始碼:
jsonObj = new JSONObject(result);
photosObj = jsonObj.getJSONObject("photos");
page = photosObj.getString("page");
pages = photosObj.getString("pages");
perpage = photosObj.getString("perpage");
total = photosObj.getString("total");
photoArray = photosObj.getJSONArray("photo");
photoNum = photoArray.length();
for(int n=0;n<photoNum;n++){
photoObj = photoArray.getJSONObject(n);
id = photoObj.getString("id");
owner = photoObj.getString("owner");
secret = photoObj.getString("secret");
server = photoObj.getString("server");
farm = photoObj.getString("farm");
title = photoObj.getString("title");
ispublic = photoObj.getString("ispublic");
isfriend = photoObj.getString("isfriend");
isfamily = photoObj.getString("isfamily");
makeImg(farm,server,id,secret);
}


對於相片及網頁的存放位置, Flickr 也設定了一些格式,如下 :
相片 URL 格式 : 取得照片的地方
http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}.jpg
or
http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}_[mstzb].jpg
or
http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{o-secret}_o.(jpg|gif|png)

後綴分類 : 所需取得的相片尺寸
s 小正方形 75x75
t 縮圖,最長邊為 100
m 小,最長邊為 240
- 中等,最長邊為 500
z 中等尺寸 640,最長邊為 640
b 大尺寸,最長邊為 1024*
o 原始圖片, 根據來源格式可以是 jpg、gif 或 png

網頁 URL : Flickr 上顯示相片的網頁,或是個人相關訊息的網頁。
http://www.flickr.com/people/{user-id}/ - profile
http://www.flickr.com/photos/{user-id}/ - photostream
http://www.flickr.com/photos/{user-id}/{photo-id} - individual photo
http://www.flickr.com/photos/{user-id}/sets/ - all photosets
http://www.flickr.com/photos/{user-id}/sets/{photoset-id} - single photoset

簡短 URL
http://flic.kr/p/{base58-photo-id}

如需詳細的說明請至 Flickr 說明頁面

由上面的格式可以知道如果要取得照片必須先得知一些資料,而這些資料也都包含在取回的 JSON 檔案中,分別是 farm-id、server-id、id 及 secret 這四個參數值,利用這四個參數並加上相片大小的綴詞即可組成相片存放的 URL;接著將 URL 的資料讀入並利用BitmapFactory.decodeStream() 這個函式將讀入的資料建構成一個 Bitmap ,一直到現在才真正取得相片主體,以下為部分原始碼。
public void makeImg(String farm,String server,String id,String secret){
String url = null;
url = "http://farm" + farm + ".static.flickr.com/" + server + "/" + id + "_" + secret + "_m.jpg";
getContentFromHttp(url);
Bitmap bm = BitmapFactory.decodeStream(is);
imgAdapter.addPhoto(bm);
}
getContentFromHttp() 為自訂函式,主要負責讀取網頁資料。
imgAdapter.addPhoto(bm) 為自訂函式,主要功能是將剛剛產生的圖片加入至 Gallery 做播放。

結尾
以上為 Android 與 Flickr 的應用簡介,Flickr API 提供了非常完整的訊息,包括了相片的授權方式或是群組類別等等,利用上面所介紹的方法可以簡單的取得需要的訊息,並加以利用。下面提供兩張由 Android 所抓下的實機操作圖,當作本文的結尾,畫面上方顯示著一列可左右拖移的圖片列表,當點擊有興趣的圖片時,將會在畫面下方顯示完整的大圖。

圖片為本人於中興大學所拍攝的鵝照片,用來測試帳號、標籤及內文搜索功能。

0 意見:

張貼留言

Twitter Delicious Facebook Digg Stumbleupon Favorites More

 
Powered by Blogger