最近在參加學(xué)校安排的學(xué)期實(shí)訓,主要的項目是根據實(shí)訓需求實(shí)現基于WEB的旅游分享平臺,并實(shí)現對應的Android客戶(hù)端(截止到2012-07-16,Android的最高版本是4.1,可以在http://www.android.com/上查看最近更新)。
在開(kāi)發(fā)Android應用平臺的時(shí),遇到的第一個(gè)比較麻煩的問(wèn)題就是在A(yíng)ndroid模擬器中訪(fǎng)問(wèn)服務(wù)器接口。
1. 最先犯的錯誤就是:在連接服務(wù)器的時(shí)候使用 127.0.0.1 或者 localhost 來(lái)指定本機PC機器。 由于A(yíng)ndroid客戶(hù)端在測試的時(shí)候是在A(yíng)ndroid模擬器中運行的,所以127.0.0.1并不會(huì )指向PC開(kāi)發(fā)機,而是指向模擬器。 為了在測試的時(shí)候能夠訪(fǎng)問(wèn)到本機PC開(kāi)發(fā)機提供的接口,需要在服務(wù)器地址連接中使用 10.0.2.2:8080來(lái)指向本機PC機, 或者使用PC機當前的IP地址也可以。如下連接地址:
1 public static String server_url = "http://10.0.2.2:8080/travel";
2. 在A(yíng)ndroid應用的AndroidManifest.xml中添加網(wǎng)絡(luò )權限:
1 <uses-permission android:name="android.permission.INTERNET" />
3. 由于A(yíng)ndroid 4.1對于網(wǎng)絡(luò )限制比較的嚴格,所以在處理網(wǎng)絡(luò )連接的時(shí)候需要調用以下代碼。 我將其封裝在一個(gè)通用的方法中,如下所示:
1 @SuppressLint("NewApi") 2 public static void StrictMode() { 3 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() 4 .detectDiskReads() 5 .detectDiskWrites() 6 .detectNetwork() 7 .penaltyLog() 8 .build()); 9 10 StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()11 .detectLeakedSqlLiteObjects()12 .penaltyLog()13 .penaltyDeath()14 .build()); 15 }
4. 在A(yíng)ndroid客戶(hù)端訪(fǎng)問(wèn)服務(wù)器接口的方法有很多,我使用的是 HttpPost來(lái)完成服務(wù)器請求的。 具體的代碼如下:
1 //網(wǎng)絡(luò )通信 2 private HttpPost request; 3 private List<NameValuePair> params; 4 private HttpClient client; 5 private HttpResponse response; 6 private String server_url = Util.server_url + "/servlet/user" ; 7 8 9 //創(chuàng )建線(xiàn)程時(shí),初始化參數10 params = new ArrayList<NameValuePair>(); 11 params.add(new BasicNameValuePair("action", Util.USER_LOGIN));12 params.add(new BasicNameValuePair("username", username));13 params.add(new BasicNameValuePair("password", password));14 15 16 //處理用戶(hù)登錄17 try{18 request = new HttpPost(server_url);19 request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));20 21 client = new DefaultHttpClient();22 response = client.execute(request);23 24 if(response.getStatusLine().getStatusCode() == 200) {25 JSONArray array = new JSONArray(EntityUtils.toString(response.getEntity()));26 JSONObject result = array.optJSONObject(0);27 28 if(result.getInt("status") == 0){29 USER = result.getJSONObject("user");30 login_handler.sendEmptyMessage(LOGIN_SUCCESS);31 }else{32 login_handler.sendEmptyMessage(LOGIN_FAILED);33 }34 }else {35 login_handler.sendEmptyMessage(LOGIN_FAILED);36 }37 }catch(Exception e){38 login_handler.sendEmptyMessage(LOGIN_EXCEPTION);39 }finally{40 progress.dismiss();41 }
這里只是展示了整個(gè)發(fā)送請求的三個(gè)階段:聲明網(wǎng)絡(luò )通信API對象、初始化參數并添加到List列表、發(fā)送請求并處理請求。
在A(yíng)ndroid應用中,主要分為UI主線(xiàn)程和子線(xiàn)程。 其中,UI主線(xiàn)程負責屏幕元素的操作,子線(xiàn)程則處理數據的請求,不能對屏幕元素進(jìn)行操作, 這二者通過(guò)Handler 或者繼承子Handler對象的子類(lèi)對象來(lái)完成通信。 一般Handler對象主要使用三個(gè)方法: sendEmptyMessage(SUCCESS)、handleMessage(Message msg)。
如上述代碼所示,在子線(xiàn)程處理完數據之后,通過(guò)使用sendEmptyMessage方法來(lái)返回操作的狀態(tài)值,Handler類(lèi)中的handleMessage會(huì )根據返回的狀態(tài)值自動(dòng)對數據進(jìn)行處理。 一個(gè)最簡(jiǎn)單的Handler子類(lèi)的定義如下:
1 class LoginHandler extends Handler{ 2 3 @Override 4 public void handleMessage(Message msg) { 5 // TODO Auto-generated method stub 6 super.handleMessage(msg); 7 8 switch(msg.what){ 9 case LOGIN_SUCCESS:10 try {11 onLoginSuccess();12 } catch (JSONException e) {13 e.printStackTrace();14 }15 break;16 case LOGIN_FAILED:17 onLoginFailed();18 break;19 case LOGIN_EXCEPTION:20 onLoginException();21 break;22 }23 }
聯(lián)系客服