Android Full App,第2部分:使用HTTP API

这是“ Android完整应用程序教程”系列的第二部分。 完整的应用程序旨在提供一种通过互联网搜索表演电影/演员的简便方法。 在本系列的第一部分( “主要活动UI” )中,我们创建了Eclipse项目并为应用程序的主要活动设置了基本界面。 在这一部分中,我们将了解如何使用外部HTTP API,以及如何将API的搜索功能集成到我们的应用程序中。

对于电影和演员查询,我们将使用TMDb API 。 从官方网站:
“对于想将电影和演员数据以及海报或电影爱好者集成在一起的任何开发人员,TMDb API都是强大的资源。 所有API方法都支持XML,YAML和JSON。”

与大多数可用的API一样,您将需要一个有效的密钥才能使用该API。 第一步是在TMDb的“注册”页面上创建一个免费帐户。 注册后,登录您的帐户并找到用于生成API密钥的链接。

可用的API方法的列表可以在TMDb API文档页面上找到,最重要的方法如下:

  • Movie.search :提供搜索电影的最简单,最快的方法。
  • Person.search :用于搜索演员,女演员或制作成员。

对于电影搜索,URL示例如下:

http://api.themoviedb.org/2.1/Movie.search/zh/xml/APIKEY/Transformers

对于人物搜索,示例网址如下:

http://api.themoviedb.org/2.1/Person.search/en/xml/APIKEY/Brad+Pitt

(其中APIKEY必须替换为有效的API密钥)

如您所见,该API非常简单易用。 它仅涉及在特定URL上执行HTTP GET请求,然后将响应检索为预定义的格式。

接下来,我们将看到如何利用Android的网络功能来使用API​​并提供所提供数据的表示形式。 请注意,我们将使用XML格式进行响应,但这将在下一个教程中进行展示。

为了在Android环境中处理HTTP请求/响应,可以使用java.net包中的标准类。 因此,诸如URLURLConnectionHttpURLConnection等之类的所有类都可以以已知方式使用。 但是,您可以通过使用Apache HTTP Client库来避免处理底层细节。 该库基于著名的Apache Commons HTTP Client框架。

让我们开始使用代码。 我们将创建一个名为“ HttpRetriever”的类,该类将负责执行所有HTTP请求,并将以文本格式和流(用于图像处理)的形式返回响应。 此类的代码如下:

package com.javacodegeeks.android.apps.moviesearchapp.services;

import java.io.IOException;
import java.io.InputStream;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

import com.javacodegeeks.android.apps.moviesearchapp.io.FlushedInputStream;
import com.javacodegeeks.android.apps.moviesearchapp.util.Utils;

public class HttpRetriever {
   
   private DefaultHttpClient client = new DefaultHttpClient();   
   
   public String retrieve(String url) {
      
        HttpGet getRequest = new HttpGet(url);
        
      try {
         
         HttpResponse getResponse = client.execute(getRequest);
         final int statusCode = getResponse.getStatusLine().getStatusCode();
         
         if (statusCode != HttpStatus.SC_OK) { 
            Log.w(getClass().getSimpleName(), "Error " + statusCode + " for URL " + url); 
            return null;
         }
         
         HttpEntity getResponseEntity = getResponse.getEntity();
         
         if (getResponseEntity != null) {
            return EntityUtils.toString(getResponseEntity);
         }
         
      } 
      catch (IOException e) {
         getRequest.abort();
         Log.w(getClass().getSimpleName(), "Error for URL " + url, e);
      }
      
      return null;
      
   }
   
   public InputStream retrieveStream(String url) {
      
      HttpGet getRequest = new HttpGet(url);
        
      try {
         
         HttpResponse getResponse = client.execute(getRequest);
         final int statusCode = getResponse.getStatusLine().getStatusCode();
         
         if (statusCode != HttpStatus.SC_OK) { 
            Log.w(getClass().getSimpleName(), "Error " + statusCode + " for URL " + url); 
            return null;
         }

         HttpEntity getResponseEntity = getResponse.getEntity();
         return getResponseEntity.getContent();
         
      } 
      catch (IOException e) {
         getRequest.abort();
         Log.w(getClass().getSimpleName(), "Error for URL " + url, e);
      }
      
      return null;
      
   }
   
   public Bitmap retrieveBitmap(String url) throws Exception {
      
      InputStream inputStream = null;
      try {
         inputStream = this.retrieveStream(url);
         final Bitmap bitmap = BitmapFactory.decodeStream(new FlushedInputStream(inputStream));
         return bitmap;
      } 
      finally {
         Utils.closeStreamQuietly(inputStream);
      }
      
   }

}

对于HTTP请求的实际执行,我们使用DefaultHttpClient类的实例,顾名思义,该实例是HTTP客户端的默认实现,即HttpClient接口的默认实现。 我们还使用HttpGet类(以表示GET请求),并为其构造函数参数提供目标URL。 HTTP客户端执行请求,并提供HttpResponse对象,该对象包含实际的服务器响应以及任何其他信息。 例如,我们可以检索响应状态代码,并将其与成功HTTP请求的代码( HttpStatus.SC_OK )进行比较。 对于成功的请求,我们将引用随附的HttpEntity对象,并从中访问实际的响应数据。 对于文本响应,我们使用EntityUtils类的静态toString方法将实体转换为String。 如果我们希望以字节流的形式检索数据(例如,为了处理二进制下载),请使用HttpEntity类的getContent方法,该方法将创建实体的新InputStream对象。

请注意,还有第三种方法可以直接返回Bitmap对象。 这将对教程系列的后续部分有所帮助,我们将从互联网上下载图像。 在该方法中,我们像往常一样执行GET请求并检索InputStream 。 然后,我们使用BitmapFactory类的encodeStream方法创建一个新的Bitmap对象。 请注意,我们不直接提供下载的InputStream ,而是首先用FlushedInputStream类包装它。 如官方Android开发人员博客文章所述,先前版本的encodeStream方法中存在一个错误,当通过缓慢的连接下载图像时,可能会导致问题。 自定义类FlushedInputStream扩展了FilterInputStream ,以解决此问题。 该类的代码如下:

package com.javacodegeeks.android.apps.moviesearchapp.io;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

public class FlushedInputStream extends FilterInputStream {
 
    public FlushedInputStream(InputStream inputStream) {
        super(inputStream);
    }

    @Override
    public long skip(long n) throws IOException {
        long totalBytesSkipped = 0L;
        while (totalBytesSkipped < n) {
            long bytesSkipped = in.skip(n - totalBytesSkipped);
            if (bytesSkipped == 0L) {
                  int b = read();
                  if (b < 0) {
                      break;  // we reached EOF
                  } else {
                      bytesSkipped = 1; // we read one byte
                  }
           }
            totalBytesSkipped += bytesSkipped;
        }
        return totalBytesSkipped;
    }
    
}

这样可以确保skip()实际上跳过提供的字节数,除非我们到达文件末尾。 最后,我们使用自定义Utils类的closeStreamQuietly方法来处理关闭InputStream时可能发生的异常。 代码如下:

package com.javacodegeeks.android.apps.moviesearchapp.util;

import java.io.IOException;
import java.io.InputStream;

public class Utils {
 
 public static void closeStreamQuietly(InputStream inputStream) {
   try {
   if (inputStream != null) {
        inputStream.close();  
    }
  } catch (IOException e) {
   // ignore exception
  }
 }

}

最后,为了能够执行HTTP请求,必须授予相应的权限。 因此,将android.permission.INTERNET添加到项目的AndroidManifest.xml文件中,该文件现在如下所示:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.javacodegeeks.android.apps.moviesearchapp"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".MovieSearchAppActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
    <uses-sdk android:minSdkVersion="3" />
 <uses-permission android:name="android.permission.INTERNET"></uses-permission>
</manifest>

因此,我们准备了用于执行HTTP GET请求的基础结构。 在以下教程中,我们将使用它来检索满足应用程序需求的XML数据和图像。 您可以在此处下载到目前为止创建的Eclipse项目。

相关文章 :

翻译自: https://www.javacodegeeks.com/2010/10/android-full-app-part-2-using-http-api.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值