大家好,我是Android新手,也是使用web API的新手。我目前正在编写一个应用程序,可以扫描一本书中的条形码,然后在Google Books中搜索它。
到目前为止,我在我的应用程序中实现了Scandit,并从Google API控制台为Books API注册并获得了API密钥。从那时起,我不知道如何继续并开始编码。从我的理解来看,它需要我通过uri请求数据,但我被困在如何实际编码的问题上。我想知道是否有人可以给我指出正确的方向,或者提供一个示例代码来说明如何使用URI获取数据。
我还下载了zipped Book API Jar libraries,我需要使用这个吗?我之所以这样问,是因为这个网站上Google Places API上的一个问题,其中一个答案说,你所需要的就是使用Google API作为构建目标,它不需要任何Jar文件,但这也适用于Books API吗?
另外,我正在使用Eclipse,我应该将构建目标设置为Google APIs 16吗?我猜这是正确的,因为我计划在未来使用谷歌地图与这个应用程序。
谢谢,这是我第一次在这里提问。
发布于 2013-05-10 06:19:28
我刚做完这件事。这就是我如何使用HttpURLConnection和AsyncTask实现它的(我只是调用“https://www.googleapis.com/books/v1/volumes?q=isbn:”+您的JSON并解析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;
}
}我省略了对话框方法的代码,因为它们不相关。希望这能有所帮助。
发布于 2017-07-10 03:40:04
要在HTTP级别直接访问Google Books API或任何其他REST,如果您愿意编写异步代码,则可以使用Volley;对于更简单的同步请求,可以使用OkHttp。还有Android Asynchronous Http Client。
但更好的是,您可以使用Feign或Retrofit抽象出HTTP级别的实现细节,并在自动生成的实现之上提供流畅的类型安全API。Retrofit是the most used network library in Android,但在更广泛的Java生态系统中更多地使用Feign。
这是一个使用Feign for Google Books API的例子,Retrofit非常相似。
接口,实现由Feign自动生成:
public interface GoogleBooksApi {
@RequestLine("GET /books/v1/volumes")
Results findBookByISBN(@QueryMap Map<String, Object> queryParameters);
}应用编程接口客户端代码
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()中的UI。
下面是一个例子:
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");
}
}
}
}https://stackoverflow.com/questions/14571478
复制相似问题