http://892848153.iteye.com/blog/1412180
掃描和識別條形碼的android支持庫
android支持掃描條形碼。不過手裏沒有真機,無法理解該功能是一個應用,還是一個可API調用的功能。不過在網上找到一個免費開源的android處理條形碼的庫。見: http://code.google.com/p/zxing 可以作爲應用安裝到android上,見: http://code.google.com/p/zxing/wiki/GettingStarted 或者,在另外的程序中使用該功能: http://code.google.com/p/zxing/wiki/ScanningViaIntent
已經有java的第三方開源條形碼識別庫(zxing)了,在自己的應用中掃描條形碼實際上只需調用該第三方庫的實現即可。寫掃描和識別條形碼的android支持庫的時候還沒有g1手機,現在可以試試了。 爲了能調用zxing,需要先安裝google market中的barcode scanner:
爲了能調用zxing,需要先安裝google market中的barcode scanner: 程序很簡陋,第一個界面: 第二個界面,跳到了zxing庫提供的Activity去做條形碼掃描,這裏掃描的是生成QR二維條碼中的本站url。
qr碼瞬間就可以識別到,然後從zxing的Activity返回到程序中,顯示條目內容: 編寫代碼很簡單。 java代碼: package com.easymorse;
import android.app.Activity; public class ShowBarcodeActivity extends Activity implements OnClickListener { private Button button; private TextView textView;
/** Called when the activity is first created. */
this.button = (Button) this.findViewById(R.id.Button01);
this.textView = (TextView) this.findViewById(R.id.hello);
@Override
@Override
this.textView.setText(data.getStringExtra(“SCAN_RESULT”)); layout目錄下面的main.xml:
<?xml version=”1.0″ encoding=”utf-8″?>
<Button android:text=”@string/Button01″ android:id=”@+id/Button01″ android:layout_width=”wrap_content” android:layout_height=”wrap_content”></Button> values目錄下的strings.xml
<?xml version=”1.0″ encoding=”utf-8″?> 從這個示例中也可以看到android強大的地方,可以複用(reuse)其他應用的服務(Service)或者Activity。
剛纔寫的編寫最簡單的android掃描條形碼功能,只能掃描qr二維碼。如果要掃描普通的商品條形碼,需要在該程序上座一點兒修改。 界面的改動: 掃描條形碼時的效果:
顯示掃描結果(識別速度明顯低於二維碼): 代碼的改動: package com.easymorse;
import android.app.Activity; public class ShowBarcodeActivity extends Activity { private Button button; private Button button2; private TextView textView;
/** Called when the activity is first created. */
this.button = (Button) this.findViewById(R.id.Button01);
@Override
this.button2 = (Button) this.findViewById(R.id.Button02);
@Override
this.textView = (TextView) this.findViewById(R.id.hello);
@Override
this.textView.setText(data.getStringExtra(“SCAN_RESULT”)); 寫完這個示例,才發現其實現在不需要寫: intent.putExtra(“SCAN_MODE”, “QR_CODE_MODE”); zxing現在的庫可以自動的識別是哪種編碼。如果寫了,反而是指定類型,不能識別其他類型的編碼。實際上,上面的: intent.putExtra(“SCAN_MODE”, “EAN_13″); 寫的不對。具體常量參數,見: http://zxing.org/w/docs/javadoc/constant-values.html 上面的內容不修改了,正確的源代碼共享在google code的svn中,見: http://easymorse.googlecode.com/svn/tags/barcode.proto.0.1.0/
寫了個技術原型,通過手機識別圖書的ISBN條形碼,然後通過豆瓣網的API,輸出ISBN號對應的圖書信息。 示例很簡單,上來是個按鈕,點擊後,進入zxing的activity,用於掃描圖書ISBN號。 使用zxing的掃描功能,這次還出現了點兒問題。我的nexus one攝像頭比較髒了,造成對焦後無法識別,或者識別的很慢。嚇了我一跳,因爲以前沒有問題的。
更換了幾個版本zxing,問題依舊,擦拭了鏡頭,問題立刻得到了解決。 nexus one的像素和自動對焦能力,也可能包括cpu的處理因素,稍稍對中條碼,立刻得到結果。之前的G1就要慢一些。 這也帶來了捕獲上面截圖的困難,因爲一瞬間掃描就結束了。怎麼辦呢?我用手在鏡頭上揉搓了幾下,就可以了,哈哈。 提示找到圖書後,通過豆瓣API,獲取到圖書的XML,這裏要說,豆瓣的圖書信息還是比較全的,我用國外圖書也找到了信息。 因爲使用聯通WCDMA卡,整個過程很快。 下面說說代碼中的一些要點。 如何掃描條形碼現在做條形碼掃描,java一般用zxing。zxing有多種複用方式,最簡單的方式是,安裝zxing軟件,通過google market。在自己的應用中,通過Intent調用zxing的掃描條碼的Activity,然後將掃描到的結果返回自己的Activity。 比較複雜的辦法是,將zxing庫包含在自己的程序中,這比較適合正式的應用。 本文使用的是前者。 示例代碼示例源代碼見: http://easymorse.googlecode.com/svn/tags/sou.book-0.2 還有一個更爲簡單的示例,可用於理解調用zxing和豆瓣API的基本過程,見: http://easymorse.googlecode.com/svn/tags/sou.book-0.1 實現activity跳轉在0.2版本中,涉及到3個activity,首先是搜索圖書的activity,見最上面的圖。點擊按鈕後,進入zxing的activity,從視覺上看,zxing獲取到ISBN號後,進入了第三個activity,顯示圖書的詳細信息。 其實,從zxing得到ISBN號以後,還是返回到搜索圖書的activity,但是該activity馬上發起新的intent,進入新的activity。另外,這裏也演示瞭如果通過intent共享activity之間的參數。 以下代碼創建新的activity,並設置參數:
Intent intent = new Intent(); 以下是從intent中獲取到參數: this.getIntent().getExtras().getString("ISBN");有關zxing的使用,可以參考我另外一個示例,android掃描商品條形碼。webview使用本地頁面的考慮在顯示圖書查詢結果的activity中,使用webview,這樣顯示可以做的比較靈活和簡單。 顯示頁面有多種做法,比如可以是遠程服務器上的頁面,這要求有服務器端的支持。看起來這樣比較省心,尤其是比如有iphone,有android等等異構終端的情況下。手機開發人員可以將這部分都空出來,交給服務器端去解決。而且是統一的解決方案。 但是,實踐中,有兩個問題: 服務器端開發人員要爲不同手機客戶端實現不同的樣式,而且服務器端開發者往往並不配備手機設備,這也確實是難以做到的,難道要爲一個做適配的服務器端開發人員配備iphone、android和s60手機麼?手機終端開發者無法靈活的控制webview中的細節,webview(這裏指android環境,iphone環境類似的)支持通過javascript訪問手機的服務或者對象,但這是平臺相關的,android有自己的代碼,iphone也有自己的代碼,很難在服務器端統一解決。我在這個原型中試圖解決,即,HTML頁面在手機端本地,手機端和服務器交互,只是取得數據,而不包含顯示樣式(也就是HTML頁面的內容),手機端通過javascript,將取得的數據注入到本地頁面中顯示。 這種方式的好處是: 手機端和服務器端交互是獲取數據,這是各種手機系統都通用的;這種方式類似與AJAX,對數據流量的要求也會下降;手機端開發人員可以靈活的決定頁面的樣式和交互動作。在本例中,將html和css放置在項目的assets目錄下,另外,該目錄下,還有一張圖片,用於未加載到圖書圖片時佔位。想像一下,如果不使用webview,這個需求需要編程處理,是比較繁瑣的,可參見android異步加載ListView中的圖片中的處理。 實現webview的代碼很簡單,這是一個更簡單的示例,見android編寫簡單的Webview。本例相關代碼:
this.resultWeb = (WebView) this.findViewById(R.id.resultWeb); this.resultWeb.getSettings().setJavaScriptCanOpenWindowsAutomatically( true); this.resultWeb.getSettings().setJavaScriptEnabled(true); this.resultWeb.loadUrl(file:///android_asset/results.html);
這裏要注意,setJavaScriptEnabled啓用javascript,否則javascript無效。 android java與html頁面中javascript互操作javascript和java之間的通信問題,本例只通過javascript調用java,還是比較簡單的。如果是java調用javascript,應該需要啓動單獨的線程來實現。 需要爲webview對象創建一個javascript調用的接口對象:
this.resultWeb.addJavascriptInterface(new Object() { return bookInfo.getName(); }
public String getBookSummary() { }
public String getBookImageUrl() { }
public String getBookAuthor() { } }, "searchResult");
其中第一個參數是javascript調用的對象,第二個參數,是調用對象的名稱。 看看javascript中怎樣調用這個對象: document.getElementById("bookName").innerHTML=window.searchResult.getBookName();可以看到window對象多了個searchResult對象屬性,這個searchResult就是上面方法中第二個參數。通過該名字,就調用到了上面第一個參數創建的內部類對象。 使用豆瓣API豆瓣API官方網址: http://www.douban.com/service/apidoc/ 這裏僅用到根據ISBN得到圖書信息xml的功能。在這裏: http://www.douban.com/service/apidoc/reference/subject#獲取書籍信息 如果匿名使用這個API,有一定的限制: API調用被限制爲每分鐘請求不超過10次。 這裏的調用次數是每ip地址的。對於手機應用來說,大於6秒鐘掃描一次圖書,應該是夠用了。 解析豆瓣XML查詢結果對豆瓣的xml查詢結果,使用了android自帶的xmlpull api進行解析。 這裏和android通過xmlpull解析xml稍有差別在於,後者是獲取xml的屬性值,這裏是獲取節點中的文本內容。 需要:
if (i == XmlPullParser.START_TAG && parser.getAttributeValue(0).equals("title")) { bookInfo.setName(parser.nextText()); Log.v("soubook", "title>>" + bookInfo.getName()); continue; }
通過parser.nextText()方法獲取。另外,要注意在獲取完畢後,continue結束本次循環。 HTML與CSS本例中顯示查詢結果的webview使用了比較難看的灰色背景,主要是爲了演示外部css可以很好的和html結合使用。 同理,也應該可以在html頁面中引用外部的javascript,打算在下一個版本中加入jquery。 |