12.3.3 使用JSON和位置提取Flickr图像

    可以对Flickr JSON示例进行更新以结合位置信息,方法是请求LocationManager的位置变化的通知时执行请求。当然,必须将位置添加到请求中,其中Flickr支持将它作为请求中查询字符串的一部分。

 1 package com.nthm.androidtestActivity;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.InputStream;
 6 import java.io.InputStreamReader;
 7 import java.net.HttpURLConnection;
 8 import java.net.MalformedURLException;
 9 import java.net.URL;
10 import org.apache.http.HttpEntity;
11 import org.apache.http.HttpResponse;
12 import org.apache.http.client.HttpClient;
13 import org.apache.http.client.methods.HttpGet;
14 import org.apache.http.impl.client.DefaultHttpClient;
15 import org.json.JSONArray;
16 import org.json.JSONObject;
17 import com.nthm.androidtest.R;
18 import android.app.Activity;
19 import android.content.Context;
20 import android.graphics.Bitmap;
21 import android.graphics.BitmapFactory;
22 import android.location.Location;
23 import android.location.LocationListener;
24 import android.location.LocationManager;
25 import android.os.Bundle;
26 import android.view.LayoutInflater;
27 import android.view.View;
28 import android.view.ViewGroup;
29 import android.widget.BaseAdapter;
30 import android.widget.ImageView;
31 import android.widget.ListView;
32 import android.widget.TextView;

    在FilchrJSONLocation活动中实现LocationListener,从而可以在位置更改时获得通知。

 1 public class FilchrJSONLocation extends Activity implements LocationListener{
 2     public static final String API_KEY="YOU_API_AKY";
 3     private  FilckrPhoto[] photos;
 4     private TextView tv;
 5     private LocationManager lm;
 6     @Override
 7     protected void onCreate(Bundle savedInstanceState) {
 8         super.onCreate(savedInstanceState);
 9         setContentView(R.layout.filchrjsonlocation);
10         tv=(TextView) findViewById(R.id.TextView);
11         tv.setText("Looking Up Location");

     与直接请求Flickr不同,首先将指定想要的位置,方法是创建一个LocationManager实例并调用requestLocationUpdates方法,将活动注册为LocationListener。其中,指定至多每60秒以及至少移动500米之后更新。

 

1         lm=(LocationManager) getSystemService(LocationManager.NETWORK_PROVIDER);
2         lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 60000, 500.0f, this);
3     }
4     
5     @Override
6     protected void onPause() {
7         super.onPause();
8         lm.removeUpdates(this);
9     }

 

    现在,当调用onLocationChanged方法时会向Flickr发出请求,同时考虑以Location对象形式传入的位置。

1     @Override
2     public void onLocationChanged(Location location) {
3         tv.setText(location.getLatitude()+" "+location.getLongitude());
4         HttpClient httpcilent=new DefaultHttpClient();

    需要构造URL来处理几个额外的参数:表示纬度的lat、表示经度的lon以及精确率(accuracy),精确率数字代表了返回结果中纬度和经度的范围。根据Flickr API文档,值1表示整个世界,6表示一个“区域”,11大约是一座城市,而16大约是一条街道。另外需要指定两个标记,“Halloween(万圣节)”和“dog(狗)”,根据Flickr API文档以逗号分隔他们。

 1         HttpGet httpget=new HttpGet("http://api.filckr.com/services/rest/?method=flickr.photos.search&tags=waterfront&format=json&api_key="+API_KEY+"&per_page=5" +
 2                 "&nojsoncallback=1&accuracy=6&lat="+location.getLatitude()+"&lon="+location.getLongitude());
 3         HttpResponse response;
 4         try{
 5             response=httpcilent.execute(httpget);
 6             HttpEntity entity=response.getEntity();
 7             if(entity!=null){
 8                 InputStream inputstream=entity.getContent();
 9                 BufferedReader bufferedreader=new BufferedReader(new InputStreamReader(inputstream));
10                 StringBuilder stringbuilder=new StringBuilder();
11                 String currentline=null;
12                 try{
13                     while((currentline=bufferedreader.readLine())!=null){
14                         stringbuilder.append(currentline+"\n");
15                     }
16                 }catch(IOException e){
17                     e.printStackTrace();
18                 }
19                 String result=stringbuilder.toString();
20                 JSONObject thedata=new JSONObject(result);
21                 JSONObject thephotosdata=thedata.getJSONObject("photos");
22                 JSONArray thephotodata=thephotosdata.getJSONArray("photo");
23                 photos=new FilckrPhoto[thephotodata.length()];
24                 for(int i=0;i<thephotodata.length();i++){
25                     JSONObject photodata=thephotodata.getJSONObject(i);
26                     photos[i]=new FilckrPhoto(photodata.getString("id"),
27                             photodata.getString("owner"), 
28                             photodata.getString("secret"), 
29                             photodata.getString("server"), 
30                             photodata.getString("title"),
31                             photodata.getString("farm"));
32                 }
33                 inputstream.close();
34             }
35         }catch(Exception e){
36             e.printStackTrace();
37         }
38         ListView listView=(ListView) this.findViewById(R.id.ListView);
39         listView.setAdapter(new FlickrGalleryAdapter(this, photos));
40     }

    当然,由于实现了LocationListener,因此需要提供onProviderEnabled和onProviderDisabled方法。此处方法是空方法。在你的应用程序中,你可能希望通知用户这些事件的发生,以解释为什么位置更新已停止或开始工作。

 1     @Override
 2     public void onStatusChanged(String provider, int status, Bundle extras) {
 3         
 4     }
 5     @Override
 6     public void onProviderEnabled(String provider) {
 7         
 8     }
 9     @Override
10     public void onProviderDisabled(String provider) {
11         
12     }

    这个示例的其余代码与之前给出的一样。需要一个FlickrGalleryAdapter类,使用来自Flickr的结果处理ListView的所有元素。

 1     class FlickrGalleryAdapter extends BaseAdapter{
 2         private Context context;
 3         private FilckrPhoto [] photos;
 4         private LayoutInflater inflater;
 5         public FlickrGalleryAdapter(Context _context,FilckrPhoto [] _items){
 6             context=_context;
 7             photos=_items;
 8             inflater=(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 9         }
10         @Override
11         public int getCount() {
12             return photos.length;
13         }
14 
15         @Override
16         public Object getItem(int position) {
17             return photos[position];
18         }
19 
20         @Override
21         public long getItemId(int position) {
22             return position;
23         }
24 
25         @Override
26         public View getView(int position, View convertView, ViewGroup parent) {
27             View photoRow=inflater.inflate(R.layout.filchrjsonlocation_list_item, null);
28             ImageView image=(ImageView) photoRow.findViewById(R.id.ImageView);
29             image.setImageBitmap(imageFromUrl(photos[position].makeURL()));
30             TextView imageTitle=(TextView) photoRow.findViewById(R.id.TextView);
31             imageTitle.setText(photos[position].title);
32             return photoRow;
33         }
34         public Bitmap imageFromUrl(String url){
35             Bitmap bitmapImage;
36             URL imageUrl=null;
37             try {
38                 imageUrl=new URL(url);
39             } catch (MalformedURLException e) {
40                 e.printStackTrace();
41             }
42             try {
43                 HttpURLConnection httpConnection=(HttpURLConnection) imageUrl.openConnection();
44                 httpConnection.setDoInput(true);
45                 httpConnection.connect();
46                 InputStream is=httpConnection.getInputStream();
47                 bitmapImage=BitmapFactory.decodeStream(is);
48             } catch (IOException e) {
49                 e.printStackTrace();
50                 bitmapImage=Bitmap.createBitmap(10,10,Bitmap.Config.ARGB_8888);
51             }
52             
53             return bitmapImage;
54         }
55     }

    最后,与之前示例中一样,有一个FilckrPhoto类,用来保存通过JSON从Flickr发送的每张照片的数据。

 1     class FilckrPhoto{
 2         private String id;
 3         private String owner;
 4         private String secret;
 5         private String server;
 6         private String title;
 7         private String farm;
 8         
 9         public FilckrPhoto(String _id,String _owner,String _secret,String _server,String _title,String _farm){
10             id=_id;
11             owner=_owner;
12             secret=_secret;
13             server=_server;
14             title=_title;
15             farm=_farm;
16         }
17         public String makeURL(){
18             return "http://farm"+farm+".static.flickr.com/"+server+"/"+id+"_"+secret+"_m.jpg";
19         }
20     }
21 }

    下面是示例中使用的filchrjsonlocation.xml布局。

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:layout_height="match_parent"
 4     android:orientation="vertical"
 5     >
 6     <TextView 
 7         android:layout_width="wrap_content"
 8         android:layout_height="wrap_content"
 9         android:id="@+id/TextView"/>
10  <ListView 
11      android:layout_width="wrap_content"
12      android:layout_height="wrap_content"
13      android:id="@+id/ListView"
14   />
15 </LinearLayout>

    下面是示例中使用的ListView布局的filchrjsonlocation_list_item.xml文件。

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:layout_height="match_parent"
 4     android:orientation="horizontal"
 5     >
 6     <ImageView 
 7         android:id="@+id/ImageView"
 8         android:layout_width="wrap_content"
 9         android:layout_height="wrap_content"
10         />
11  <TextView 
12      android:id="@+id/TextView"
13      android:text="TextView"
14      android:layout_width="fill_parent"
15      android:layout_height="wrap_content"
16      android:textSize="35dip"></TextView>
17 </LinearLayout>

    当然还需要指定此示例具有访问Internet和使用位置的权限。

    正如我们所见,只须在应用程序中考虑位置,就可以创建及其动态的体验。在当前的情况下,随着用户的移动,将会为他或她展示一套全新的由Flickr提供的“dog,halloween”照片。

    现在让我们将注意力转回到Web服务协议并开始讨论REST。

 

posted on 2014-09-11 11:59  宁静致远,一览众山小  阅读(265)  评论(0编辑  收藏  举报

导航