可以对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。