在Android中使用Google Books API

时间:2013-01-28 21:22:31

标签: android google-api google-books

您好我是Android新手并使用网络API。我目前正在编写一个应用程序,可以扫描书籍中的条形码,然后搜索Google Books。

到目前为止,我已将Scandit应用到我的应用程序中,并在Google API控制台中为Books API注册并获取了API密钥。从那里我不知道如何继续并开始编码。到目前为止,根据我的理解,它需要我通过uri发出请求数据,但我仍然坚持如何实际编码它。我想知道是否有人能指出我正确的方向或提供一个示例代码,说明如何使用URI获取数据。

我还下载了zipped Book API Jar libraries我需要使用它吗?我问这个问题是因为根据Google网站上的Google Places API问题,其中一个答案说您只需要使用Google API作为构建目标,它不需要任何Jar文件,但这适用于Books API好?

我也在使用Eclipse,我应该将构建目标设置为Google API 16吗?我猜这是对的,因为我计划将来使用谷歌地图这个应用程序。

谢谢这是我第一次在这里问一个问题。

2 个答案:

答案 0 :(得分:5)

我刚刚完成了这个。这就是我使用HttpURLConnectionAsyncTask实现它的方式(我只是调用“https://www.googleapis.com/books/v1/volumes?q=isbn:”+ yourISBN并解析JSON):

// Received ISBN from Barcode Scanner. Send to GoogleBooks to obtain book information.
class GoogleApiRequest extends AsyncTask<String, Object, JSONObject>{

    @Override
    protected void onPreExecute() {
        // Check network connection.
        if(isNetworkConnected() == false){
            // Cancel request.
            Log.i(getClass().getName(), "Not connected to the internet");
            cancel(true);
            return;
        }
    }
    @Override
    protected JSONObject doInBackground(String... isbns) {
        // Stop if cancelled
        if(isCancelled()){
            return null;
        }

        String apiUrlString = "https://www.googleapis.com/books/v1/volumes?q=isbn:" + isbns[0];
        try{
            HttpURLConnection connection = null;
            // Build Connection.
            try{
                URL url = new URL(apiUrlString);
                connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.setReadTimeout(5000); // 5 seconds
                connection.setConnectTimeout(5000); // 5 seconds
            } catch (MalformedURLException e) {
                // Impossible: The only two URLs used in the app are taken from string resources.
                e.printStackTrace();
            } catch (ProtocolException e) {
                // Impossible: "GET" is a perfectly valid request method.
                e.printStackTrace();
            }
            int responseCode = connection.getResponseCode();
            if(responseCode != 200){
                Log.w(getClass().getName(), "GoogleBooksAPI request failed. Response Code: " + responseCode);
                connection.disconnect();
                return null;
            }

            // Read data from response.
            StringBuilder builder = new StringBuilder();
            BufferedReader responseReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line = responseReader.readLine();
            while (line != null){
                builder.append(line);
                line = responseReader.readLine();
            }
            String responseString = builder.toString();
            Log.d(getClass().getName(), "Response String: " + responseString);
            JSONObject responseJson = new JSONObject(responseString);
            // Close connection and return response code.
            connection.disconnect();
            return responseJson;
        } catch (SocketTimeoutException e) {
            Log.w(getClass().getName(), "Connection timed out. Returning null");
            return null;
        } catch(IOException e){
            Log.d(getClass().getName(), "IOException when connecting to Google Books API.");
            e.printStackTrace();
            return null;
        } catch (JSONException e) {
            Log.d(getClass().getName(), "JSONException when connecting to Google Books API.");
            e.printStackTrace();
            return null;
        }
    }
    @Override
    protected void onPostExecute(JSONObject responseJson) {
        if(isCancelled()){
            // Request was cancelled due to no network connection.
            showNetworkDialog();
        } else if(responseJson == null){
            showSimpleDialog(getResources().getString(R.string.dialog_null_response));
        }
        else{
            // All went well. Do something with your new JSONObject.
        }
    }
}

protected boolean isNetworkConnected(){

    // Instantiate mConnectivityManager if necessary
    if(mConnectivityManager == null){
        mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    }
    // Is device connected to the Internet?
    NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
    if(networkInfo != null && networkInfo.isConnected()){
        return true;
    } else {
        return false;
    }
}

我省略了对话框方法的代码,因为它们不相关。希望这会有所帮助。

答案 1 :(得分:0)

要直接在HTTP级别访问Google Books API或任何其他REST API,如果您愿意为简单的同步请求编写异步代码或Volley,则可以使用OkHttp。还有Android Asynchronous Http Client

但更好的是,您可以使用FeignRetrofit抽象出HTTP级实现细节,并在自动生成的实现之上提供流畅的类型安全API。改造是the most used network library in Android,但是在更广泛的Java生态系统中更多地使用了Feign。

以下是使用Feign for Google Books API的示例,Retrofit非常相似。

API接口,实施由Feign自动生成:

public interface GoogleBooksApi {

    @RequestLine("GET /books/v1/volumes")
    Results findBookByISBN(@QueryMap Map<String, Object> queryParameters);

}

API客户端代码

public class BookLookupService {

    public Book fetchBookByISBN(String isbn) throws BookLookupException {
        final GoogleBooksApi googleBooksApi = connect();
        final Map<String, Object> queryParameters = new HashMap<>();
        queryParameters.put("q", "isbn:" + isbn);
        final Results apiResponse = googleBooksApi.findBookByISBN(queryParameters);
        if (apiResponse == null || apiResponse.getTotalItems() < 1) {
            throw new BookLookupException("No books found for ISBN " + isbn);
        }
        final List<Result> results = apiResponse.getItems();
        if (results == null || results.size() < 1) {
            throw new BookLookupException("Invalid items list for ISBN " + isbn);
        }
        final Book book = results.get(0).getBook();
        return book;
    }

    private static GoogleBooksApi connect() {
        return Feign.builder()
            .decoder(new GsonDecoder())
            .logger(new Logger.ErrorLogger())
            .logLevel(Logger.Level.BASIC)
            .target(GoogleBooksApi.class, "https://www.googleapis.com");
    }
}
为API响应结构建模的

实体

public class Results {
    int totalItems;
    List<Result> items;

    public int getTotalItems() {
        return totalItems;
    }

    public List<Result> getItems() {
        return items;
    }
}

public class Result {
    // the JSON field is named volumeInfo
    Book volumeInfo;

    public Book getBook() {
        return volumeInfo;
    }
}

public class Book {
    private String title;
    private List<String> authors;

    public String getTitle() {
        return title;
    }

    public List<String> getAuthors() {
        return authors;
    }
}

最后,测试

@RunWith(AndroidJUnit4.class)
public class BookLookupServiceAndroidTest {
    private BookLookupService bookLookupService = new BookLookupService();

    @Test
    public void whenMultipleLookupResultsThenReturnsFirst() throws Exception {
        assertThat(bookLookupService.fetchBookByISBN("9780321356680").getTitle(),
                   is(equalTo("Effective Java, 2nd Edition")));
    }
}

请注意,您需要将代码包装在AsyncTask中以使其异步,因为主线程上不允许网络请求。 AsyncTask应更新onPostExecute()中的用户界面。

以下是一个例子:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        final Button fetchBookButton = (Button) findViewById(R.id.FetchBookButton);
        fetchBookButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) { new FetchBookTask().execute(getISBN()); }
        });
    }

    private String getISBN() {
        final EditText isbnField = (EditText) findViewById(R.id.BookIsbnField);
        return isbnField.getText().toString();
    }

    private void showMessage(String message) {
        Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
    }

    class FetchBookTask extends AsyncTask<String, Void, Book> {

        @Override
        protected Book doInBackground(String... params) {
            final String isbn = params[0];
            try {
                return new BookLookupService().fetchBookByISBN(isbn);
            } catch (Exception e) {
                Log.e("fetchBookByISBN", e.toString());
                return null;
            }
        }

        @Override
        protected void onPostExecute(Book book) {
            if (book != null) {
                showMessage("Got book: " + book.getTitle());
            } else {
                showMessage("Failed to fetch book");
            }
        }
    }
}