www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 嵌入式 > 嵌入式軟件
[導(dǎo)讀] 注:本文來(lái)自友盟-安卓巴士教程大賽第一名獲獎(jiǎng)作品,作者安卓巴士的ID為liupeinye。推薦給所有剛剛開(kāi)始接觸Android開(kāi)發(fā)的朋友們!本文面向Android初級(jí)開(kāi)發(fā)者,有一定的Java

 注:本文來(lái)自友盟-安卓巴士教程大賽第一名獲獎(jiǎng)作品,作者安卓巴士的ID為liupeinye。推薦給所有剛剛開(kāi)始接觸Android開(kāi)發(fā)的朋友們!

本文面向Android初級(jí)開(kāi)發(fā)者,有一定的Java和Android知識(shí)即可。

文章覆蓋知識(shí)點(diǎn):HttpWatch抓包,HttpClient模擬POST請(qǐng)求,Jsoup解析HTML代碼,動(dòng)態(tài)更新ListView

背景介紹:客戶端(Client)或稱為用戶端,是指與服務(wù)器相對(duì)應(yīng),為客戶提供本地服務(wù)的程序。而android系統(tǒng)上的90%客戶端軟件都有一個(gè)共性,就是為了改善網(wǎng)頁(yè)在android系統(tǒng)上體驗(yàn)不佳而生,最具有影響力的軟件有:新浪微博、人人網(wǎng)、淘寶等,這類(lèi)軟件最突出的特點(diǎn)就是,先有網(wǎng)站再有軟件。由于網(wǎng)絡(luò)技術(shù)發(fā)展的多樣性,手機(jī)瀏覽器往往無(wú)法跟隨它的步伐,為改善用戶體驗(yàn),網(wǎng)站客戶端軟件印運(yùn)而生。

以下內(nèi)容100%原創(chuàng),并在安卓巴士論壇首發(fā),如需轉(zhuǎn)載,請(qǐng)注明作者和出處。謝謝合作。

開(kāi)發(fā)Android網(wǎng)站客戶端通常有兩種方法:第一種,通過(guò)服務(wù)端的開(kāi)放平臺(tái),調(diào)用提供的API接口來(lái)開(kāi)發(fā),比如說(shuō)open sina;第二種,服務(wù)端沒(méi)有提供任何接口,你也沒(méi)有服務(wù)端任何數(shù)據(jù)庫(kù)訪問(wèn)權(quán)限,就是一個(gè)純純粹粹的網(wǎng)站,要你做客戶端。今天,我要和大家分享的正是第二種情況。

這是一個(gè)簡(jiǎn)單的示意圖,告訴我們,數(shù)據(jù)是由網(wǎng)頁(yè)從數(shù)據(jù)庫(kù)中取出,我們要為這個(gè)系統(tǒng)做客戶端,我們就應(yīng)該這樣去改造它。

通過(guò)這樣間接的方法來(lái)訪問(wèn)數(shù)據(jù)庫(kù),只要網(wǎng)頁(yè)能看到的內(nèi)容,我們的客戶端都能獲取到,而UI是由你自行制作,就可以使使用體驗(yàn)上一個(gè)臺(tái)階。

既然網(wǎng)頁(yè)是我們的數(shù)據(jù)樞紐,我們就從網(wǎng)頁(yè)分析著手。

該教程來(lái)自本人項(xiàng)目-掌上民大-真實(shí)經(jīng)驗(yàn),所以用項(xiàng)目中的”掌上圖書(shū)館”板塊來(lái)示范。

該項(xiàng)目任務(wù)為中南民族大學(xué)圖書(shū)館圖書(shū)查詢功能制作客戶端。

首先打開(kāi)該網(wǎng)址http://www.lib.scuec.edu.cn/,我們會(huì)看到主界面

正中間就是查詢?nèi)肟?,我們輸?rdquo;android”進(jìn)行查詢

得到結(jié)果的網(wǎng)頁(yè),但我們能發(fā)現(xiàn),這個(gè)頁(yè)面是ILAS圖書(shū)管理系統(tǒng),所以真正的入口并不是上面紅圈的地方。

所以我繼續(xù)找,經(jīng)過(guò)短暫的觀察,發(fā)現(xiàn)入口在這里

我們點(diǎn)擊進(jìn)入

果然就是這貨,我們點(diǎn)擊書(shū)目查詢

就是它了。真正的入口就在這里,這時(shí)我們打開(kāi)HttpWatch軟件,點(diǎn)”Record”,在搜索框里輸入”android”,點(diǎn)擊查詢,抓取以”android”為關(guān)鍵字搜索時(shí)瀏覽器的所有包。待結(jié)果界面載入完成后,HttpWatch上就會(huì)出現(xiàn)如下信息

我們先看Summary選項(xiàng)卡,我們可以初步了解,這是一個(gè)POST請(qǐng)求(Http請(qǐng)求中的一種,另一種是GET),POST到的網(wǎng)址是http://coin.lib.scuec.edu.cn/cgi-bin/IlaswebBib。

這樣我們的思路就清晰了,我們的客戶端需要模擬瀏覽器,向上述地址POST一個(gè)包,那個(gè)地址肯定會(huì)返回一個(gè)Content給我們,不出意外的話,Content里面就是我們要的書(shū)目信息。那么,瀏覽器POST上去的內(nèi)容是什么呢?我們點(diǎn)擊這條POST請(qǐng)求,看詳細(xì)信息,

由于是POST請(qǐng)求,我們先看POST DATA,里面是以鍵值對(duì)的形式存儲(chǔ)的,這里顯示了我們?yōu)g覽器在我們搜索”android”時(shí),POST的所有數(shù)據(jù)。那這些鍵值對(duì)又代表了什么呢,我們打開(kāi)這個(gè)網(wǎng)頁(yè)的源碼來(lái)一探究竟。

從這段可以看出v_index是表示查找途徑的它有TITLE,AUTHOR,SUBJECT,CLASSNO,ISBN,CALLNO六種值

FLD_DAT_BEG和FLD_DAT_END分別是開(kāi)始和結(jié)束年份

v_value表示用戶在搜索框中輸入的內(nèi)容

v_paggnum表示每頁(yè)顯示的書(shū)目條數(shù),有10 15 20三種

v_seldatabases是檢索庫(kù) 有0 1 2三種值v_LogicSrch是檢索方式 有0 1兩種值[!--empirenews.page--]

Submit是查詢或重填,有 查 詢 和 重 填 兩種值

至此,我們弄清楚了POST Data里所有內(nèi)容的含義和取值可能。但我們模擬POST請(qǐng)求為什么,其實(shí)就是為了得到搜索的書(shū)目信息,所以我們看一下返回的Content是不是我們要的東西

果然,就是我們搜到的書(shū)目信息,就以String的形式放在Content里面。最后我們查看一下Stream,截圖,以防等下我們需要這里面的東西

好了,這個(gè)頁(yè)面的工作原理我們已經(jīng)弄清楚了:用戶在網(wǎng)頁(yè)中輸入搜索內(nèi)容后,點(diǎn)擊查詢,瀏覽器會(huì)POST一個(gè)Data到目標(biāo)網(wǎng)址,該網(wǎng)址的返回信息就是搜到的書(shū)目。

我們開(kāi)始編寫(xiě)代碼,模擬這個(gè)過(guò)程,先打開(kāi)eclipse建立一個(gè)Java項(xiàng)目(注意是Java項(xiàng)目,因?yàn)镴ava項(xiàng)目可以完美移植到Android項(xiàng)目中且調(diào)試方便,并且模擬Http請(qǐng)求這一過(guò)程沒(méi)有用到任何Android功能)。

導(dǎo)入HttpClient的4個(gè)包c(diǎn)ommons-codec、commons-httpclient、commons-logging、log4j。

//實(shí)例化HttpClient

HttpClient client = new HttpClient();

//Stream頁(yè)面里面有Host地址 端口是80

client.getHostConfiguration().setHost("http://coin.lib.scuec.edu.cn", 80);

//用目標(biāo)地址 實(shí)例一個(gè)POST方法

PostMethod post = new PostMethod("http://coin.lib.scuec.edu.cn/cgi-bin/IlaswebBib");

//將需要的鍵值對(duì)寫(xiě)出來(lái)

NameValuePair beg = new NameValuePair("FLD_DAT_BEG" , “”);

NameValuePair end = new NameValuePair("FLD_DAT_END" , “”);

NameValuePair submit = new NameValuePair("submit" , "查 詢"));

NameValuePair vIndex = new NameValuePair("v_index" , “TITLE”);

NameValuePair vLogicSrch = new NameValuePair("v_LogicSrch" , "0");

NameValuePair vPagenum = new NameValuePair("v_pagenum" , "10");

NameValuePair vSeldatabase = new NameValuePair("v_seldatabase" , "0");

NameValuePair vValue = new NameValuePair("v_value" ,”android”);

//給POST方法加入上述鍵值對(duì)

post.setRequestBody(new NameValuePair[] {beg , end , submit , vIndex , vLogicSrch , vPagenum , vSeldatabase , vValue});

//執(zhí)行POST方法

client.executeMethod(post);

//將POST返回的數(shù)據(jù)以流的形式讀入,再把輸入流流至一個(gè)buff緩沖字節(jié)數(shù)組

//StreamTool類(lèi)是我自己寫(xiě)的一個(gè)工具類(lèi),其內(nèi)容將在下文附出

byte[] buff = StreamTool.readInputStream(post.getResponseBodyAsStream());

//將返回的內(nèi)容格式化為String存在html中

String html = new String(buff);

//任務(wù)完成了,釋放連接

post.releaseConnection();

//StreamTool類(lèi)如下

public class StreamTool {

/**

* 從輸入流中獲取數(shù)據(jù)

* @param inputStream 輸入流

* @return 字節(jié)數(shù)組

* @throws Exception

*/

public static byte[] readInputStream(InputStream inputStream) throws Exception

{

//實(shí)例化一個(gè)輸出流

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

//一個(gè)1024字節(jié)的緩沖字節(jié)數(shù)組

byte[] buffer = new byte[1024];

int len = 0;

//讀流的基本知識(shí)

while ((len=inputStream.read(buffer)) != -1) {

outputStream.write(buffer, 0, len);

}

//用完要關(guān),大家都懂的

inputStream.close();

return outputStream.toByteArray();

}

}

現(xiàn)在,我們得到了POST方法返回的String,我們輸出到控制臺(tái)看看是什么

System.out.println(html);

沒(méi)錯(cuò),就是我們上文看到的HttpWatch 抓到的返回Content,也就是一段HTML代碼,這說(shuō)明,我們模擬瀏覽器POST請(qǐng)求成功了!

我們?cè)僭囋噭e的搜索內(nèi)容,來(lái)一個(gè)”android開(kāi)發(fā)”(即將v_value鍵值對(duì)的值改成”android開(kāi)發(fā)”),這時(shí)運(yùn)行后,我們卻從控制臺(tái)得到了這樣的結(jié)果:

經(jīng)過(guò)幾次試驗(yàn)后,發(fā)現(xiàn)一個(gè)規(guī)律,只要搜索內(nèi)容中包括中文,就搜不到。

所以可以判定是中文編碼的問(wèn)題,(在開(kāi)發(fā)這類(lèi)客戶端時(shí)候,中文編碼往往是個(gè)很具困難的問(wèn)題。安卓巴士開(kāi)發(fā)3群的某群友提到:服務(wù)器交流用的編碼是”ISO-8859-1”,跟我起初用到的編碼一致,但真實(shí)性仍需考證)所以我們修改上面的代碼,將代表搜索內(nèi)容的v_value對(duì)應(yīng)的值編碼為”ISO-8859-1”

就將上段代碼中的

NameValuePair vValue = new NameValuePair("v_value" ,”android”);

改為

NameValuePair vValue = new NameValuePair("v_value" , new String(“android開(kāi)發(fā)”.getBytes(),"ISO-8859-1"));[!--empirenews.page--]

這時(shí)再運(yùn)行,控制臺(tái)成功輸出以” android開(kāi)發(fā)”為關(guān)鍵字的Content。

至此,我們POST請(qǐng)求才真正完成。 觀察控制臺(tái)的HTML后發(fā)現(xiàn),我們需要的書(shū)目信息就在里面,只不過(guò)被一些HTML標(biāo)簽包裹住了,下一步我們就要解放這些信息,存儲(chǔ)到容器里。

這里我們要用到Jsoup,一個(gè)Java開(kāi)源HTML解析器(來(lái)自org.jsoup包)。

我們直接上代碼,逐行解釋(大家最好對(duì)應(yīng)上面的HTML代碼來(lái)理解)

首先我們建一個(gè)容器來(lái)裝這些解析到的數(shù)據(jù),由于我的項(xiàng)目是將這些數(shù)據(jù)以ListView呈現(xiàn)給用戶,而ListView的數(shù)據(jù)是由Adapter提供,Adapter需要傳一個(gè)特殊容器-包含HashMap的ArrayList(Android基礎(chǔ)知識(shí))

//所以有

List

//開(kāi)始使用Jsoup

//Jsoup支援一個(gè)Document類(lèi) 將剛才的html轉(zhuǎn)化成Document

Document document = Jsoup.parse(html);

//一個(gè)Document又由elements組成 我們選擇”tr”開(kāi)頭的標(biāo)簽,存入 trs元素群中

Elements trs = document.select("tr");

//得到整個(gè)HTML中包含tr的標(biāo)簽的個(gè)數(shù)

int totalTrs = trs.size();

//我們可以觀察上面沒(méi)有搜索結(jié)果的那個(gè)HTML。發(fā)現(xiàn),如果totalTrs<=3就表示沒(méi)結(jié)果。

//只要有書(shū)目結(jié)果totalTrs必定大于3,于是

if(totalTrs > 3)

for(int i = 0;i < totalTrs – 3;i++)

{

//觀察HTML,從第i+2個(gè)tr開(kāi)始,包含的才是我們要的書(shū)目信息

//我們從每個(gè)tr中選出td標(biāo)簽元素群

Elements tds = trs.get(i + 2).select("td");

//得到每個(gè)tr中td的個(gè)數(shù)

int totalTds = tds.size();

//一個(gè)臨時(shí)的HashMap,里面是String-Object鍵值對(duì)

Map

//j是一個(gè)標(biāo)識(shí)數(shù)

for(int j =0;j < totalTds ;j++)

{

switch (j) {

//0表示第一個(gè),即書(shū)名

//put方法即向map加入一條鍵值對(duì)

//html()方法就得到標(biāo)簽括起來(lái)的內(nèi)容

case 0:

map.put("book_title", tds.get(j).html().toString());

break;

case 1:

//1表示第二個(gè),即作者

map.put("book_author", tds.get(j).html().toString());

break;

case 2:

//2表示第三個(gè),即出版信息

map.put("book_press", tds.get(j).html().toString());

break;

case 3:

//3表示第四個(gè),即頁(yè)數(shù)

map.put("book_page", tds.get(j).html().toString());

break;

case 4:

//4表示第五個(gè),即價(jià)格

map.put("book_price", tds.get(j).html().toString());

break;

case 5:

//5表示第六個(gè),即索取號(hào)

map.put("book_noFor", tds.get(j).html().toString());

break;

case 6:

//6表示第七個(gè),即那段網(wǎng)址

//那段網(wǎng)址td中又包含一個(gè)a標(biāo)簽,a標(biāo)簽的href屬性的值就是網(wǎng)址

//attr(“href”)可以返回href屬性的值

map.put("book_detail", tds.get(j).select("a").attr("href").toString());

break;

default:

break;

}

}

list.add(map);

}

list就是我們需要的ArrayList啦

上面所有代碼調(diào)通后,我們只需一些簡(jiǎn)單的復(fù)制粘貼,就可以放在我們的Android工程中,加上一段簡(jiǎn)單的代碼就可以讓ListView顯示這個(gè)ArrayList。(由于沒(méi)有任何技術(shù)含量,以及該項(xiàng)目暫未上線,此段代碼不予以展示,敬請(qǐng)諒解)

接下來(lái),我們一個(gè)頁(yè)面最多只包含10個(gè)書(shū)目信息,而我們校圖書(shū)館,光以”Java”為關(guān)鍵字的書(shū)就超過(guò)1000本,怎么來(lái)顯示完全呢,一次顯示所有的書(shū)肯定不現(xiàn)實(shí)。首先數(shù)據(jù)量太大,手機(jī)無(wú)法承受;消耗流量過(guò)大,用戶體驗(yàn)極差。所以,我們就需要ListView能夠動(dòng)態(tài)加載數(shù)據(jù),即一開(kāi)始顯示十項(xiàng),如果用戶此時(shí)拉動(dòng)ListView顯示完十項(xiàng)之后,自動(dòng)聯(lián)網(wǎng),再加載十項(xiàng)(如果還有十項(xiàng)的話),這樣的用戶體驗(yàn)會(huì)非常順暢。

這個(gè)功能的核心是,我們的ListView需要實(shí)現(xiàn)OnScrollListener接口。

如果你的ListView所在的Activity繼承的是ListActivity的話,只需在extends ListActivity后面加上implements OnScrollListener,這時(shí)你需要復(fù)寫(xiě)onScroll和onScrollStateChanged。如果你的ListView是從XMLgetView 得到的,你只需為它setOnScrollListener,也會(huì)需要你復(fù)寫(xiě)onScroll和onScrollStateChanged。

不管你用哪種方法,我們只用修改onScroll方法

@Override

public void onScroll(AbsListView view, int firstVisibleItem,

int visibleItemCount, int totalItemCount) {

// TODO Auto-generated method stub

//關(guān)鍵的判斷代碼,這句話表示用戶將ListView拉至最底部

if(firstVisibleItem + visibleItemCount == totalItemCount)

//你只需要把繼續(xù)得到下面十項(xiàng)的代碼寫(xiě)在這里,就可以實(shí)現(xiàn)上述功能了。

//同樣再使用一次POST方法,不再贅述

//代碼由于同樣原因不予以展示,敬請(qǐng)諒解

至此,文章開(kāi)頭的幾個(gè)知識(shí)點(diǎn)已經(jīng)全部講解完畢,時(shí)間倉(cāng)促,事物繁忙,可能會(huì)影響文章質(zhì)量,還請(qǐng)大家多多包涵。 如果有問(wèn)題,可以直接回帖、發(fā)論壇信息或通過(guò)Email:anliupeinye@gmail.com聯(lián)系我。

項(xiàng)目成品展示:

看看這些信息是不是就是上面用網(wǎng)頁(yè)以"android"為關(guān)鍵字搜索到的?

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專(zhuān)欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車(chē)的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車(chē)技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車(chē)工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車(chē)。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車(chē) 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉