读书人

运用Zxing及豆瓣API

发布时间: 2012-12-18 12:43:41 作者: rapoo

使用Zxing及豆瓣API
本文原创,转载请注明原文地址:http://maosidiaoxian.iteye.com/blog/1743296或我在sinaapp上的博客:http://msdxblog.sinaapp.com/?p=716。

最近在做团队图书管理的一个Android端。因为需要通过手机扫描来输入图书信息(人工一条一条地输入,作为技术人员太受不了了),需要使用ZXing的API扫描图书ISBN,及使用豆瓣API来获取图书信息。

由于时间关系,这里没有使用ZXing的jar包,而是下载并安装了它的开源项目——条码扫描器,然后调用里面的Activity扫描再获取结果。
首先到市场下载Barcode Scaner(或搜索条码扫描器),下载安装。
下面先贴上Activity的布局代码,因为是demo版,而且在内部使用,就没去好好做布局设计,只是把需要的控件都写上。

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <Button        android:id="@+id/home_scan"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="@string/button_scan" />    <TextView        android:id="@+id/home_result_scan"        android:layout_width="wrap_content"        android:layout_height="wrap_content" />    <TextView        android:id="@+id/home_book_info"        android:layout_width="wrap_content"        android:layout_height="wrap_content" />    <Button        android:id="@+id/home_upload_result"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="@string/button_upload" />    <TextView        android:id="@+id/home_result_upload"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:singleLine="false" />    <LinearLayout        android:layout_width="fill_parent"        android:layout_height="wrap_content" >        <Button            android:id="@+id/home_borrow_book"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="@string/borrow_book" />        <Spinner            android:id="@+id/home_users"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="right" />    </LinearLayout>    <Button        android:id="@+id/home_return_book"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="@string/return_book" />    <Button        android:id="@+id/home_user_manager"        android:layout_width="wrap_content"        android:text="@string/manager_user"        android:layout_height="wrap_content" /></LinearLayout>


然后在我们的项目中,写一个Activity来调用Zxing的扫描功能,并通过它返回的结果访问互联网获取信息。

下面是该Activity的代码。这里对于控件及事件的绑定,我使用了自己封装的一个工具(Androidkit)来简化这些代码,所以你们会看到许多类似@AndroidView的注解,这个工具可以在http://code.google.com/p/cfuture-androidkit/获取,或从https://github.com/msdx/androidkit上获得最新代码。
/* * @(#)HomeActivity.java       Project:bookscan * Date:2012-12-3 * * Copyright (c) 2011 CFuture09, Institute of Software,  * Guangdong Ocean University, Zhanjiang, GuangDong, China. * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); *  you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.sinaapp.msdxblog.bookscan.activity;import org.apache.http.HttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.DefaultHttpClient;import android.app.Activity;import android.content.Intent;import android.database.Cursor;import android.os.Bundle;import android.os.Handler;import android.view.View;import android.widget.SimpleCursorAdapter;import android.widget.Spinner;import android.widget.TextView;import com.sinaapp.msdxblog.androidkit.thread.HandlerFactory;import com.sinaapp.msdxblog.androidkit.ui.ResBindUtil;import com.sinaapp.msdxblog.androidkit.ui.UIBindUtil;import com.sinaapp.msdxblog.androidkit.ui.annotation.AndroidRes;import com.sinaapp.msdxblog.androidkit.ui.annotation.AndroidRes.ResType;import com.sinaapp.msdxblog.androidkit.ui.annotation.AndroidView;import com.sinaapp.msdxblog.androidkit.ui.annotation.OnClick;import com.sinaapp.msdxblog.bookscan.R;import com.sinaapp.msdxblog.bookscan.bean.Book;import com.sinaapp.msdxblog.bookscan.util.DB;import com.sinaapp.msdxblog.bookscan.util.XMLSax;/** * @author Geek_Soledad (66704238@51uc.com) */public class HomeActivity extends Activity {private static final int HOME_ACTIVITY = 1990;private static final String DOUBAN_API = "http://api.douban.com/book/subject/isbn/";@AndroidView(id = R.id.home_result_scan)private TextView mTextScan;@AndroidView(id = R.id.home_book_info)private TextView mTextBook;@AndroidView(id = R.id.home_result_upload)private TextView mTextUpload;@AndroidView(id = R.id.home_users)private Spinner mSpinnerUser;@AndroidRes(id = R.string.result_scan, type = ResType.STRING)private String mStringScan;@AndroidRes(id = R.string.result_getting, type = ResType.STRING)private String mStringGetting;@AndroidRes(id = R.string.book_info, type = ResType.STRING)private String mStringBookInfo;private Handler mGettingBook;private Book book;private DB mDb;private SimpleCursorAdapter mAdapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);UIBindUtil.bind(this, R.layout.activity_home);ResBindUtil.bindAllRes(this);init();}/** * 初始化参数。 */private final void init() {mGettingBook = HandlerFactory.getNewHandlerInOtherThread("book");mDb = new DB(this);Cursor users = mDb.getAllUser();startManagingCursor(users);mAdapter = new SimpleCursorAdapter(this,android.R.layout.simple_spinner_item, users,new String[] { "username" }, new int[] { android.R.id.text1 });mAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);mSpinnerUser.setAdapter(mAdapter);}@OnClick(viewId = { R.id.home_scan, R.id.home_upload_result,R.id.home_borrow_book, R.id.home_return_book,R.id.home_user_manager })public void onButtonClick(View v) {switch (v.getId()) {case R.id.home_scan:Intent intent = new Intent("com.google.zxing.client.android.SCAN");this.startActivityForResult(intent, HOME_ACTIVITY);break;case R.id.home_upload_result:break;case R.id.home_borrow_book:break;case R.id.home_return_book:break;case R.id.home_user_manager:startActivity(new Intent(this, UserManagerActivity.class));break;default:break;}}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode != HOME_ACTIVITY) {super.onActivityResult(requestCode, resultCode, data);return;}if (data == null) {return;}final String isbn = data.getStringExtra("SCAN_RESULT");mTextScan.setText(String.format(mStringScan, isbn));if (isbn != null) {mTextBook.setText(mStringGetting);mGettingBook.post(new Runnable() {@Overridepublic void run() {DefaultHttpClient client = new DefaultHttpClient();HttpGet request = new HttpGet(DOUBAN_API + isbn);try {HttpResponse response = client.execute(request);book = XMLSax.sax(response.getEntity().getContent());String summary = book.getSummary();summary = summary.substring(0,summary.length() < 60 ? summary.length() : 60).concat("...");String string = String.format(mStringBookInfo,book.getName(), book.getAuthor(),book.getPublisher(), book.getIsbn13(), summary);updateBookInfoView(string);} catch (Exception e) {e.printStackTrace();}}});}}/** * 更新图书信息 *  * @param string */private void updateBookInfoView(final String string) {runOnUiThread(new Runnable() {@Overridepublic void run() {mTextBook.setText(string);}});}@Overrideprotected void onResume() {super.onResume();mAdapter.notifyDataSetChanged();}@Overrideprotected void onDestroy() {super.onDestroy();mDb.close();}}

里面的功能及流程大致如下:
调用Zxinig的扫描条码的Activity,然后返回该扫描结果,显示扫描结果,然后调用豆瓣的API获取图书信息。接下来是要从我们的服务器上获得该图书的信息(如是否登记,有没有人借走等),但因为服务端还没搭建好,这一部分功能就没去实现。
上面代码中,调用Zxing的过程比较简单,
Intent intent = new Intent("com.google.zxing.client.android.SCAN");this.startActivityForResult(intent, HOME_ACTIVITY);

然后再在onActivityResult方法中对返回的结果进行处理就好了。
然后从豆瓣API中获得的是xml格式的内容,这里我就使用了android自带的pull解析器。我需要获得的图书信息相对较少,Book的JavaBean如下:
/* * @(#)BookInfo.java       Project:bookscan * Date:2012-12-3 * * Copyright (c) 2011 CFuture09, Institute of Software,  * Guangdong Ocean University, Zhanjiang, GuangDong, China. * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); *  you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.sinaapp.msdxblog.bookscan.bean;/** * @author Geek_Soledad (66704238@51uc.com) */public class Book {private String isbn10;// 10位的ISBNprivate String isbn13;// 13位的ISBNprivate String name; // 书名private String author;// 作者名private String summary;// 简介private String publisher; // 出版社private String image; // 封面图片地址public String getIsbn10() {return isbn10;}public void setIsbn10(String isbn10) {this.isbn10 = isbn10;}public String getIsbn13() {return isbn13;}public void setIsbn13(String isbn13) {this.isbn13 = isbn13;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public String getSummary() {return summary;}public void setSummary(String summary) {this.summary = summary;}public String getPublisher() {return publisher;}public void setPublisher(String publisher) {this.publisher = publisher;}public String getImage() {return image;}public void setImage(String image) {this.image = image;}@Overridepublic String toString() {return "Book [isbn10=" + isbn10 + ", isbn13=" + isbn13 + ", name="+ name + ", author=" + author + ", summary=" + summary+ ", publisher=" + publisher + ", image=" + image + "]";}}


然后解析器的代码如下:
/* * @(#)XMLSax.java       Project:bookscan * Date:2012-12-3 * * Copyright (c) 2011 CFuture09, Institute of Software,  * Guangdong Ocean University, Zhanjiang, GuangDong, China. * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); *  you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.sinaapp.msdxblog.bookscan.util;import java.io.IOException;import java.io.InputStream;import org.xmlpull.v1.XmlPullParser;import org.xmlpull.v1.XmlPullParserException;import com.sinaapp.msdxblog.bookscan.bean.Book;import android.util.Log;import android.util.Xml;/** * @author Geek_Soledad (66704238@51uc.com) */public class XMLSax {public static Book sax(InputStream is) {Book book = null;XmlPullParser parser = Xml.newPullParser();try {parser.setInput(is, "UTF-8");int eventType = parser.getEventType();while (eventType != XmlPullParser.END_DOCUMENT) {switch (eventType) {case XmlPullParser.START_TAG:Log.d("test", parser.getName());if (parser.getName().equals("entry")) {book = new Book();} else if (parser.getName().equals("link")) {if (parser.getAttributeValue(null, "rel").equals("image")) {book.setImage(parser.getAttributeValue(null, "href"));}eventType = parser.next();}else if (parser.getName().equals("attribute")) {String attribute = parser.getAttributeValue(0);eventType = parser.next();if (attribute.equals("title")) {book.setName(parser.getText());} else if (attribute.equals("author")) {book.setAuthor(parser.getText());} else if (attribute.equals("isbn10")) {book.setIsbn10(parser.getText());} else if (attribute.equals("isbn13")) {book.setIsbn13(parser.getText());} else if ( attribute.equals("publisher")) {book.setPublisher(parser.getText());} } else if (parser.getName().equals("summary")) {eventType = parser.next();book.setSummary(parser.getText());} else if (parser.getName().equals("title")) {if (book.getName() == null) {eventType = parser.next();book.setName(parser.getText());}}break;case XmlPullParser.END_TAG:break;}eventType = parser.next();}} catch (XmlPullParserException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return book;}}

然后是引用到的String资源,如下:
<resources>    <string name="app_name">图书扫描</string>    <string name="bookmark_picker_name">Bookmarks</string>    <string name="button_scan">图书扫描</string>    <string name="button_upload">上传结果</string>    <string name="result_scan">扫描结果为:%s</string>    <string name="result_getting">正在向豆瓣请求数据</string>    <string name="book_info">图书信息:\n\t书名:%1$s\n\t作者:%2$s\n\t出版社:%3$s\n\tISBN:%4$s\n\t简介:%5$s </string>    <string name="borrow_book">借书</string>    <string name="return_book">还书</string>    <string name="manager_user">管理用户</string>    <string name="add">添加</string>    <string name="delete">删除</string></resources>

最后的结果是这样子的:

读书人网 >移动开发

热点推荐