使用Zxing及豆瓣API
Posted on 2012/12/06归档于 ANDROID最近在做团队图书管理的一个Android端。因为需要通过手机扫描来输入图书信息(人工一条一条地输入,作为技术人员太受不了了),需要使用ZXing的API扫描图书ISBN,及使用豆瓣API来获取图书信息。
由于时间关系,这里没有使用ZXing的jar包,而是下载并安装了它的开源项目——条码扫描器,然后调用里面的Activity扫描再获取结果。
首先到市场下载Barcode Scaner(或搜索条码扫描器),下载安装。
下面先贴上Activity的布局代码,因为是demo版,而且在内部使用,就没去好好做布局设计,只是把需要的控件都写上。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364<?xmlversion="1.0"encoding="utf-8"?>android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:id="@+id/home_scan"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/button_scan"/><TextViewandroid:id="@+id/home_result_scan"android:layout_width="wrap_content"android:layout_height="wrap_content"/><TextViewandroid:id="@+id/home_book_info"android:layout_width="wrap_content"android:layout_height="wrap_content"/><Buttonandroid:id="@+id/home_upload_result"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/button_upload"/><TextViewandroid:id="@+id/home_result_upload"android:layout_width="wrap_content"android:layout_height="wrap_content"android:singleLine="false"/><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"><Buttonandroid:id="@+id/home_borrow_book"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/borrow_book"/><Spinnerandroid:id="@+id/home_users"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="right"/></LinearLayout><Buttonandroid:id="@+id/home_return_book"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/return_book"/><Buttonandroid: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上获得最新代码。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189/** @(#)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*** 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.*/packagecom.sinaapp.msdxblog.bookscan.activity;importorg.apache.http.HttpResponse;importorg.apache.http.client.methods.HttpGet;importorg.apache.http.impl.client.DefaultHttpClient;importandroid.app.Activity;importandroid.content.Intent;importandroid.database.Cursor;importandroid.os.Bundle;importandroid.os.Handler;importandroid.view.View;importandroid.widget.SimpleCursorAdapter;importandroid.widget.Spinner;importandroid.widget.TextView;importcom.sinaapp.msdxblog.androidkit.thread.HandlerFactory;importcom.sinaapp.msdxblog.androidkit.ui.ResBindUtil;importcom.sinaapp.msdxblog.androidkit.ui.UIBindUtil;importcom.sinaapp.msdxblog.androidkit.ui.annotation.AndroidRes;importcom.sinaapp.msdxblog.androidkit.ui.annotation.AndroidRes.ResType;importcom.sinaapp.msdxblog.androidkit.ui.annotation.AndroidView;importcom.sinaapp.msdxblog.androidkit.ui.annotation.OnClick;importcom.sinaapp.msdxblog.bookscan.R;importcom.sinaapp.msdxblog.bookscan.bean.Book;importcom.sinaapp.msdxblog.bookscan.util.DB;importcom.sinaapp.msdxblog.bookscan.util.XMLSax;/*** @author Geek_Soledad (66704238@51uc.com)*/publicclassHomeActivityextendsActivity {privatestaticfinalintHOME_ACTIVITY =1990;@AndroidView(id = R.id.home_result_scan)privateTextView mTextScan;@AndroidView(id = R.id.home_book_info)privateTextView mTextBook;@AndroidView(id = R.id.home_result_upload)privateTextView mTextUpload;@AndroidView(id = R.id.home_users)privateSpinner mSpinnerUser;@AndroidRes(id = R.string.result_scan, type = ResType.STRING)privateString mStringScan;@AndroidRes(id = R.string.result_getting, type = ResType.STRING)privateString mStringGetting;@AndroidRes(id = R.string.book_info, type = ResType.STRING)privateString mStringBookInfo;privateHandler mGettingBook;privateBook book;privateDB mDb;privateSimpleCursorAdapter mAdapter;@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);UIBindUtil.bind(this, R.layout.activity_home);ResBindUtil.bindAllRes(this);init();}/*** 初始化参数。*/privatefinalvoidinit() {mGettingBook = HandlerFactory.getNewHandlerInOtherThread("book");mDb =newDB(this);Cursor users = mDb.getAllUser();startManagingCursor(users);mAdapter =newSimpleCursorAdapter(this,android.R.layout.simple_spinner_item, users,newString[] {"username"},newint[] { 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 })publicvoidonButtonClick(View v) {switch(v.getId()) {caseR.id.home_scan:Intent intent =newIntent("com.google.zxing.client.android.SCAN");this.startActivityForResult(intent, HOME_ACTIVITY);break;caseR.id.home_upload_result:break;caseR.id.home_borrow_book:break;caseR.id.home_return_book:break;caseR.id.home_user_manager:startActivity(newIntent(this, UserManagerActivity.class));break;default:break;}}@OverrideprotectedvoidonActivityResult(intrequestCode,intresultCode, Intent data) {if(requestCode != HOME_ACTIVITY) {super.onActivityResult(requestCode, resultCode, data);return;}if(data ==null) {return;}finalString isbn = data.getStringExtra("SCAN_RESULT");mTextScan.setText(String.format(mStringScan, isbn));if(isbn !=null) {mTextBook.setText(mStringGetting);mGettingBook.post(newRunnable() {@Overridepublicvoidrun() {DefaultHttpClient client =newDefaultHttpClient();HttpGet request =newHttpGet(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*/privatevoidupdateBookInfoView(finalString string) {runOnUiThread(newRunnable() {@Overridepublicvoidrun() {mTextBook.setText(string);}});}@OverrideprotectedvoidonResume() {super.onResume();mAdapter.notifyDataSetChanged();}@OverrideprotectedvoidonDestroy() {super.onDestroy();mDb.close();}}里面的功能及流程大致如下:
调用Zxinig的扫描条码的Activity,然后返回该扫描结果,显示扫描结果,然后调用豆瓣的API获取图书信息。接下来是要从我们的服务器上获得该图书的信息(如是否登记,有没有人借走等),但因为服务端还没搭建好,这一部分功能就没去实现。
上面代码中,调用Zxing的过程比较简单,
12Intent intent =newIntent("com.google.zxing.client.android.SCAN");this.startActivityForResult(intent, HOME_ACTIVITY);然后再在onActivityResult方法中对返回的结果进行处理就好了。
然后从豆瓣API中获得的是xml格式的内容,这里我就使用了android自带的pull解析器。我需要获得的图书信息相对较少,Book的JavaBean如下:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798/** @(#)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*** 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.*/packagecom.sinaapp.msdxblog.bookscan.bean;/*** @author Geek_Soledad (66704238@51uc.com)*/publicclassBook {privateString isbn10;// 10位的ISBNprivateString isbn13;// 13位的ISBNprivateString name;// 书名privateString author;// 作者名privateString summary;// 简介privateString publisher;// 出版社privateString image;// 封面图片地址publicString getIsbn10() {returnisbn10;}publicvoidsetIsbn10(String isbn10) {this.isbn10 = isbn10;}publicString getIsbn13() {returnisbn13;}publicvoidsetIsbn13(String isbn13) {this.isbn13 = isbn13;}publicString getName() {returnname;}publicvoidsetName(String name) {this.name = name;}publicString getAuthor() {returnauthor;}publicvoidsetAuthor(String author) {this.author = author;}publicString getSummary() {returnsummary;}publicvoidsetSummary(String summary) {this.summary = summary;}publicString getPublisher() {returnpublisher;}publicvoidsetPublisher(String publisher) {this.publisher = publisher;}publicString getImage() {returnimage;}publicvoidsetImage(String image) {this.image = image;}@OverridepublicString toString() {return"Book [isbn10="+ isbn10 +", isbn13="+ isbn13 +", name="+ name +", author="+ author +", summary="+ summary+", publisher="+ publisher +", image="+ image +"]";}}然后解析器的代码如下:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394/** @(#)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*** 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.*/packagecom.sinaapp.msdxblog.bookscan.util;importjava.io.IOException;importjava.io.InputStream;importorg.xmlpull.v1.XmlPullParser;importorg.xmlpull.v1.XmlPullParserException;importcom.sinaapp.msdxblog.bookscan.bean.Book;importandroid.util.Log;importandroid.util.Xml;/*** @author Geek_Soledad (66704238@51uc.com)*/publicclassXMLSax {publicstaticBook sax(InputStream is) {Book book =null;XmlPullParser parser = Xml.newPullParser();try{parser.setInput(is,"UTF-8");inteventType = parser.getEventType();while(eventType != XmlPullParser.END_DOCUMENT) {switch(eventType) {caseXmlPullParser.START_TAG:Log.d("test", parser.getName());if(parser.getName().equals("entry")) {book =newBook();}elseif(parser.getName().equals("link")) {if(parser.getAttributeValue(null,"rel").equals("image")) {book.setImage(parser.getAttributeValue(null,"href"));}eventType = parser.next();}elseif(parser.getName().equals("attribute")) {String attribute = parser.getAttributeValue(0);eventType = parser.next();if(attribute.equals("title")) {book.setName(parser.getText());}elseif(attribute.equals("author")) {book.setAuthor(parser.getText());}elseif(attribute.equals("isbn10")) {book.setIsbn10(parser.getText());}elseif(attribute.equals("isbn13")) {book.setIsbn13(parser.getText());}elseif( attribute.equals("publisher")) {book.setPublisher(parser.getText());}}elseif(parser.getName().equals("summary")) {eventType = parser.next();book.setSummary(parser.getText());}elseif(parser.getName().equals("title")) {if(book.getName() ==null) {eventType = parser.next();book.setName(parser.getText());}}break;caseXmlPullParser.END_TAG:break;}eventType = parser.next();}}catch(XmlPullParserException e) {e.printStackTrace();}catch(IOException e) {e.printStackTrace();}returnbook;}}然后是引用到的String资源,如下:
123456789101112131415<resources><stringname="app_name">图书扫描</string><stringname="bookmark_picker_name">Bookmarks</string><stringname="button_scan">图书扫描</string><stringname="button_upload">上传结果</string><stringname="result_scan">扫描结果为:%s</string><stringname="result_getting">正在向豆瓣请求数据</string><stringname="book_info">图书信息:\n\t书名:%1$s\n\t作者:%2$s\n\t出版社:%3$s\n\tISBN:%4$s\n\t简介:%5$s </string><stringname="borrow_book">借书</string><stringname="return_book">还书</string><stringname="manager_user">管理用户</string><stringname="add">添加</string><stringname="delete">删除</string></resources>
