6

嗨,我是 Android 新手,正在使用 Web API。我目前正在编写一个应用程序,它可以扫描一本书的条形码,然后在 Google 图书中搜索它。

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

我还下载了压缩的 Book API Jar 库,我需要使用它吗?我问这个是因为从这个网站上关于 Google Places API 的一个问题中,答案之一说你所需要的就是使用 Google API 作为构建目标,它不需要任何 Jar 文件,但这是否适用于 Books API出色地?

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

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

4

2 回答 2

7

我自己刚刚完成了这个。这就是我使用 anHttpURLConnection和 an实现它的方式AsyncTask(我只是调用“ 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;
    }
}

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

于 2013-05-09T22:19:28.257 回答
2

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

但更好的是,您可以使用FeignRetrofit来抽象出 HTTP 级别的实现细节,并在自动生成的实现之上提供流畅的类型安全 API。Retrofit 是Android 中使用最多的网络库,但 Feign 在更广泛的 Java 生态系统中使用得更多。

这是一个使用 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");
            }
        }
    }
}
于 2017-07-09T19:40:04.033 回答