最近在做团队图书管理的一个Android端。因为需要通过手机扫描来输入图书信息(人工一条一条地输入,作为技术人员太受不了了),需要使用ZXing的API扫描图书ISBN,及使用豆瓣API来获取图书信息。
由于时间关系,这里没有使用ZXing的jar包,而是下载并安装了它的开源项目——条码扫描器,然后调用里面的Activity扫描再获取结果。
首先到市场下载Barcode Scaner(或搜索条码扫描器),下载安装。
下面先贴上Activity的布局代码,因为是demo版,而且在内部使用,就没去好好做布局设计,只是把需要的控件都写上。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
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上获得最新代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
|
/*
* @(#)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.
*/
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 ([email protected])
*/
public
class
HomeActivity
extends
Activity {
private
static
final
int
HOME_ACTIVITY =
1990
;
@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;
@Override
protected
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
;
}
}
@Override
protected
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() {
@Override
public
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() {
@Override
public
void
run() {
mTextBook.setText(string);
}
});
}
@Override
protected
void
onResume() {
super
.onResume();
mAdapter.notifyDataSetChanged();
}
@Override
protected
void
onDestroy() {
super
.onDestroy();
mDb.close();
}
}
|
里面的功能及流程大致如下:
调用Zxinig的扫描条码的Activity,然后返回该扫描结果,显示扫描结果,然后调用豆瓣的API获取图书信息。接下来是要从我们的服务器上获得该图书的信息(如是否登记,有没有人借走等),但因为服务端还没搭建好,这一部分功能就没去实现。
上面代码中,调用Zxing的过程比较简单,
1
2
|
Intent intent =
new
Intent(
"com.google.zxing.client.android.SCAN"
);
this
.startActivityForResult(intent, HOME_ACTIVITY);
|
然后再在onActivityResult方法中对返回的结果进行处理就好了。
然后从豆瓣API中获得的是xml格式的内容,这里我就使用了android自带的pull解析器。我需要获得的图书信息相对较少,Book的JavaBean如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
/*
* @(#)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.
*/
package
com.sinaapp.msdxblog.bookscan.bean;
/**
* @author Geek_Soledad ([email protected])
*/
public
class
Book {
private
String isbn10;
// 10位的ISBN
private
String isbn13;
// 13位的ISBN
private
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;
}
@Override
public
String toString() {
return
"Book [isbn10="
+ isbn10 +
", isbn13="
+ isbn13 +
", name="
+ name +
", author="
+ author +
", summary="
+ summary
+
", publisher="
+ publisher +
", image="
+ image +
"]"
;
}
}
|
然后解析器的代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
/*
* @(#)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.
*/
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 ([email protected])
*/
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资源,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<
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
>
|