六、android 網絡編程

1基於socket的用法html

  服務器端:java

  先啓動一個服務器端的socket     ServerSocket svr = new ServerSocket(8989);android

  開始偵聽請求         Socket s = svr.accept();git

  取得輸入和輸出        DataInputStream dis = new DataInputStream(s.getInputStream());web

                 DataOutputStream dos = new DataOutputStream(s.getOutputStream());sql

  Socket 的交互經過流來完成,便是說傳送的字節流,所以任何文件均可以在上面傳送。誰打開的記得要關上。數據庫

  用DataInputStream/DataOutputStream來進行包裝是由於咱們想要他們對基本數據類型的讀寫功能readInt(),writeInt(),readUTF(),writeUTF()等等。express

  客戶端:apache

  發起一個socket鏈接      Socket s = new Socket("192.168.1.200",8989);編程

  取得輸入和輸出        DataInputStream dis = new DataInputStream(s.getInputStream());

                 DataOutputStream dos = new DataOutputStream(s.getOutputStream());

  以後就能夠相互通訊了。誰打開的記得要關上。

2基於Http協議

  通常是發送請求到某個應用服務器。此時須要用到HttpURLConnection

  先取得HttpURLConnection urlConn = new URL("http://www.google.com").openConnection();

  設置標誌 

    urlConn.setDoOutput(true);  urlConn.setDoInput(true);//post的狀況下須要設置DoOutputtrue

    urlConn.setRequestMethod("POST");

    urlConn.setUseCache(false);//設置是否用緩存

    urlConn.setRequestProperty("Content-type","application/x-www-form-urlencoded");//設置contenttype

  得到輸出流,便於想服務器發送信息。

    DataOutputStream dos = new DataOutputStream(urlConn.getOutputStream());

  望流裏面寫請求參數

    dos.writeBytes("name="+URLEncoder.encode("chenmouren","gb2312");

    dos.flush();dos.close();//發送完後立刻關閉。

  得到輸入流,取數據

    BufferReader reader = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));

    reader.readLine();//用 !=null來判斷是否結束

    reader.close();

  讀完了記得關閉connection  urlConn.disconnect();

流程記錄就到此爲止。

三、HttpURLConnection接口
    首先須要明確的是,Http通訊中的POST和GET請求方式的不一樣。GET能夠得到靜態頁面,也能夠把參數放在URL字符串後面,傳遞給服務器。而POST方法的參數是放在Http請求中。所以,在編程以前,應當首先明確使用的請求方法,而後再根據所使用的方式選擇相應的編程方式。
    HttpURLConnection是繼承於URLConnection類,兩者都是抽象類。其對象主要經過URL的openConnection方法得到。建立方法以下代碼所示:

 
 

  1. URL url = new URL("http://www.51cto.com/index.jsp?par=123456");  
  2. HttpURLConnection urlConn=(HttpURLConnection)url.openConnection(); 

   

    經過如下方法能夠對請求的屬性進行一些設置,以下所示:

 
 

  1. //設置輸入和輸出流  
  2. urlConn.setDoOutput(true);  
  3. urlConn.setDoInput(true);  
  4. //設置請求方式爲POST  
  5. urlConn.setRequestMethod("POST");  
  6. //POST請求不能使用緩存  
  7. urlConn.setUseCaches(false);  
  8. //關閉鏈接  
  9. urlConn.disConnection();  



HttpURLConnection默認使用GET方式,例以下面代碼所示:

 
 

  1. //使用HttpURLConnection打開鏈接  
  2. HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();  
  3. //獲得讀取的內容( 
  4. InputStreamReader in = new InputStreamReader(urlConn.getInputStream());  
  5. // 爲輸出建立BufferedReader  
  6. BufferedReader buffer = new BufferedReader(in);  
  7. String inputLine = null;  
  8. //使用循環來讀取得到的數據  
  9. while (((inputLine = buffer.readLine()) != null))  
  10. {  
  11. //咱們在每一行後面加上一個"\n"來換行  
  12. resultData += inputLine + "\n";  
  13. }           
  14. //關閉InputStreamReader  
  15. in.close();  
  16. //關閉http鏈接  
  17. urlConn.disconnect(); 



    若是須要使用POST方式,則須要setRequestMethod設置。代碼以下:

 
 

  1. String httpUrl = "http://192.168.1.110:8080/httpget.jsp";  
  2. //得到的數據  
  3. String resultData = "";  
  4. URL url = null;  
  5. try 
  6. {  
  7. //構造一個URL對象  
  8. url = new URL(httpUrl);   
  9. }  
  10. catch (MalformedURLException e)  
  11. {  
  12. Log.e(DEBUG_TAG, "MalformedURLException");  
  13. }  
  14. if (url != null)  
  15. {  
  16. try 
  17. {  
  18. // 使用HttpURLConnection打開鏈接  
  19. HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();  
  20. //由於這個是post請求,設立須要設置爲true  
  21. urlConn.setDoOutput(true);  
  22. urlConn.setDoInput(true);  
  23. // 設置以POST方式  
  24. urlConn.setRequestMethod("POST");  
  25. // Post 請求不能使用緩存  
  26. urlConn.setUseCaches(false);  
  27. urlConn.setInstanceFollowRedirects(true);  
  28. // 配置本次鏈接的Content-type,配置爲application/x-www-form-urlencoded的  
  29. urlConn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");  
  30. // 鏈接,從postUrl.openConnection()至此的配置必需要在connect以前完成,  
  31. // 要注意的是connection.getOutputStream會隱含的進行connect。  
  32. urlConn.connect();  
  33. //DataOutputStream流  
  34. DataOutputStream out = new DataOutputStream(urlConn.getOutputStream());  
  35. //要上傳的參數  
  36. String content = "par=" + URLEncoder.encode("ABCDEFG", "gb2312");  
  37. //將要上傳的內容寫入流中  
  38. out.writeBytes(content);   
  39. //刷新、關閉  
  40. out.flush();  
  41. out.close();  

 

四、使用Apache提供的HttpClient接口一樣能夠進行HTTP操做。

    對於GET和POST請求方法的操做有所不一樣。GET方法的操做代碼示例以下:

[java] view plaincopy

  1. // http地址    
  2. String httpUrl = "http://192.168.1.110:8080/httpget.jsp?par=HttpClient_android_Get";    
  3. //HttpGet鏈接對象    
  4. HttpGet httpRequest = new HttpGet(httpUrl);    
  5. //取得HttpClient對象    
  6. HttpClient httpclient = new DefaultHttpClient();    
  7. //請求HttpClient,取得HttpResponse    
  8. HttpResponse httpResponse = httpclient.execute(httpRequest);    
  9. //請求成功    
  10. if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK)    
  11. {    
  12. //取得返回的字符串    
  13. String strResult = EntityUtils.toString(httpResponse.getEntity());    
  14. mTextView.setText(strResult);    
  15. }    
  16. else   
  17. {    
  18. mTextView.setText("請求錯誤!");    
  19. }    
  20. }   

 

    使用POST方法進行參數傳遞時,須要使用NameValuePair來保存要傳遞的參數。,另外,還須要設置所使用的字符集。代碼以下所示:

 

[java] view plaincopy

  1. // http地址    
  2. String httpUrl = "http://192.168.1.110:8080/httpget.jsp";    
  3. //HttpPost鏈接對象    
  4. HttpPost httpRequest = new HttpPost(httpUrl);    
  5. //使用NameValuePair來保存要傳遞的Post參數    
  6. List<NameValuePair> params = new ArrayList<NameValuePair>();    
  7. //添加要傳遞的參數    
  8. params.add(new BasicNameValuePair("par", "HttpClient_android_Post"));    
  9. //設置字符集    
  10. HttpEntity httpentity = new UrlEncodedFormEntity(params, "gb2312");    
  11. //請求httpRequest    
  12. httpRequest.setEntity(httpentity);    
  13. //取得默認的HttpClient    
  14. HttpClient httpclient = new DefaultHttpClient();    
  15. //取得HttpResponse    
  16. HttpResponse httpResponse = httpclient.execute(httpRequest);    
  17. //HttpStatus.SC_OK表示鏈接成功    
  18. if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK)    
  19. {    
  20. //取得返回的字符串    
  21. String strResult = EntityUtils.toString(httpResponse.getEntity());    
  22. mTextView.setText(strResult);    
  23. }    
  24. else   
  25. {    
  26. mTextView.setText("請求錯誤!");    
  27. }    
  28. }   

 

HttpClient其實是對Java提供方法的一些封裝,在HttpURLConnection中的輸入輸出流操做,在這個接口中被統一封裝成了HttpPost(HttpGet)和HttpResponse,這樣,就減小了操做的繁瑣性。

另外,在使用POST方式進行傳輸時,須要進行字符編碼。

五、

  1. package com.study.ws;  
  2. import java.io.IOException;  
  3. import org.ksoap2.SoapEnvelope;  
  4. import org.ksoap2.SoapFault;  
  5. import org.ksoap2.serialization.SoapObject;  
  6. import org.ksoap2.serialization.SoapSerializationEnvelope;  
  7. import org.ksoap2.transport.AndroidHttpTransport;  
  8. import org.ksoap2.transport.HttpTransportSE;  
  9. import org.xmlpull.v1.XmlPullParserException;  
  10. import android.app.Activity;  
  11. import android.os.Bundle;  
  12. import android.view.View;  
  13. import android.view.View.OnClickListener;  
  14. import android.webkit.WebSettings;  
  15. import android.widget.Button;  
  16. import android.widget.EditText;  
  17. import android.widget.TextView;  
  18. public class WSClient extends Activity {  
  19.  private Button search;  
  20.  private EditText phone;  
  21.  private TextView  result;  
  22.     /** Called when the activity is first created. */  
  23.     @Override  
  24.     public void onCreate(Bundle savedInstanceState) {  
  25.         super.onCreate(savedInstanceState);  
  26.         setContentView(R.layout.main);  
  27.         search=(Button)findViewById(R.id.search);  
  28.         phone=(EditText)findViewById(R.id.phone);  
  29.         result=(TextView)findViewById(R.id.result);  
  30.         search.setOnClickListener(new OnClickListener() {  
  31.      
  32.    @Override  
  33.    public void onClick(View v) {  
  34.     String strPhone=phone.getText().toString().trim();  
  35.     if(!(strPhone.length()==0||strPhone.equals("")))  
  36.     {  
  37.       String str = "";  
  38.     try {  
  39.      str = getPhoneInfo(strPhone);  
  40.     } catch (IOException e) {  
  41.      // TODO Auto-generated catch block  
  42.      e.printStackTrace();  
  43.     } catch (XmlPullParserException e) {  
  44.      // TODO Auto-generated catch block  
  45.      e.printStackTrace();  
  46.     }  
  47.       result.setText(str);  
  48.     }  
  49.    }  
  50.   });  
  51.           
  52.     }  
  53.     public String getPhoneInfo(String phoneName) throws IOException, XmlPullParserException  
  54.     {  
  55.      //返回的查詢結果  
  56.      String result = null;  
  57.      //調用webservice接口的名稱空間  
  58.      String nameSpace="http://WebXml.com.cn/";  
  59.      //調用的方法名  
  60.      String methodName="getMobileCodeInfo";  
  61.      //將方法名和名稱空間綁定在一塊兒  
  62.   String SOAP_ACTION = nameSpace + methodName;  
  63. //得到返回請求對象  
  64. SoapObject request = new SoapObject(nameSpace, methodName);  
  65. //設置須要返回請求對象的參數  
  66.   request.addProperty("mobileCode", phoneName);  
  67.   request.addProperty("userId", "");  
  68.   //設置soap的版本  
  69.   SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(  
  70.     SoapEnvelope.VER11);  
  71.         //設置是否調用的是dotNet開發的  
  72.   envelope.dotNet = true;  
  73.   //  
  74.   envelope.bodyOut = request;  
  75.   AndroidHttpTransport hts = new AndroidHttpTransport  
  76. ("http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx");  
  77.   // web service請求  
  78.   hts.call(SOAP_ACTION, envelope);  
  79.   // 獲得返回結果  
  80.   Object o = envelope.getResponse();  
  81.   result = o.toString();  
  82.    
  83.   return result;  
  84.     
  85. }  
  86. }  

 

61、獲取並使用KSOAP

Android SDK中並無提供調用WebService的庫,所以,須要使用第三方的SDK來調用WebServicePC版本的WebService庫很是豐富,但這些對Android來講過於龐大。適合手機的WebService客戶端的SDK有一些,比較經常使用的是KSOAP2

KSOAP2 地址:http://code.google.com/p/ksoap2-android/

我下載的最新的是: ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar

注意:

我在使用ksoap2-android時犯了一個低級錯誤:使用時報錯誤:The import org.ksoap2 cannot be resolved 
當時分析這個問題時一直覺得是Eclipse出了問題,找了好多方法都不行, 
實際是我下載的ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar文件是錯誤的致使的,走了彎路。

 http://code.google.com/p/ksoap2-android/wiki/HowToUse?tm=2 頁面 經過鼠標右鍵連接另存爲存的是同名的一個純文本的Html文件。而不是咱們想要的。

我是在 
http://code.google.com/p/ksoap2-android/source/browse/m2-repo/com/google/code/ksoap2-android/ksoap2-android-assembly/2.5.4/ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar  點 View raw file 才正確下載對應文件的。

 

 

選擇咱們的項目,右鍵菜單中 Build Path –> Add External Archives… 增長這個下載的包

 

增長好後,咱們在 選擇咱們的項目,右鍵菜單中 Build Path –> Configure Build Path 的 Libraries 中能夠看到下面圖:

 

二,分如下幾步來調用 WebService

 

1、指定 WebService 的命名空間和調用方法

import org.ksoap2.serialization.SoapObject;private static final String NAMESPACE = "http://WebXml.com.cn/";private static final String METHOD_NAME = "getWeatherbyCityName"; SoapObject rpc = new SoapObject(NAMESPACE, METHOD_NAME);

SoapObject類的第一個參數表示WebService的命名空間,能夠從WSDL文檔中找到WebService的命名空間。 
第二個參數表示要調用的WebService方法名。

2、設置調用方法的參數值,若是沒有參數,能夠省略,設置方法的參數值的代碼以下:

rpc.addProperty("theCityName", "北京");

要注意的是,addProperty方法的第1個參數雖然表示調用方法的參數名,但該參數值並不必定與服務端的WebService類中的方法參數名一致,只要設置參數的順序一致便可。

3、生成調用Webservice方法的SOAP請求信息。

SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);envelope.bodyOut = rpc;envelope.dotNet = true;envelope.setOutputSoapObject(rpc);

建立SoapSerializationEnvelope對象時須要經過SoapSerializationEnvelope類的構造方法設置SOAP協議的版本號。 
該版本號須要根據服務端WebService的版本號設置。 
在建立SoapSerializationEnvelope對象後,不要忘了設置SOAPSoapSerializationEnvelope類的bodyOut屬性, 
該屬性的值就是在第一步建立的SoapObject對象。

4、建立HttpTransportsSE對象。

這裏不要使用 AndroidHttpTransport ht = new AndroidHttpTransport(URL); 這是一個要過時的類

private static String URL = "http://www.webxml.com.cn/webservices/weatherwebservice.asmx";HttpTransportSE ht = new HttpTransportSE(URL); 

ht.debug = true;

5、使用call方法調用WebService方法

private static String SOAP_ACTION = "http://WebXml.com.cn/getWeatherbyCityName";ht.call(SOAP_ACTION, envelope);

網上有人說這裏的call的第一個參數爲null,可是通過個人測試,null是不行的。 
2個參數就是在第3步建立的SoapSerializationEnvelope對象。

6、得到WebService方法的返回結果

有兩種方法:

1、使用getResponse方法得到返回數據。

private SoapObject detail;detail =(SoapObject) envelope.getResponse();

2、使用 bodyIn 及 getProperty

private SoapObject detail;SoapObject result = (SoapObject)envelope.bodyIn;detail = (SoapObject) result.getProperty("getWeatherbyCityNameResult");

7、 這時候執行會出錯,提示沒有權限訪問網絡

須要修改 AndroidManifest.xml 文件,賦予相應權限

簡單來講就是增長下面這行配置:<uses-permission android:name="android.permission.INTERNET"></uses-permission>

完整的 AndroidManifest.xml 文件 以下:

 

注:Android 中在代碼中爲了調試寫了system.out.print()輸出項

在菜單:Window-->show view-->other-->找到Android,選擇Logcat 是能夠看到輸出的
若是你想在一個單獨的窗口看到system.out.print()的輸出的話,能夠在logcat界面點那個綠色的「+」好,

Filter name 和 By log tag裏面均填入System.out,這樣的話你就能在單獨的界面查看system.out.print()的輸出了!!

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ghj1976.MyWeather" android:versionCode="1" android:versionName="1.0">  <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MyWeatherActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.INTERNET"></uses-permission> </manifest>

完整的代碼以下:

package ghj1976.MyWeather;import java.io.UnsupportedEncodingException;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.Toast;import org.ksoap2.SoapEnvelope;import org.ksoap2.serialization.SoapObject;import org.ksoap2.serialization.SoapSerializationEnvelope;//import org.ksoap2.transport.AndroidHttpTransport;import org.ksoap2.transport.HttpTransportSE;public class MyWeatherActivity extends Activity {  private Button okButton;  /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); okButton = (Button) this.findViewById(R.id.btn_Search); okButton.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) {   String city = "北京";   getWeather(city);   }  }); }  private static final String NAMESPACE = "http://WebXml.com.cn/";  // WebService地址 private static String URL = "http://www.webxml.com.cn/webservices/weatherwebservice.asmx";  private static final String METHOD_NAME = "getWeatherbyCityName";  private static String SOAP_ACTION = "http://WebXml.com.cn/getWeatherbyCityName";  private String weatherToday;  private SoapObject detail;  public void getWeather(String cityName) { try { System.out.println("rpc------"); SoapObject rpc = new SoapObject(NAMESPACE, METHOD_NAME); System.out.println("rpc" + rpc); System.out.println("cityName is " + cityName); rpc.addProperty("theCityName", cityName);  SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.bodyOut = rpc; envelope.dotNet = true; envelope.setOutputSoapObject(rpc); HttpTransportSE ht = new HttpTransportSE(URL);  //AndroidHttpTransport ht = new AndroidHttpTransport(URL); ht.debug = true;  ht.call(SOAP_ACTION, envelope); //ht.call(null, envelope);  //SoapObject result = (SoapObject)envelope.bodyIn; //detail = (SoapObject) result.getProperty("getWeatherbyCityNameResult");  detail =(SoapObject) envelope.getResponse(); //System.out.println("result" + result); System.out.println("detail" + detail); Toast.makeText(this, detail.toString(), Toast.LENGTH_LONG).show(); parseWeather(detail);  return; } catch (Exception e) { e.printStackTrace(); } }  private void parseWeather(SoapObject detail) throws UnsupportedEncodingException { String date = detail.getProperty(6).toString(); weatherToday = "今天:" + date.split(" ")[0]; weatherToday = weatherToday + "\n天氣:" + date.split(" ")[1]; weatherToday = weatherToday + "\n氣溫:" + detail.getProperty(5).toString(); weatherToday = weatherToday + "\n風力:" + detail.getProperty(7).toString() + "\n"; System.out.println("weatherToday is " + weatherToday); Toast.makeText(this, weatherToday, Toast.LENGTH_LONG).show();  }}

參考資料

Android中訪問WebService接口 
http://www.cnblogs.com/yy-7years/archive/2011/01/24/1943286.html

Android調用WebService 
http://express.ruanko.com/ruanko-express_34/technologyexchange5.html

中國氣象局的WebService地址 
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx

Android與服務器端數據交互(基於SOAP協議整合android+webservice 
http://www.cnblogs.com/zhangdongzi/archive/2011/04/19/2020688.html

版權聲明:本文爲博主原創文章,未經博主容許不得轉載。

 

7[java] view plaincopy

  1. 在android程序中運行第一步就是檢測當前有無可用網絡   
  2. 若是沒有網絡可用就退出程序   
  3. if (isConnect(this)==false)   
  4. {     
  5. new AlertDialog.Builder(this)   
  6. .setTitle("網絡錯誤")   
  7. .setMessage("網絡鏈接失敗,請確認網絡鏈接")   
  8. .setPositiveButton("肯定", new DialogInterface.OnClickListener() {   
  9. @Override   
  10. public void onClick(DialogInterface arg0, int arg1) {   
  11. // TODO Auto-generated method stub   
  12. android.os.Process.killProcess(android.os.Process.myPid());   
  13. System.exit(0);   
  14. }   
  15. }).show();   
  16. }   
  17. public static boolean isConnect(Context context) {   
  18. // 獲取手機全部鏈接管理對象(包括對wi-fi,net等鏈接的管理)   
  19. try {   
  20. ConnectivityManager connectivity = (ConnectivityManager) context   
  21. .getSystemService(Context.CONNECTIVITY_SERVICE);   
  22. if (connectivity != null) {   
  23. // 獲取網絡鏈接管理的對象   
  24. NetworkInfo info = connectivity.getActiveNetworkInfo();   
  25. if (info != null&& info.isConnected()) {   
  26. // 判斷當前網絡是否已經鏈接   
  27. if (info.getState() == NetworkInfo.State.CONNECTED) {   
  28. return true;   
  29. }   
  30. }   
  31. }   
  32. } catch (Exception e) {   
  33. // TODO: handle exception   
  34. Log.v("error",e.toString());   
  35. }   
  36. return false;   
  37. }   
  38. 最後一點還得再manifest中添加權限   
  39. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  

8[java] view plaincopy

  1. public class MainActivity extends Activity     
  2. {    
  3. private static final String TAG = "MainActivity";    
  4. private EditText timelengthText;    
  5. private EditText titleText;    
  6. private EditText videoText;    
  7. @Override    
  8. public void onCreate(Bundle savedInstanceState)     
  9. {    
  10. super.onCreate(savedInstanceState);    
  11. setContentView(R.layout.main);    
  12. //提交上傳按鈕    
  13. Button button = (Button) this.findViewById(R.id.button);    
  14. timelengthText = (EditText) this.findViewById(R.id.timelength);    
  15. videoText = (EditText) this.findViewById(R.id.video);    
  16. titleText = (EditText) this.findViewById(R.id.title);    
  17. button.setOnClickListener(new View.OnClickListener()     
  18. {                
  19. @Override    
  20. public void onClick(View v)     
  21. {    
  22. String title = titleText.getText().toString();    
  23. String timelength = timelengthText.getText().toString();    
  24. Map<String, String> params = new HashMap<String, String>();    
  25. params.put("method", "save");    
  26. params.put("title", title);    
  27. params.put("timelength", timelength);    
  28. try     
  29. {                       
  30. //獲得SDCard的目錄    
  31. File uploadFile = new File(Environment.getExternalStorageDirectory(), videoText.getText().toString());    
  32. //上傳音頻文件    
  33. FormFile formfile = new FormFile("02.mp3", uploadFile, "video", "audio/mpeg");    
  34. SocketHttpRequester.post("http://192.168.1.100:8080/videoweb/video/manage.do", params, formfile);    
  35. Toast.makeText(MainActivity.this, R.string.success, 1).show();    
  36. }    
  37. catch (Exception e)     
  38. {    
  39. Toast.makeText(MainActivity.this, R.string.error, 1).show();    
  40. Log.e(TAG, e.toString());    
  41. }    
  42. }    
  43. });            
  44. }    
  45. }    

[java] view plaincopy

  1. .上傳工具類,注意裏面構造協議字符串須要根據不一樣的提交表單來處理  
  2. public class SocketHttpRequester     
  3. {    
  4. /**  
  5. * 發送xml數據  
  6. * @param path 請求地址  
  7. * @param xml xml數據  
  8. * @param encoding 編碼  
  9. * @return  
  10. * @throws Exception  
  11. */    
  12. public static byte[] postXml(String path, String xml, String encoding) throws Exception{    
  13. byte[] data = xml.getBytes(encoding);    
  14. URL url = new URL(path);    
  15. HttpURLConnection conn = (HttpURLConnection)url.openConnection();    
  16. conn.setRequestMethod("POST");    
  17. conn.setDoOutput(true);    
  18. conn.setRequestProperty("Content-Type", "text/xml; charset="+ encoding);    
  19. conn.setRequestProperty("Content-Length", String.valueOf(data.length));    
  20. conn.setConnectTimeout(5 * 1000);    
  21. OutputStream outStream = conn.getOutputStream();    
  22. outStream.write(data);    
  23. outStream.flush();    
  24. outStream.close();    
  25. if(conn.getResponseCode()==200){    
  26. return readStream(conn.getInputStream());    
  27. }    
  28. return null;    
  29. }    
  30. /**  
  31. * 直接經過HTTP協議提交數據到服務器,實現以下面表單提交功能:  
  32. *   <FORM METHOD=POST ACTION="http://192.168.0.200:8080/ssi/fileload/test.do" enctype="multipart/form-data">  
  33. <INPUT TYPE="text" NAME="name">  
  34. <INPUT TYPE="text" NAME="id">  
  35. <input type="file" name="imagefile"/>  
  36. <input type="file" name="zip"/>  
  37. </FORM>  
  38. * @param path 上傳路徑(注:避免使用localhost或127.0.0.1這樣的路徑測試,  
  39. *                  由於它會指向手機模擬器,你可使用http://www.baidu.com或http://192.168.1.10:8080這樣的路徑測試)  
  40. * @param params 請求參數 key爲參數名,value爲參數值  
  41. * @param file 上傳文件  
  42. */    
  43. public static boolean post(String path, Map<String, String> params, FormFile[] files) throws Exception    
  44. {       
  45. //數據分隔線    
  46. final String BOUNDARY = "---------------------------7da2137580612";     
  47. //數據結束標誌"---------------------------7da2137580612--"    
  48. final String endline = "--" + BOUNDARY + "--/r/n";    
  49. //下面兩個for循環都是爲了獲得數據長度參數,依據表單的類型而定    
  50. //首先獲得文件類型數據的總長度(包括文件分割線)    
  51. int fileDataLength = 0;    
  52. for(FormFile uploadFile : files)    
  53. {    
  54. StringBuilder fileExplain = new StringBuilder();    
  55. fileExplain.append("--");    
  56. fileExplain.append(BOUNDARY);    
  57. fileExplain.append("/r/n");    
  58. fileExplain.append("Content-Disposition: form-data;name=/""+ uploadFile.getParameterName()+"/";filename=/""+ uploadFile.getFilname() + "/"/r/n");    
  59. fileExplain.append("Content-Type: "+ uploadFile.getContentType()+"/r/n/r/n");    
  60. fileExplain.append("/r/n");    
  61. fileDataLength += fileExplain.length();    
  62. if(uploadFile.getInStream()!=null){    
  63. fileDataLength += uploadFile.getFile().length();    
  64. }else{    
  65. fileDataLength += uploadFile.getData().length;    
  66. }    
  67. }    
  68. //再構造文本類型參數的實體數據    
  69. StringBuilder textEntity = new StringBuilder();            
  70. for (Map.Entry<String, String> entry : params.entrySet())     
  71. {      
  72. textEntity.append("--");    
  73. textEntity.append(BOUNDARY);    
  74. textEntity.append("/r/n");    
  75. textEntity.append("Content-Disposition: form-data; name=/""+ entry.getKey() + "/"/r/n/r/n");    
  76. textEntity.append(entry.getValue());    
  77. textEntity.append("/r/n");    
  78. }    
  79. //計算傳輸給服務器的實體數據總長度(文本總長度+數據總長度+分隔符)    
  80. int dataLength = textEntity.toString().getBytes().length + fileDataLength +  endline.getBytes().length;    
  81. URL url = new URL(path);    
  82. //默認端口號其實能夠不寫    
  83. int port = url.getPort()==-1 ? 80 : url.getPort();    
  84. //創建一個Socket連接    
  85. Socket socket = new Socket(InetAddress.getByName(url.getHost()), port);    
  86. //得到一個輸出流(從Android流到web)    
  87. OutputStream outStream = socket.getOutputStream();    
  88. //下面完成HTTP請求頭的發送    
  89. String requestmethod = "POST "+ url.getPath()+" HTTP/1.1/r/n";    
  90. outStream.write(requestmethod.getBytes());    
  91. //構建accept    
  92. String accept = "Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*/r/n";    
  93. outStream.write(accept.getBytes());    
  94. //構建language    
  95. String language = "Accept-Language: zh-CN/r/n";    
  96. outStream.write(language.getBytes());    
  97. //構建contenttype    
  98. String contenttype = "Content-Type: multipart/form-data; boundary="+ BOUNDARY+ "/r/n";    
  99. outStream.write(contenttype.getBytes());    
  100. //構建contentlength    
  101. String contentlength = "Content-Length: "+ dataLength + "/r/n";    
  102. outStream.write(contentlength.getBytes());    
  103. //構建alive    
  104. String alive = "Connection: Keep-Alive/r/n";            
  105. outStream.write(alive.getBytes());    
  106. //構建host    
  107. String host = "Host: "+ url.getHost() +":"+ port +"/r/n";    
  108. outStream.write(host.getBytes());    
  109. //寫完HTTP請求頭後根據HTTP協議再寫一個回車換行    
  110. outStream.write("/r/n".getBytes());    
  111. //把全部文本類型的實體數據發送出來    
  112. outStream.write(textEntity.toString().getBytes());             
  113. //把全部文件類型的實體數據發送出來    
  114. for(FormFile uploadFile : files)    
  115. {    
  116. StringBuilder fileEntity = new StringBuilder();    
  117. fileEntity.append("--");    
  118. fileEntity.append(BOUNDARY);    
  119. fileEntity.append("/r/n");    
  120. fileEntity.append("Content-Disposition: form-data;name=/""+ uploadFile.getParameterName()+"/";filename=/""+ uploadFile.getFilname() + "/"/r/n");    
  121. fileEntity.append("Content-Type: "+ uploadFile.getContentType()+"/r/n/r/n");    
  122. outStream.write(fileEntity.toString().getBytes());    
  123. //邊讀邊寫    
  124. if(uploadFile.getInStream()!=null)    
  125. {    
  126. byte[] buffer = new byte[1024];    
  127. int len = 0;    
  128. while((len = uploadFile.getInStream().read(buffer, 0, 1024))!=-1)    
  129. {    
  130. outStream.write(buffer, 0, len);    
  131. }    
  132. uploadFile.getInStream().close();    
  133. }    
  134. else    
  135. {    
  136. outStream.write(uploadFile.getData(), 0, uploadFile.getData().length);    
  137. }    
  138. outStream.write("/r/n".getBytes());    
  139. }    
  140. //下面發送數據結束標誌,表示數據已經結束    
  141. outStream.write(endline.getBytes());            
  142. BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));    
  143. //讀取web服務器返回的數據,判斷請求碼是否爲200,若是不是200,表明請求失敗    
  144. if(reader.readLine().indexOf("200")==-1)    
  145. {    
  146. return false;    
  147. }    
  148. outStream.flush();    
  149. outStream.close();    
  150. reader.close();    
  151. socket.close();    
  152. return true;    
  153. }    
  154. /**    
  155. * 提交數據到服務器    
  156. * @param path 上傳路徑(注:避免使用localhost或127.0.0.1這樣的路徑測試,由於它會指向手機模擬器,你可使用http://www.baidu.com或http://192.168.1.10:8080這樣的路徑測試)    
  157. * @param params 請求參數 key爲參數名,value爲參數值    
  158. * @param file 上傳文件    
  159. */    
  160. public static boolean post(String path, Map<String, String> params, FormFile file) throws Exception    
  161. {    
  162. return post(path, params, new FormFile[]{file});    
  163. }    
  164. /**  
  165. * 提交數據到服務器  
  166. * @param path 上傳路徑(注:避免使用localhost或127.0.0.1這樣的路徑測試,由於它會指向手機模擬器,你可使用http://www.baidu.com或http://192.168.1.10:8080這樣的路徑測試)  
  167. * @param params 請求參數 key爲參數名,value爲參數值  
  168. * @param encode 編碼  
  169. */    
  170. public static byte[] postFromHttpClient(String path, Map<String, String> params, String encode) throws Exception    
  171. {    
  172. //用於存放請求參數    
  173. List<NameValuePair> formparams = new ArrayList<NameValuePair>();    
  174. for(Map.Entry<String, String> entry : params.entrySet())    
  175. {    
  176. formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));    
  177. }    
  178. UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, encode);    
  179. HttpPost httppost = new HttpPost(path);    
  180. httppost.setEntity(entity);    
  181. //看做是瀏覽器    
  182. HttpClient httpclient = new DefaultHttpClient();    
  183. //發送post請求      
  184. HttpResponse response = httpclient.execute(httppost);       
  185. return readStream(response.getEntity().getContent());    
  186. }    
  187. /**  
  188. * 發送請求  
  189. * @param path 請求路徑  
  190. * @param params 請求參數 key爲參數名稱 value爲參數值  
  191. * @param encode 請求參數的編碼  
  192. */    
  193. public static byte[] post(String path, Map<String, String> params, String encode) throws Exception    
  194. {    
  195. //String params = "method=save&name="+ URLEncoder.encode("老畢", "UTF-8")+ "&age=28&";//須要發送的參數    
  196. StringBuilder parambuilder = new StringBuilder("");    
  197. if(params!=null && !params.isEmpty())    
  198. {    
  199. for(Map.Entry<String, String> entry : params.entrySet())    
  200. {    
  201. parambuilder.append(entry.getKey()).append("=")    
  202. .append(URLEncoder.encode(entry.getValue(), encode)).append("&");    
  203. }    
  204. parambuilder.deleteCharAt(parambuilder.length()-1);    
  205. }    
  206. byte[] data = parambuilder.toString().getBytes();    
  207. URL url = new URL(path);    
  208. HttpURLConnection conn = (HttpURLConnection)url.openConnection();    
  209. //設置容許對外發送請求參數    
  210. conn.setDoOutput(true);    
  211. //設置不進行緩存    
  212. conn.setUseCaches(false);    
  213. conn.setConnectTimeout(5 * 1000);    
  214. conn.setRequestMethod("POST");    
  215. //下面設置http請求頭    
  216. conn.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");    
  217. conn.setRequestProperty("Accept-Language", "zh-CN");    
  218. conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");    
  219. conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");    
  220. conn.setRequestProperty("Content-Length", String.valueOf(data.length));    
  221. conn.setRequestProperty("Connection", "Keep-Alive");    
  222. //發送參數    
  223. DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());    
  224. outStream.write(data);//把參數發送出去    
  225. outStream.flush();    
  226. outStream.close();    
  227. if(conn.getResponseCode()==200)    
  228. {    
  229. return readStream(conn.getInputStream());    
  230. }    
  231. return null;    
  232. }    
  233. /**    
  234. * 讀取流    
  235. * @param inStream    
  236. * @return 字節數組    
  237. * @throws Exception    
  238. */    
  239. public static byte[] readStream(InputStream inStream) throws Exception    
  240. {    
  241. ByteArrayOutputStream outSteam = new ByteArrayOutputStream();    
  242. byte[] buffer = new byte[1024];    
  243. int len = -1;    
  244. while( (len=inStream.read(buffer)) != -1)    
  245. {    
  246. outSteam.write(buffer, 0, len);    
  247. }    
  248. outSteam.close();    
  249. inStream.close();    
  250. return outSteam.toByteArray();    
  251. }    
  252. }    

 

[java] view plaincopy

  1. public class StreamTool     
  2. {    
  3. /**  
  4. * 從輸入流讀取數據  
  5. * @param inStream  
  6. * @return  
  7. * @throws Exception  
  8. */    
  9. public static byte[] readInputStream(InputStream inStream) throws Exception{    
  10. ByteArrayOutputStream outSteam = new ByteArrayOutputStream();    
  11. byte[] buffer = new byte[1024];    
  12. int len = 0;    
  13. while( (len = inStream.read(buffer)) !=-1 ){    
  14. outSteam.write(buffer, 0, len);    
  15. }    
  16. outSteam.close();    
  17. inStream.close();    
  18. return outSteam.toByteArray();    
  19. }    
  20. }    

 

[java] view plaincopy

  1. /**  
  2. * 使用JavaBean封裝上傳文件數據  
  3. *   
  4. */    
  5. public class FormFile     
  6. {    
  7. //上傳文件的數據     
  8. private byte[] data;    
  9. private InputStream inStream;    
  10. private File file;    
  11. //文件名稱     
  12. private String filname;    
  13. //請求參數名稱    
  14. private String parameterName;    
  15. //內容類型    
  16. private String contentType = "application/octet-stream";    
  17. /**  
  18. * 上傳小文件,把文件數據先讀入內存  
  19. * @param filname  
  20. * @param data  
  21. * @param parameterName  
  22. * @param contentType  
  23. */    
  24. public FormFile(String filname, byte[] data, String parameterName, String contentType)     
  25. {    
  26. this.data = data;    
  27. this.filname = filname;    
  28. this.parameterName = parameterName;    
  29. if(contentType!=null) this.contentType = contentType;    
  30. }    
  31. /**  
  32. * 上傳大文件,一邊讀文件數據一邊上傳  
  33. * @param filname  
  34. * @param file  
  35. * @param parameterName  
  36. * @param contentType  
  37. */    
  38. public FormFile(String filname, File file, String parameterName, String contentType)     
  39. {    
  40. this.filname = filname;    
  41. this.parameterName = parameterName;    
  42. this.file = file;    
  43. try     
  44. {    
  45. this.inStream = new FileInputStream(file);    
  46. }    
  47. catch (FileNotFoundException e)     
  48. {    
  49. e.printStackTrace();    
  50. }    
  51. if(contentType!=null) this.contentType = contentType;    
  52. }    
  53. public File getFile()     
  54. {    
  55. return file;    
  56. }    
  57. public InputStream getInStream()     
  58. {    
  59. return inStream;    
  60. }    
  61. public byte[] getData()     
  62. {    
  63. return data;    
  64. }    
  65. public String getFilname()     
  66. {    
  67. return filname;    
  68. }    
  69. public void setFilname(String filname)    
  70. {    
  71. this.filname = filname;    
  72. }    
  73. public String getParameterName()     
  74. {    
  75. return parameterName;    
  76. }    
  77. public void setParameterName(String parameterName)     
  78. {    
  79. this.parameterName = parameterName;    
  80. }    
  81. public String getContentType()    
  82. {    
  83. return contentType;    
  84. }    
  85. public void setContentType(String contentType)     
  86. {    
  87. this.contentType = contentType;    
  88. }       
  89. }    

 

9[java] view plaincopy

  1. 對於Android流量統計來講在2.2版中新加入了TrafficStats類能夠輕鬆獲取,其實自己TrafficStats類也是讀取Linux提供的文件對象系統類型的文本進行解析。android.net.TrafficStats類中,提供了多種靜態方法,能夠直接調用獲取,返回類型均爲 long型,若是返回等於-1表明 UNSUPPORTED 當前設備不支持統計。   
  2. Java代碼    
  3. static long  getMobileRxBytes()  //獲取經過Mobile鏈接收到的字節總數,不包含WiFi    
  4. static long  getMobileRxPackets()  //獲取Mobile鏈接收到的數據包總數    
  5. static long  getMobileTxBytes()  //Mobile發送的總字節數    
  6. static long  getMobileTxPackets()  //Mobile發送的總數據包數    
  7. static long  getTotalRxBytes()  //獲取總的接受字節數,包含Mobile和WiFi等    
  8. static long  getTotalRxPackets()  //總的接受數據包數,包含Mobile和WiFi等    
  9. static long  getTotalTxBytes()  //總的發送字節數,包含Mobile和WiFi等    
  10. static long  getTotalTxPackets()  //發送的總數據包數,包含Mobile和WiFi等     
  11. static long  getUidRxBytes(int uid)  //獲取某個網絡UID的接受字節數    
  12. static long  getUidTxBytes(int uid) //獲取某個網絡UID的發送字節數     
  13. 總接受流量TrafficStats.getTotalRxBytes(),   
  14. 總髮送流量TrafficStats.getTotalTxBytes());   
  15. 不包含WIFI的手機GPRS接收量TrafficStats.getMobileRxBytes());   
  16. 不包含Wifi的手機GPRS發送量TrafficStats.getMobileTxBytes());   
  17. 某一個進程的總接收量TrafficStats.getUidRxBytes(Uid));   
  18. 某一個進程的總髮送量TrafficStats.getUidTxBytes(Uid));   
  19. 這些都是從第一次啓動程序到最後一次啓動的統計量。並非這篇文章裏所說的「從本次開機到本次關機的統計量」!   
  20. 用法舉例,注意這裏獲得的單位都是"KB"   
  21. Java代碼    
  22. public long getTotalRxBytes(){  //獲取總的接受字節數,包含Mobile和WiFi等    
  23. return TrafficStats.getTotalRxBytes()==TrafficStats.UNSUPPORTED?0:(TrafficStats.getTotalRxBytes()/1024);    
  24. }    
  25. public long getTotalTxBytes(){  //總的發送字節數,包含Mobile和WiFi等    
  26. return TrafficStats.getTotalTxBytes()==TrafficStats.UNSUPPORTED?0:(TrafficStats.getTotalTxBytes()/1024);    
  27. }    
  28. public long getMobileRxBytes(){  //獲取經過Mobile鏈接收到的字節總數,不包含WiFi    
  29. return TrafficStats.getMobileRxBytes()==TrafficStats.UNSUPPORTED?0:(TrafficStats.getMobileRxBytes()/1024);    
  30. }    

10Android開發應用程序時,若是應用程序須要訪問網絡權限,須要在 AndroidManifest.xml 中加入如下代碼<uses-permission android:name=」android.permission.INTERNET」></uses-permission>

若是不知道放在哪一個位置,那就放在</manifest>前邊好了。

一樣的若是用到其它的權限,也須要做出聲明,部分權限列表以下:

android.permission.ACCESS_CHECKIN_PROPERTIES

容許讀寫訪問」properties」表在 checkin數據庫中,改值能夠修改上傳( Allows read/write access to the 「properties」 table in the checkin database, to change values that get uploaded)

android.permission.ACCESS_COARSE_LOCATION

容許一個程序訪問CellIDWiFi熱點來獲取粗略的位置(Allows an application to access coarse (e.g., Cell-ID, WiFi) location)

android.permission.ACCESS_FINE_LOCATION

容許一個程序訪問精良位置(GPS) (Allows an application to access fine (e.g., GPS) location)

android.permission.ACCESS_LOCATION_EXTRA_COMMANDS

容許應用程序訪問額外的位置提供命令(Allows an application to access extra location provider commands)

android.permission.ACCESS_MOCK_LOCATION

容許程序建立模擬位置提供用於測試(Allows an application to create mock location providers for testing)

android.permission.ACCESS_NETWORK_STATE

容許程序訪問有關GSM網絡信息(Allows applications to access information about networks)

android.permission.ACCESS_SURFACE_FLINGER

容許程序使用SurfaceFlinger底層特性 (Allows an application to use SurfaceFlinger’s low level features)

android.permission.ACCESS_WIFI_STATE

容許程序訪問Wi-Fi網絡狀態信息(Allows applications to access information about Wi-Fi networks)

android.permission.ADD_SYSTEM_SERVICE

容許程序發佈系統級服務(Allows an application to publish system-level services).

android.permission.BATTERY_STATS

容許程序更新手機電池統計信息(Allows an application to update the collected battery statistics)

android.permission.BLUETOOTH

容許程序鏈接到已配對的藍牙設備(Allows applications to connect to paired bluetooth devices)

11不說廢話,直接說說實現android定位有關的API吧。

這些API都在android.location包下,一共有三個接口和八個類。它們配合使用便可實現定位功能。

三個接口:

GpsStatus.Listener:這是一個當GPS狀態發生改變時,用來接收通知的接口。

GpsStatus.NmeaListener:這是一個用來從GPS裏接收Nmea-0183(爲海用電子設備制定的標準格式)信息的接口。

LocationListener:位置監聽器,用於接收當位置信息發生改變時從LocationManager接收通知的接口。

八個類:

Address:描述地址的類,好比:北京天安門

Criteria:用於描述Location Provider標準的類,標準包括位置精度水平,電量消耗水平,是否獲取海拔、方位信息,是否容許接收付費服務。

GeoCoder:用於處理地理位置的編碼。

GpsSatellite:和GpsStatus聯合使用,用於描述當前GPS衛星的狀態。

GpsStatus:和GpsStatus.Listener聯合使用,用於描述當前GPS衛星的狀態。

Location:用於描述位置信息。

LocationManager:經過此類獲取和調用系統位置服務

LocationProvider:用於描述Location Provider的抽象超類,一個LocationProvider應該可以週期性的報告當前設備的位置信息。

這裏經過一個示例代碼來演示一下android定位

首先,在AndroidManifest.xml清單文件裏須要加入ACCESS_FINE_LOCATION權限:

?

1

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>

其次,實現代碼以下:

?

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

package com.test;

 

import java.io.IOException;

import java.util.List;

 

import android.app.Activity;

import android.location.Address;

import android.location.Criteria;

import android.location.Geocoder;

import android.location.Location;

import android.location.LocationListener;

import android.location.LocationManager;

import android.os.Bundle;

import android.util.Log;

import android.widget.Toast;

 

public class PositionActivity extends Activity {

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        // 獲取到LocationManager對象

        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

        // 建立一個Criteria對象

        Criteria criteria = new Criteria();

        // 設置粗略精確度

        criteria.setAccuracy(Criteria.ACCURACY_COARSE);

        // 設置是否須要返回海拔信息

        criteria.setAltitudeRequired(false);

        // 設置是否須要返回方位信息

        criteria.setBearingRequired(false);

        // 設置是否容許付費服務

        criteria.setCostAllowed(true);

        // 設置電量消耗等級

        criteria.setPowerRequirement(Criteria.POWER_HIGH);

        // 設置是否須要返回速度信息

        criteria.setSpeedRequired(false);

        // 根據設置的Criteria對象,獲取最符合此標準的provider對象 41

        String currentProvider = locationManager

                .getBestProvider(criteria, true);

        Log.d("Location", "currentProvider: " + currentProvider);

        // 根據當前provider對象獲取最後一次位置信息 44

        Location currentLocation = locationManager

                .getLastKnownLocation(currentProvider);

        // 若是位置信息爲null,則請求更新位置信息 46

        if (currentLocation == null) {

            locationManager.requestLocationUpdates(currentProvider, 0, 0,

                    locationListener);

        }

        // 直到得到最後一次位置信息爲止,若是未得到最後一次位置信息,則顯示默認經緯度 50

        // 每隔10秒獲取一次位置信息 51

        while (true) {

            currentLocation = locationManager

                    .getLastKnownLocation(currentProvider);

            if (currentLocation != null) {

                Log.d("Location", "Latitude: " + currentLocation.getLatitude());

                Log.d("Location", "location: " + currentLocation.getLongitude());

                break;

            } else {

                Log.d("Location", "Latitude: " + 0);

                Log.d("Location", "location: " + 0);

            }

            try {

                Thread.sleep(10000);

            } catch (InterruptedException e) {

                Log.e("Location", e.getMessage());

            }

        }

        // 解析地址並顯示 69

        Geocoder geoCoder = new Geocoder(this);

        try {

            int latitude = (int) currentLocation.getLatitude();

            int longitude = (int) currentLocation.getLongitude();

            List<Address> list = geoCoder.getFromLocation(latitude, longitude,

                    2);

            for (int i = 0; i < list.size(); i++) {

                Address address = list.get(i);

                Toast.makeText(

                        PositionActivity.this,

                        address.getCountryName() + address.getAdminArea()

                                + address.getFeatureName(), Toast.LENGTH_LONG)

                        .show();

            }

        } catch (IOException e) {

            Toast.makeText(PositionActivity.this, e.getMessage(),

                    Toast.LENGTH_LONG).show();

        }

    }

    // 建立位置監聽器 85

    private LocationListener locationListener = new LocationListener() {

        // 位置發生改變時調用 87

        @Override

        public void onLocationChanged(Location location) {

            Log.d("Location", "onLocationChanged");

            Log.d("Location",

                    "onLocationChanged Latitude" + location.getLatitude());

            Log.d("Location",

                    "onLocationChanged location" + location.getLongitude());

        }

 

        // provider失效時調用 95

        @Override

        public void onProviderDisabled(String provider) {

            Log.d("Location", "onProviderDisabled");

        }

 

        // provider啓用時調用101

        @Override

        public void onProviderEnabled(String provider) {

            Log.d("Location", "onProviderEnabled");

        }

 

        // 狀態改變時調用107

        @Override

        public void onStatusChanged(String provider, int status, Bundle extras) {

            Log.d("Location", "onStatusChanged");

        }

    };

}

因爲代碼裏的Criteria對象對位置精度要求並不高,因此通常會返回「network」做爲provider,而基於network的定位每每會存在必定的位置誤差,這對於須要精肯定位的應用程序來講,顯然不合要求。這時,須要則須要用到基於GPS的定位方法了

12在前文Android定位功能(一)中,已經大體介紹了一下在Android平臺中,和定位功能相關的類,並舉例獲取了位置信息。可是前文是基於Criteria定製了一個標準,經過getBestProvider()方法由Android系統自動獲取最符合CriteriaLocationProvider,從而實現了定位功能。這樣的作法能最大限度的保證定位功能的可實現性,可是卻沒法保證獲取到的位置信息有最大的準確度。由於除了GPS外,其餘定位方式都或多或少存在着位置偏移。

在實現GPS定位前,先了解一下GPS的部分特性:

1GPS定位須要依靠3顆或以上的衛星。

2GPS定位受環境影響較大,在晴朗的空地上,較容易搜索到衛星,而在室內一般是沒法搜索到衛星的。

3GPS定位須要使用GPS功能模塊,而GPS功能模塊的耗電量是巨大的。

Android系統中,實現GPS定位的思路大體是:

1、獲取GPSLocation Provider

2、將此Provider傳入到requestLocationUpdates()方法,讓Android系統獲知搜索位置方式。

3、建立實現了GpsStatus.Listener接口的對象,重寫onGpsStatusChanged()方法,向LocationManager添加次監聽器,檢測衛星狀態。(可選步驟)

根據以上思路,仿照Android定位功能(一)中的例子,能夠很容易的獲得如下實現代碼:(此代碼的實現前提是GPS功能模塊處於打開狀態)

?

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

public class MainActivity extends Activity {

    private LocationManager locationManager;

    private GpsStatus gpsstatus;

 

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

 

        // 獲取到LocationManager對象

        locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

 

        // 根據設置的Criteria對象,獲取最符合此標準的provider對象

        String currentProvider = locationManager.getProvider(

                LocationManager.GPS_PROVIDER).getName();

 

        // 根據當前provider對象獲取最後一次位置信息

        Location currentLocation = locationManager

                .getLastKnownLocation(currentProvider);

        // 若是位置信息爲null,則請求更新位置信息

        if (currentLocation == null) {

            locationManager.requestLocationUpdates(currentProvider, 0, 0,

                    locationListener);

        }

        // 增長GPS狀態監聽器

        locationManager.addGpsStatusListener(gpsListener);

 

        // 直到得到最後一次位置信息爲止,若是未得到最後一次位置信息,則顯示默認經緯度

        // 每隔10秒獲取一次位置信息

        while (true) {

            currentLocation = locationManager

                    .getLastKnownLocation(currentProvider);

            if (currentLocation != null) {

                Log.d("Location", "Latitude: " + currentLocation.getLatitude());

                Log.d("Location", "location: " + currentLocation.getLongitude());

                break;

            } else {

                Log.d("Location", "Latitude: " + 0);

                Log.d("Location", "location: " + 0);

            }

            try {

                Thread.sleep(10000);

            } catch (InterruptedException e) {

                Log.e("Location", e.getMessage());

            }

        }

    }

 

    private GpsStatus.Listener gpsListener = new GpsStatus.Listener() {

        // GPS狀態發生變化時觸發

        @Override

        public void onGpsStatusChanged(int event) {

            // 獲取當前狀態

            gpsstatus = locationManager.getGpsStatus(null);

            switch (event) {

            // 第一次定位時的事件

            case GpsStatus.GPS_EVENT_FIRST_FIX:

                break;

            // 開始定位的事件

            case GpsStatus.GPS_EVENT_STARTED:

                break;

            // 發送GPS衛星狀態事件

            case GpsStatus.GPS_EVENT_SATELLITE_STATUS:

                Toast.makeText(MainActivity.this,"GPS_EVENT_SATELLITE_STATUS",

                        Toast.LENGTH_SHORT).show();

                Iterable<GpsSatellite> allSatellites = gpsstatus

                        .getSatellites();

                Iterator<GpsSatellite> it = allSatellites.iterator();

                int count = 0;

                while (it.hasNext()) {

                    count++;

                }

                Toast.makeText(MainActivity.this, "Satellite Count:" + count,

                        Toast.LENGTH_SHORT).show();

                break;

            // 中止定位事件

            case GpsStatus.GPS_EVENT_STOPPED:

                Log.d("Location", "GPS_EVENT_STOPPED");

                break;

            }

        }

    };

 

    // 建立位置監聽器

    private LocationListener locationListener = new LocationListener() {

        // 位置發生改變時調用

        @Override

        public void onLocationChanged(Location location) {

            Log.d("Location", "onLocationChanged");

        }

 

        // provider失效時調用

        @Override

        public void onProviderDisabled(String provider) {

            Log.d("Location", "onProviderDisabled");

        }

 

        // provider啓用時調用

        @Override

        public void onProviderEnabled(String provider) {

            Log.d("Location", "onProviderEnabled");

        }

 

        // 狀態改變時調用

        @Override

        public void onStatusChanged(String provider, int status, Bundle extras) {

            Log.d("Location", "onStatusChanged");

        }

    };

}

13[java] view plaincopy

  1. package wizzer.cn.app;  
  2. public class SecBase64 {  
  3. private static final byte[] encodingTable = { (byte) 'A', (byte) 'B',  
  4. (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G',  
  5. (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L',  
  6. (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', (byte) 'Q',  
  7. (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V',  
  8. (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'a',  
  9. (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f',  
  10. (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k',  
  11. (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p',  
  12. (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u',  
  13. (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z',  
  14. (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4',  
  15. (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9',  
  16. (byte) '+', (byte) '/' };  
  17. private static final byte[] decodingTable;  
  18. static {  
  19. decodingTable = new byte[128];  
  20. for (int i = 0; i < 128; i++) {  
  21. decodingTable[i] = (byte) -1;  
  22. }  
  23. for (int i = 'A'; i <= 'Z'; i++) {  
  24. decodingTable[i] = (byte) (i - 'A');  
  25. }  
  26. for (int i = 'a'; i <= 'z'; i++) {  
  27. decodingTable[i] = (byte) (i - 'a' + 26);  
  28. }  
  29. for (int i = '0'; i <= '9'; i++) {  
  30. decodingTable[i] = (byte) (i - '0' + 52);  
  31. }  
  32. decodingTable['+'] = 62;  
  33. decodingTable['/'] = 63;  
  34. }  
  35. // 加密  
  36. public static byte[] encode(byte[] data) {  
  37. byte[] bytes;  
  38. int modulus = data.length % 3;  
  39. if (modulus == 0) {  
  40. bytes = new byte[(4 * data.length) / 3];  
  41. } else {  
  42. bytes = new byte[4 * ((data.length / 3) + 1)];  
  43. }  
  44. int dataLength = (data.length - modulus);  
  45. int a1;  
  46. int a2;  
  47. int a3;  
  48. for (int i = 0, j = 0; i < dataLength; i += 3, j += 4) {  
  49. a1 = data[i] & 0xff;  
  50. a2 = data[i + 1] & 0xff;  
  51. a3 = data[i + 2] & 0xff;  
  52. bytes[j] = encodingTable[(a1 >>> 2) & 0x3f];  
  53. bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f];  
  54. bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f];  
  55. bytes[j + 3] = encodingTable[a3 & 0x3f];  
  56. }  
  57. int b1;  
  58. int b2;  
  59. int b3;  
  60. int d1;  
  61. int d2;  
  62. switch (modulus) {  
  63. case 0:  
  64. break;  
  65. case 1:  
  66. d1 = data[data.length - 1] & 0xff;  
  67. b1 = (d1 >>> 2) & 0x3f;  
  68. b2 = (d1 << 4) & 0x3f;  
  69. bytes[bytes.length - 4] = encodingTable[b1];  
  70. bytes[bytes.length - 3] = encodingTable[b2];  
  71. bytes[bytes.length - 2] = (byte) '=';  
  72. bytes[bytes.length - 1] = (byte) '=';  
  73. break;  
  74. case 2:  
  75. d1 = data[data.length - 2] & 0xff;  
  76. d2 = data[data.length - 1] & 0xff;  
  77. b1 = (d1 >>> 2) & 0x3f;  
  78. b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;  
  79. b3 = (d2 << 2) & 0x3f;  
  80. bytes[bytes.length - 4] = encodingTable[b1];  
  81. bytes[bytes.length - 3] = encodingTable[b2];  
  82. bytes[bytes.length - 2] = encodingTable[b3];  
  83. bytes[bytes.length - 1] = (byte) '=';  
  84. break;  
  85. }  
  86. return bytes;  
  87. }  
  88. // 解密  
  89. public static byte[] decode(byte[] data) {  
  90. byte[] bytes;  
  91. byte b1;  
  92. byte b2;  
  93. byte b3;  
  94. byte b4;  
  95. data = discardNonBase64Bytes(data);  
  96. if (data[data.length - 2] == '=') {  
  97. bytes = new byte[(((data.length / 4) - 1) * 3) + 1];  
  98. } else if (data[data.length - 1] == '=') {  
  99. bytes = new byte[(((data.length / 4) - 1) * 3) + 2];  
  100. } else {  
  101. bytes = new byte[((data.length / 4) * 3)];  
  102. }  
  103. for (int i = 0, j = 0; i < (data.length - 4); i += 4, j += 3) {  
  104. b1 = decodingTable[data[i]];  
  105. b2 = decodingTable[data[i + 1]];  
  106. b3 = decodingTable[data[i + 2]];  
  107. b4 = decodingTable[data[i + 3]];  
  108. bytes[j] = (byte) ((b1 << 2) | (b2 >> 4));  
  109. bytes[j + 1] = (byte) ((b2 << 4) | (b3 >> 2));  
  110. bytes[j + 2] = (byte) ((b3 << 6) | b4);  
  111. }  
  112. if (data[data.length - 2] == '=') {  
  113. b1 = decodingTable[data[data.length - 4]];  
  114. b2 = decodingTable[data[data.length - 3]];  
  115. bytes[bytes.length - 1] = (byte) ((b1 << 2) | (b2 >> 4));  
  116. } else if (data[data.length - 1] == '=') {  
  117. b1 = decodingTable[data[data.length - 4]];  
  118. b2 = decodingTable[data[data.length - 3]];  
  119. b3 = decodingTable[data[data.length - 2]];  
  120. bytes[bytes.length - 2] = (byte) ((b1 << 2) | (b2 >> 4));  
  121. bytes[bytes.length - 1] = (byte) ((b2 << 4) | (b3 >> 2));  
  122. } else {  
  123. b1 = decodingTable[data[data.length - 4]];  
  124. b2 = decodingTable[data[data.length - 3]];  
  125. b3 = decodingTable[data[data.length - 2]];  
  126. b4 = decodingTable[data[data.length - 1]];  
  127. bytes[bytes.length - 3] = (byte) ((b1 << 2) | (b2 >> 4));  
  128. bytes[bytes.length - 2] = (byte) ((b2 << 4) | (b3 >> 2));  
  129. bytes[bytes.length - 1] = (byte) ((b3 << 6) | b4);  
  130. }  
  131. return bytes;  
  132. }  
  133. // 解密  
  134. public static byte[] decode(String data) {  
  135. byte[] bytes;  
  136. byte b1;  
  137. byte b2;  
  138. byte b3;  
  139. byte b4;  
  140. data = discardNonBase64Chars(data);  
  141. if (data.charAt(data.length() - 2) == '=') {  
  142. bytes = new byte[(((data.length() / 4) - 1) * 3) + 1];  
  143. } else if (data.charAt(data.length() - 1) == '=') {  
  144. bytes = new byte[(((data.length() / 4) - 1) * 3) + 2];  
  145. } else {  
  146. bytes = new byte[((data.length() / 4) * 3)];  
  147. }  
  148. for (int i = 0, j = 0; i < (data.length() - 4); i += 4, j += 3) {  
  149. b1 = decodingTable[data.charAt(i)];  
  150. b2 = decodingTable[data.charAt(i + 1)];  
  151. b3 = decodingTable[data.charAt(i + 2)];  
  152. b4 = decodingTable[data.charAt(i + 3)];  
  153. bytes[j] = (byte) ((b1 << 2) | (b2 >> 4));  
  154. bytes[j + 1] = (byte) ((b2 << 4) | (b3 >> 2));  
  155. bytes[j + 2] = (byte) ((b3 << 6) | b4);  
  156. }  
  157. if (data.charAt(data.length() - 2) == '=') {  
  158. b1 = decodingTable[data.charAt(data.length() - 4)];  
  159. b2 = decodingTable[data.charAt(data.length() - 3)];  
  160. bytes[bytes.length - 1] = (byte) ((b1 << 2) | (b2 >> 4));  
  161. } else if (data.charAt(data.length() - 1) == '=') {  
  162. b1 = decodingTable[data.charAt(data.length() - 4)];  
  163. b2 = decodingTable[data.charAt(data.length() - 3)];  
  164. b3 = decodingTable[data.charAt(data.length() - 2)];  
  165. bytes[bytes.length - 2] = (byte) ((b1 << 2) | (b2 >> 4));  
  166. bytes[bytes.length - 1] = (byte) ((b2 << 4) | (b3 >> 2));  
  167. } else {  
  168. b1 = decodingTable[data.charAt(data.length() - 4)];  
  169. b2 = decodingTable[data.charAt(data.length() - 3)];  
  170. b3 = decodingTable[data.charAt(data.length() - 2)];  
  171. b4 = decodingTable[data.charAt(data.length() - 1)];  
  172. bytes[bytes.length - 3] = (byte) ((b1 << 2) | (b2 >> 4));  
  173. bytes[bytes.length - 2] = (byte) ((b2 << 4) | (b3 >> 2));  
  174. bytes[bytes.length - 1] = (byte) ((b3 << 6) | b4);  
  175. }  
  176. return bytes;  
  177. }  
  178. private static byte[] discardNonBase64Bytes(byte[] data) {  
  179. byte[] temp = new byte[data.length];  
  180. int bytesCopied = 0;  
  181. for (int i = 0; i < data.length; i++) {  
  182. if (isValidBase64Byte(data[i])) {  
  183. temp[bytesCopied++] = data[i];  
  184. }  
  185. }  
  186. byte[] newData = new byte[bytesCopied];  
  187. System.arraycopy(temp, 0, newData, 0, bytesCopied);  
  188. return newData;  
  189. }  
  190. private static String discardNonBase64Chars(String data) {  
  191. StringBuffer sb = new StringBuffer();  
  192. int length = data.length();  
  193. for (int i = 0; i < length; i++) {  
  194. if (isValidBase64Byte((byte) (data.charAt(i)))) {  
  195. sb.append(data.charAt(i));  
  196. }  
  197. }  
  198. return sb.toString();  
  199. }  
  200. private static boolean isValidBase64Byte(byte b) {  
  201. if (b == '=') {  
  202. return true;  
  203. } else if ((b < 0) || (b >= 128)) {  
  204. return false;  
  205. } else if (decodingTable[b] == -1) {  
  206. return false;  
  207. }  
  208. return true;  
  209. }  
  210. // 測試類  
  211. public static void main(String[] args) {  
  212. String data = "wizzer@qq.com:etpass";  
  213. byte[] result = SecBase64.encode(data.getBytes());// 加密  
  214. System.out.println("Basic " + data);  
  215. System.out.println("Basic " + new String(result));  
  216. System.out.println(new String(SecBase64.decode(new String(result))));// 解密  
  217. }  
  218. }  

14登錄頁面輸入用戶名和密碼,登錄成功後跳轉到主頁面,失敗時顯示錯誤信息。

 

傳遞參數時用BasicNameValuePair的List以httpPost.setEntity的方式來作,不能用HttpParams。

 

[java] view plaincopy

  1. userName = (EditText) this.findViewById(R.id.editTextUserName);    
  2. password = (EditText) this.findViewById(R.id.editTextPassword);    
  3. errorMsg = (TextView) this.findViewById(R.id.textViewLoginMsg);    
  4. Button loginBtn = (Button) this.findViewById(R.id.btnLogin);    
  5. loginBtn.setOnClickListener(new OnClickListener() {    
  6. @Override    
  7. public void onClick(View arg0) {    
  8. String result;    
  9. /* 發送部分 */    
  10. try {    
  11. HttpClient httpClient = new DefaultHttpClient();    
  12. String address = strUrl;    
  13. HttpPost httpPost = new HttpPost(address);    
  14. List<BasicNameValuePair> params = new LinkedList<BasicNameValuePair>();    
  15. params.add(new BasicNameValuePair("username", userName.getText().toString()));    
  16. params.add(new BasicNameValuePair("password", password.getText().toString()));    
  17. httpPost.setEntity(new UrlEncodedFormEntity(params, "utf-8")); //將參數填入POST Entity中    
  18. HttpResponse httpResponse = httpClient.execute(httpPost);    
  19. /* 接收 */    
  20. if (httpResponse.getStatusLine().getStatusCode() == 200) {    
  21. result = EntityUtils.toString(httpResponse.getEntity());    
  22. /* json文本解析 */    
  23. JSONTokener jsonParser = new JSONTokener(result);    
  24. JSONObject jsonResult = (JSONObject) jsonParser.nextValue();    
  25. String status = jsonResult.getString("loginStatus");    
  26. String outMessage = jsonResult.getString("outMessage");    
  27. if(status.equals("true")){    
  28. Intent i = new Intent(LoginActivity.this, MainActivity.class);    
  29. i.putExtra("username", outMessage);    
  30. startActivityForResult(i, FIRST_REQUEST_CODE);    
  31. } else {    
  32. errorMsg.setVisibility(View.VISIBLE);    
  33. errorMsg.setText(outMessage);    
  34. }    
  35. } else {    
  36. errorMsg.setVisibility(View.VISIBLE);    
  37. errorMsg.setText("網絡鏈接問題。CODE:" + httpResponse.getStatusLine().getStatusCode());    
  38. }    
  39. } catch (JSONException e) {    
  40. e.printStackTrace();    
  41. } catch (UnsupportedEncodingException e) {    
  42. e.printStackTrace();    
  43. } catch (ClientProtocolException e) {    
  44. e.printStackTrace();    
  45. } catch (IOException e) {    
  46. e.printStackTrace();    
  47. }    
  48. }    
  49. });    

 

15Android  Http JSon服務器端和客戶端通訊 
 服務器端: 

[java] view plaincopy

  1. package com.web.servlet;  
  2. import java.io.IOException;  
  3. import java.io.PrintWriter;  
  4. import java.util.ArrayList;  
  5. import java.util.Iterator;  
  6. import java.util.List;  
  7. import javax.servlet.ServletException;  
  8. import javax.servlet.http.HttpServlet;  
  9. import javax.servlet.http.HttpServletRequest;  
  10. import javax.servlet.http.HttpServletResponse;  
  11. import net.sf.json.JSONArray;  
  12. import net.sf.json.JSONObject;  
  13. import com.web.model.User;  
  14. public class JSONServlet extends HttpServlet {  
  15. /** 
  16. * Constructor of the object. 
  17. */  
  18. public JSONServlet() {  
  19. super();  
  20. }  
  21. /** 
  22. * Destruction of the servlet. <br> 
  23. */  
  24. public void destroy() {  
  25. super.destroy(); // Just puts "destroy" string in log  
  26. // Put your code here  
  27. }  
  28. /** 
  29. * The doGet method of the servlet. <br> 
  30. * This method is called when a form has its tag value method equals to get. 
  31. *  
  32. * @param request the request send by the client to the server 
  33. * @param response the response send by the server to the client 
  34. * @throws ServletException if an error occurred 
  35. * @throws IOException if an error occurred 
  36. */  
  37. public void doGet(HttpServletRequest request, HttpServletResponse response)  
  38. throws ServletException, IOException {  
  39. doPost(request, response);  
  40. }  
  41. /** 
  42. * The doPost method of the servlet. <br> 
  43. * This method is called when a form has its tag value method equals to post. 
  44. *  
  45. * @param request the request send by the client to the server 
  46. * @param response the response send by the server to the client 
  47. * @throws ServletException if an error occurred 
  48. * @throws IOException if an error occurred 
  49. */  
  50. public void doPost(HttpServletRequest request, HttpServletResponse response)  
  51. throws ServletException, IOException {  
  52. response.setContentType("text/html");  
  53. PrintWriter out = response.getWriter();  
  54. List<User> list = new ArrayList<User>();  
  55. User u1 = new User();  
  56. u1.setId(111);  
  57. u1.setUsername("zhang shan");  
  58. u1.setPassword("zs");  
  59. User u2 = new User();  
  60. u2.setId(222);  
  61. u2.setUsername("li si");  
  62. u2.setPassword("ls");  
  63. User u3 = new User();  
  64. u3.setId(333);  
  65. u3.setUsername("wang wu");  
  66. u3.setPassword("ww");  
  67. list.add(u1);  
  68. list.add(u2);  
  69. list.add(u3);  
  70. JSONArray ja = new JSONArray();  
  71. for (Iterator iterator = list.iterator(); iterator.hasNext();) {  
  72. User user = (User) iterator.next();  
  73. JSONObject jobj= new JSONObject();  
  74. jobj.put("id", user.getId());  
  75. jobj.put("username", user.getUsername());  
  76. jobj.put("password", user.getPassword());  
  77. ja.add(jobj);  
  78. }  
  79. out.write(ja.toString());     
  80. out.flush();     
  81. out.close();   
  82. }  
  83. /** 
  84. * Initialization of the servlet. <br> 
  85. * @throws ServletException if an error occurs 
  86. */  
  87. public void init() throws ServletException {  
  88. // Put your code here  
  89. }  
  90. }  

[java] view plaincopy

[java] view plaincopy

  1. 手機端:  

[java] view plaincopy

  1. package com.web.activity;  
  2. import java.io.BufferedInputStream;  
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.InputStreamReader;  
  7. import java.io.ObjectInputStream;  
  8. import java.io.UnsupportedEncodingException;  
  9. import java.util.ArrayList;  
  10. import java.util.Iterator;  
  11. import java.util.List;  
  12. import org.apache.commons.httpclient.Cookie;  
  13. import org.apache.commons.httpclient.HttpException;  
  14. import org.apache.commons.httpclient.HttpStatus;  
  15. import org.apache.commons.httpclient.NameValuePair;  
  16. import org.apache.commons.httpclient.methods.PostMethod;   
  17. import org.apache.http.HttpEntity;  
  18. import org.apache.http.HttpResponse;  
  19. import org.apache.http.client.ClientProtocolException;   
  20. import org.apache.http.client.HttpClient;  
  21. import org.apache.http.client.entity.UrlEncodedFormEntity;  
  22. import org.apache.http.client.methods.HttpGet;  
  23. import org.apache.http.client.methods.HttpPost;  
  24. import org.apache.http.client.methods.HttpUriRequest;  
  25. import org.apache.http.entity.StringEntity;  
  26. import org.apache.http.impl.client.DefaultHttpClient;  
  27. import org.apache.http.message.BasicNameValuePair;  
  28. import org.apache.http.params.HttpConnectionParams;  
  29. import org.apache.http.params.HttpParams;  
  30. import org.apache.http.protocol.HTTP;  
  31. import org.json.JSONArray;  
  32. import org.json.JSONException;  
  33. import org.json.JSONObject;  
  34. import com.web.model.User;  
  35. import android.app.Activity;  
  36. import android.os.Bundle;  
  37. import android.util.Log;  
  38. import android.view.View;  
  39. import android.view.View.OnClickListener;  
  40. import android.widget.Button;  
  41. import android.widget.EditText;  
  42. import android.widget.TextView;  
  43. public class WebclientActivity extends Activity {   
  44. private TextView hello;    
  45. @Override  
  46. public void onCreate(Bundle savedInstanceState) {  
  47. super.onCreate(savedInstanceState);  
  48. setContentView(R.layout.main);    
  49. HttpClient httpclient = new DefaultHttpClient();  
  50. String uri="http://10.11.72.108:8086/web/JSONServlet";  
  51. HttpPost httpReqest = new HttpPost(uri);     
  52. try {    
  53. HttpResponse response = httpclient.execute(httpReqest);     
  54. HttpEntity entity = response.getEntity();   
  55. BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()));   
  56. StringBuffer sb = new StringBuffer();       
  57. String line = null;  
  58. while ((line = reader.readLine()) != null) {  
  59. sb.append(line + "\n");  
  60. }  
  61. reader.close();   
  62. JSONArray ja = new JSONArray(sb.toString());  
  63. StringBuffer sb2 = new StringBuffer();  
  64. for (int i = 0; i < ja.length(); i++) {  
  65. JSONObject jobj= (JSONObject)ja.get(i);  
  66. sb2.append("id:").append(jobj.getInt("id")).append(" ");  
  67. sb2.append("用戶:").append(jobj.getString("username")).append(" ");  
  68. sb2.append("密碼:").append(jobj.getString("password")).append("\r\n");  
  69. }  
  70. TextView hello = (TextView) findViewById(R.id.helloid);  
  71. hello.setText(sb2.toString());  
  72. } catch (Exception e) {   
  73. Log.i("uuu", e.toString());  
  74. }    
  75. }   
  76. }  

 

16咱們編寫的是AndoridHTTP協議多線程斷點下載應用程序。直接使用單線程下載HTTP文件對咱們來講是一件很是簡單的事。那麼,多線程斷點須要什麼功能?

1.多線程下載,

2.支持斷點。

 

使用多線程的好處:使用多線程下載會提高文件下載的速度。那麼多線程下載文件的過程是: 

   (1)首先得到下載文件的長度,而後設置本地文件的長度。

       HttpURLConnection.getContentLength();//獲取下載文件的長度

      RandomAccessFile file = new RandomAccessFile("QQWubiSetup.exe","rwd");

        file.setLength(filesize);//設置本地文件的長度

 

  (2)根據文件長度和線程數計算每條線程下載的數據長度和下載位置。

      如:文件的長度爲6M,線程數爲3,那麼,每條線程下載的數據長度爲2M,每條線程開始下載的位置以下圖所示。

  

   例如10M大小,使用3個線程來下載,

        線程下載的數據長度   (10%3 == 0 ? 10/3:10/3+1) ,12個線程下載長度是4M,第三個線程下載長度爲2M

         下載開始位置:線程id*每條線程下載的數據長度 = ?

        下載結束位置:(線程id+1*每條線程下載的數據長度-1=?

 

  (3)使用HttpRange頭字段指定每條線程從文件的什麼位置開始下載,下載到什麼位置爲止,

         如:指定從文件的2M位置開始下載,下載到位置(4M-1byte)爲止

           代碼以下:HttpURLConnection.setRequestProperty("Range", "bytes=2097152-4194303");

 

  (4)保存文件,使用RandomAccessFile類指定每條線程從本地文件的什麼位置開始寫入數據。

RandomAccessFile threadfile = new RandomAccessFile("QQWubiSetup.exe ","rwd");

threadfile.seek(2097152);//從文件的什麼位置開始寫入數據

 

  程序結構以下圖所示:

 

 

    string.xml文件中代碼:

 

 

<?xml version="1.0" encoding="utf-8"?> 

<resources>
    <string name="hello">Hello World, MainActivity!</string>
    <string name="app_name">Android網絡多線程斷點下載</string>
    <string name="path">下載路徑</string>
    <string name="downloadbutton">下載</string>
    <string name="sdcarderror">SDCard不存在或者寫保護</string>
    <string name="success">下載完成</string>
    <string name="error">下載失敗</string>
</resources>

 

 

 main.xml文件中代碼:

 

 

 <?xml version="1.0" encoding="utf-8"?>    

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"   

android:layout_width="fill_parent"    

android:layout_height="fill_parent">

    <!-- 下載路徑 -->
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/path"/>
    <EditText 
        android:id="@+id/path" 
        android:text="http://www.winrar.com.cn/download/wrar380sc.exe" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content">
    </EditText>
    <!-- 下載按鈕 -->
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/downloadbutton"
        android:id="@+id/button"/>
    <!-- 進度條 -->
    <ProgressBar
        android:layout_width="fill_parent"
        android:layout_height="20dip"
        style="?android:attr/progressBarStyleHorizontal"
        android:id="@+id/downloadbar" />
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:id="@+id/resultView" />
    </LinearLayout>

 

  

AndroidManifest.xml文件中代碼:

 

 

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"      package="com.android.downloader"      android:versionCode="1"      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".MainActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
    
    <!-- SDCard中建立與刪除文件權限 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    
    <!-- SDCard寫入數據權限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    
    <!-- 訪問internet權限 -->
    <uses-permission android:name="android.permission.INTERNET"/>

</manifest>  

 


 MainActivity中代碼:

 

 

package com.android.downloader;

import java.io.File;

import com.android.network.DownloadProgressListener;
import com.android.network.FileDownloader;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
    private EditText downloadpathText;
    private TextView resultView;
    private ProgressBar progressBar;
    
    /**
     * Handler被建立會關聯到建立它的當前線程的消息隊列,該類用於往消息隊列發送消息
     * 消息隊列中的消息由當前線程內部進行處理
     */
    private Handler handler = new Handler(){

        @Override
        public void handleMessage(Message msg) {            
            switch (msg.what) {
            case 1:                
                progressBar.setProgress(msg.getData().getInt("size"));
                float num = (float)progressBar.getProgress()/(float)progressBar.getMax();
                int result = (int)(num*100);
                resultView.setText(result+ "%");
                
                if(progressBar.getProgress()==progressBar.getMax()){
                    Toast.makeText(MainActivity.this, R.string.success, 1).show();
                }
                break;
            case -1:
                Toast.makeText(MainActivity.this, R.string.error, 1).show();
                break;
            }
        }
    };
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        downloadpathText = (EditText) this.findViewById(R.id.path);
        progressBar = (ProgressBar) this.findViewById(R.id.downloadbar);
        resultView = (TextView) this.findViewById(R.id.resultView);
        Button button = (Button) this.findViewById(R.id.button);
        
        button.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                String path = downloadpathText.getText().toString();
                System.out.println(Environment.getExternalStorageState()+"------"+Environment.MEDIA_MOUNTED);
                
                if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
                    download(path, Environment.getExternalStorageDirectory());
                }else{
                    Toast.makeText(MainActivity.this, R.string.sdcarderror, 1).show();
                }
            }
        });
    }
    
      /**
       * 主線程(UI線程)
       * 對於顯示控件的界面更新只是由UI線程負責,若是是在非UI線程更新控件的屬性值,更新後的顯示界面不會反映到屏幕上
       * @param path
       * @param savedir
       */
    private void download(final String path, final File savedir) {
        new Thread(new Runnable() {            
            @Override
            public void run() {
                FileDownloader loader = new FileDownloader(MainActivity.this, path, savedir, 3);
                progressBar.setMax(loader.getFileSize());//設置進度條的最大刻度爲文件的長度
                
                try {
                    loader.download(new DownloadProgressListener() {
                        @Override
                        public void onDownloadSize(int size) {//實時獲知文件已經下載的數據長度
                            Message msg = new Message();
                            msg.what = 1;
                            msg.getData().putInt("size", size);
                            handler.sendMessage(msg);//發送消息
                        }
                    });
                } catch (Exception e) {
                    handler.obtainMessage(-1).sendToTarget();
                }
            }
        }).start();
    }

}  

 

DBOpenHelper中代碼:

 

 

package com.android.service;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DBOpenHelper extends SQLiteOpenHelper {
    private static final String DBNAME = "down.db";
    private static final int VERSION = 1;
    
    public DBOpenHelper(Context context) {
        super(context, DBNAME, null, VERSION);
    }
    
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE IF NOT EXISTS filedownlog (id integer primary key autoincrement, downpath varchar(100), threadid INTEGER, downlength INTEGER)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS filedownlog");
        onCreate(db);
    }
}

 

    

FileService中代碼:

 

 

package com.android.service;

import java.util.HashMap;
import java.util.Map;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class FileService {
    private DBOpenHelper openHelper;

    public FileService(Context context) {
        openHelper = new DBOpenHelper(context);
    }
    
    /**
     * 獲取每條線程已經下載的文件長度
     * @param path
     * @return
     */
    public Map<Integer, Integer> getData(String path){
        SQLiteDatabase db = openHelper.getReadableDatabase();
        Cursor cursor = db.rawQuery("select threadid, downlength from filedownlog where downpath=?", new String[]{path});
        Map<Integer, Integer> data = new HashMap<Integer, Integer>();
        
        while(cursor.moveToNext()){
            data.put(cursor.getInt(0), cursor.getInt(1));
        }
        
        cursor.close();
        db.close();
        return data;
    }
    
    /**
     * 保存每條線程已經下載的文件長度
     * @param path
     * @param map
     */
    public void save(String path,  Map<Integer, Integer> map){//int threadid, int position
        SQLiteDatabase db = openHelper.getWritableDatabase();
        db.beginTransaction();
        
        try{
            for(Map.Entry<Integer, Integer> entry : map.entrySet()){
                db.execSQL("insert into filedownlog(downpath, threadid, downlength) values(?,?,?)",
                        new Object[]{path, entry.getKey(), entry.getValue()});
            }
            db.setTransactionSuccessful();
        }finally{
            db.endTransaction();
        }
        
        db.close();
    }
    
    /**
     * 實時更新每條線程已經下載的文件長度
     * @param path
     * @param map
     */
    public void update(String path, Map<Integer, Integer> map){
        SQLiteDatabase db = openHelper.getWritableDatabase();
        db.beginTransaction();
        
        try{
            for(Map.Entry<Integer, Integer> entry : map.entrySet()){
                db.execSQL("update filedownlog set downlength=? where downpath=? and threadid=?",
                        new Object[]{entry.getValue(), path, entry.getKey()});
            }
            
            db.setTransactionSuccessful();
        }finally{
            db.endTransaction();
        }
        
        db.close();
    }
    
    /**
     * 當文件下載完成後,刪除對應的下載記錄
     * @param path
     */
    public void delete(String path){
        SQLiteDatabase db = openHelper.getWritableDatabase();
        db.execSQL("delete from filedownlog where downpath=?", new Object[]{path});
        db.close();
    }

}  

 

DownloadProgressListener中代碼:

 

package com.android.network;

public interface DownloadProgressListener {
    public void onDownloadSize(int size);

}  

FileDownloader中代碼:

 

 

package com.android.network;

import java.io.File;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.android.service.FileService;

import android.content.Context;
import android.util.Log;

public class FileDownloader {
    private static final String TAG = "FileDownloader";
    private Context context;
    private FileService fileService;    
    
    /* 已下載文件長度 */
    private int downloadSize = 0;
    
    /* 原始文件長度 */
    private int fileSize = 0;
    
    /* 線程數 */
    private DownloadThread[] threads;
    
    /* 本地保存文件 */
    private File saveFile;
    
    /* 緩存各線程下載的長度*/
    private Map<Integer, Integer> data = new ConcurrentHashMap<Integer, Integer>();
    
    /* 每條線程下載的長度 */
    private int block;
    
    /* 下載路徑  */
    private String downloadUrl;
    
    /**
     * 獲取線程數
     */
    public int getThreadSize() {
        return threads.length;
    }
    
    /**
     * 獲取文件大小
     * @return
     */
    public int getFileSize() {
        return fileSize;
    }
    
    /**
     * 累計已下載大小
     * @param size
     */
    protected synchronized void append(int size) {
        downloadSize += size;
    }
    
    /**
     * 更新指定線程最後下載的位置
     * @param threadId 線程id
     * @param pos 最後下載的位置
     */
    protected synchronized void update(int threadId, int pos) {
        this.data.put(threadId, pos);
        this.fileService.update(this.downloadUrl, this.data);
    }
    
    /**
     * 構建文件下載器
     * @param downloadUrl 下載路徑
     * @param fileSaveDir 文件保存目錄
     * @param threadNum 下載線程數
     */
    public FileDownloader(Context context, String downloadUrl, File fileSaveDir, int threadNum) {
        try {
            this.context = context;
            this.downloadUrl = downloadUrl;
            fileService = new FileService(this.context);
            URL url = new URL(this.downloadUrl);
            if(!fileSaveDir.exists()) fileSaveDir.mkdirs();
            this.threads = new DownloadThread[threadNum];                    
            
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5*1000);
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
            conn.setRequestProperty("Accept-Language", "zh-CN");
            conn.setRequestProperty("Referer", downloadUrl); 
            conn.setRequestProperty("Charset", "UTF-8");
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.connect();
            printResponseHeader(conn);
            
            if (conn.getResponseCode()==200) {
                this.fileSize = conn.getContentLength();//根據響應獲取文件大小
                if (this.fileSize <= 0) throw new RuntimeException("Unkown file size ");
                        
                String filename = getFileName(conn);//獲取文件名稱
                this.saveFile = new File(fileSaveDir, filename);//構建保存文件
                Map<Integer, Integer> logdata = fileService.getData(downloadUrl);//獲取下載記錄
                
                if(logdata.size()>0){//若是存在下載記錄
                    for(Map.Entry<Integer, Integer> entry : logdata.entrySet())
                        data.put(entry.getKey(), entry.getValue());//把各條線程已經下載的數據長度放入data
                }
                
                if(this.data.size()==this.threads.length){//下面計算全部線程已經下載的數據長度
                    for (int i = 0; i < this.threads.length; i++) {
                        this.downloadSize += this.data.get(i+1);
                    }
                    
                    print("已經下載的長度"+ this.downloadSize);
                }
                
                //計算每條線程下載的數據長度
                this.block = (this.fileSize % this.threads.length)==0? this.fileSize / this.threads.length : this.fileSize / this.threads.length + 1;
            }else{
                throw new RuntimeException("server no response ");
            }
        } catch (Exception e) {
            print(e.toString());
            throw new RuntimeException("don't connection this url");
        }
    }
    
    /**
     * 獲取文件名
     * @param conn
     * @return
     */
    private String getFileName(HttpURLConnection conn) {
        String filename = this.downloadUrl.substring(this.downloadUrl.lastIndexOf('/') + 1);
        
        if(filename==null || "".equals(filename.trim())){//若是獲取不到文件名稱
            for (int i = 0;; i++) {
                String mine = conn.getHeaderField(i);
                
                if (mine == null) break;
                
                if("content-disposition".equals(conn.getHeaderFieldKey(i).toLowerCase())){
                    Matcher m = Pattern.compile(".*filename=(.*)").matcher(mine.toLowerCase());
                    if(m.find()) return m.group(1);
                }
            }
            
            filename = UUID.randomUUID()+ ".tmp";//默認取一個文件名
        }
        
        return filename;
    }
    
    /**
     *  開始下載文件
     * @param listener 監聽下載數量的變化,若是不須要了解實時下載的數量,能夠設置爲null
     * @return 已下載文件大小
     * @throws Exception
     */
    public int download(DownloadProgressListener listener) throws Exception{
        try {
            RandomAccessFile randOut = new RandomAccessFile(this.saveFile, "rw");
            if(this.fileSize>0) randOut.setLength(this.fileSize);
            randOut.close();
            URL url = new URL(this.downloadUrl);
            
            if(this.data.size() != this.threads.length){
                this.data.clear();
                
                for (int i = 0; i < this.threads.length; i++) {
                    this.data.put(i+1, 0);//初始化每條線程已經下載的數據長度爲0
                }
            }
            
            for (int i = 0; i < this.threads.length; i++) {//開啓線程進行下載
                int downLength = this.data.get(i+1);
                
                if(downLength < this.block && this.downloadSize<this.fileSize){//判斷線程是否已經完成下載,不然繼續下載    
                    this.threads[i] = new DownloadThread(this, url, this.saveFile, this.block, this.data.get(i+1), i+1);
                    this.threads[i].setPriority(7);
                    this.threads[i].start();
                }else{
                    this.threads[i] = null;
                }
            }
            
            this.fileService.save(this.downloadUrl, this.data);
            boolean notFinish = true;//下載未完成
            
            while (notFinish) {// 循環判斷全部線程是否完成下載
                Thread.sleep(900);
                notFinish = false;//假定所有線程下載完成
                
                for (int i = 0; i < this.threads.length; i++){
                    if (this.threads[i] != null && !this.threads[i].isFinish()) {//若是發現線程未完成下載
                        notFinish = true;//設置標誌爲下載沒有完成
                        
                        if(this.threads[i].getDownLength() == -1){//若是下載失敗,再從新下載
                            this.threads[i] = new DownloadThread(this, url, this.saveFile, this.block, this.data.get(i+1), i+1);
                            this.threads[i].setPriority(7);
                            this.threads[i].start();
                        }
                    }
                }    
                
                if(listener!=null) listener.onDownloadSize(this.downloadSize);//通知目前已經下載完成的數據長度
            }
            
            fileService.delete(this.downloadUrl);
        } catch (Exception e) {
            print(e.toString());
            throw new Exception("file download fail");
        }
        return this.downloadSize;
    }
    
    /**
     * 獲取Http響應頭字段
     * @param http
     * @return
     */
    public static Map<String, String> getHttpResponseHeader(HttpURLConnection http) {
        Map<String, String> header = new LinkedHashMap<String, String>();
        
        for (int i = 0;; i++) {
            String mine = http.getHeaderField(i);
            if (mine == null) break;
            header.put(http.getHeaderFieldKey(i), mine);
        }
        
        return header;
    }
    
    /**
     * 打印Http頭字段
     * @param http
     */
    public static void printResponseHeader(HttpURLConnection http){
        Map<String, String> header = getHttpResponseHeader(http);
        
        for(Map.Entry<String, String> entry : header.entrySet()){
            String key = entry.getKey()!=null ? entry.getKey()+ ":" : "";
            print(key+ entry.getValue());
        }
    }

    private static void print(String msg){
        Log.i(TAG, msg);
    }

 

DownloadThread 中代碼:

 

 

package com.android.network;

import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

import android.util.Log;

public class DownloadThread extends Thread {
    private static final String TAG = "DownloadThread";
    private File saveFile;
    private URL downUrl;
    private int block;
    
    /* 下載開始位置  */
    private int threadId = -1;    
    private int downLength;
    private boolean finish = false;
    private FileDownloader downloader;
    
    public DownloadThread(FileDownloader downloader, URL downUrl, File saveFile, int block, int downLength, int threadId) {
        this.downUrl = downUrl;
        this.saveFile = saveFile;
        this.block = block;
        this.downloader = downloader;
        this.threadId = threadId;
        this.downLength = downLength;
    }
    
    @Override
    public void run() {
        if(downLength < block){//未下載完成
            try {
                HttpURLConnection http = (HttpURLConnection) downUrl.openConnection();
                http.setConnectTimeout(5 * 1000);
                http.setRequestMethod("GET");
                http.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
                http.setRequestProperty("Accept-Language", "zh-CN");
                http.setRequestProperty("Referer", downUrl.toString()); 
                http.setRequestProperty("Charset", "UTF-8");
                int startPos = block * (threadId - 1) + downLength;//開始位置
                int endPos = block * threadId -1;//結束位置
                http.setRequestProperty("Range", "bytes=" + startPos + "-"+ endPos);//設置獲取實體數據的範圍
                http.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
                http.setRequestProperty("Connection", "Keep-Alive");
                
                InputStream inStream = http.getInputStream();
                byte[] buffer = new byte[1024];
                int offset = 0;
                print("Thread " + this.threadId + " start download from position "+ startPos);
                RandomAccessFile threadfile = new RandomAccessFile(this.saveFile, "rwd");
                threadfile.seek(startPos);
                
                while ((offset = inStream.read(buffer, 0, 1024)) != -1) {
                    threadfile.write(buffer, 0, offset);
                    downLength += offset;
                    downloader.update(this.threadId, downLength);
                    downloader.append(offset);
                }
                
                threadfile.close();
                inStream.close();
                print("Thread " + this.threadId + " download finish");
                this.finish = true;
            } catch (Exception e) {
                this.downLength = -1;
                print("Thread "+ this.threadId+ ":"+ e);
            }
        }
    }
    
    private static void print(String msg){
        Log.i(TAG, msg);
    }
    
    /**
     * 下載是否完成
     * @return
     */
    public boolean isFinish() {
        return finish;
    }
    
    /**
     * 已經下載的內容大小
     * @return 若是返回值爲-1,表明下載失敗
     */
    public long getDownLength() {
        return downLength;
    }

 

 

   運行效果以下:

 

 

 

版權聲明:本文爲博主原創文章,未經博主容許不得轉載。

17Android手機操做系統已經出現就受到了用戶的好評。各大手機廠商也開始利用這一開源的系統抓住商機,發展本身的產業。在這裏先來了解一下這一操做系統的一個小技巧,有關Android顯示網絡圖片的實現。

在Android中顯示一張網絡圖片實際上是超級簡單的,下面就一個很是簡單的例子:

Android顯示網絡圖片Step1:

一、建立你的Activity,本例中以ViewWebImageActivity說明;

二、ViewWebImageActivity中的代碼以下:

[java] view plaincopy

  1. String imageUrl = "http://hiphotos.baidu.com/baidu/pic  
  2. /item/7d8aebfebf3f9e125c6008d8.jpg";   
  3. //這就是你須要顯示的網絡圖片---網上隨便找的    
  4. Bitmap bmImg;     
  5. ImageView imView;    
  6. Button button1;     
  7. @Override     
  8. public void onCreate(Bundle savedInstanceState) {     
  9. super.onCreate(savedInstanceState);     
  10. setContentView(R.layout.main);     
  11. imView = (ImageView) findViewById(R.id.imview);     
  12. imView.setImageBitmap(returnBitMap(imageUrl));     
  13. }     
  14. public Bitmap returnBitMap(String url) {     
  15. URL myFileUrl = null;     
  16. Bitmap bitmap = null;     
  17. try {     
  18. myFileUrl = new URL(url);     
  19. } catch (MalformedURLException e) {     
  20. e.printStackTrace();     
  21. }     
  22. try {     
  23. HttpURLConnection conn = (HttpURLConnection)   
  24. myFileUrl.openConnection();     
  25. conn.setDoInput(true);     
  26. conn.connect();     
  27. InputStream is = conn.getInputStream();     
  28. bitmap = BitmapFactory.decodeStream(is);     
  29. is.close();     
  30. } catch (IOException e) {     
  31. e.printStackTrace();     
  32. }     
  33. return bitmap;     
  34. }  

 

三、其中,returnBitMap(String url) 方法就是具體實現網絡圖片轉換成bitmap。

Android顯示網絡圖片Step2:

一、修改你的main.xml文件以下:

[java] view plaincopy

  1. < ?xml version="1.0" encoding="utf-8"?>   
  2. < LinearLayout xmlns:android=  
  3. "http://schemas.android.com/apk/res/android"   
  4. android:orientation="vertical"   
  5. android:layout_width="fill_parent"   
  6. android:layout_height="fill_parent"   
  7. >   
  8. < ImageView     
  9. android:id="@+id/imview"   
  10. android:layout_width="wrap_content"     
  11. android:layout_height="wrap_content"     
  12. android:layout_gravity="center"     
  13. />     
  14. < /LinearLayout>   

 

Android顯示網絡圖片Step3:

在你的AndroidManifest.xml文件的< /manifest>節點上面添加< uses-permission android:name="android.permission.INTERNET" />,這是因爲Android有不少的權限限制,不然圖片是不能在你的模擬器上顯示的

18android

[java] view plaincopy

  1. <span style=" font-family: Arial, Tahoma, Verdana, sans-serif; font-size: 14px;">獲取網絡信息須要在AndroidManifest.xml文件中加入相應的權限。 </span>  

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 

1)判斷是否有網絡鏈接 

[java] view plaincopy

  1. public boolean isNetworkConnected(Context context) {   
  2. if (context != null) {   
  3. ConnectivityManager mConnectivityManager = (ConnectivityManager) context   
  4. .getSystemService(Context.CONNECTIVITY_SERVICE);   
  5. NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();   
  6. if (mNetworkInfo != null) {   
  7. return mNetworkInfo.isAvailable();   
  8. }   
  9. }   
  10. return false;   
  11. }   

 

2)判斷WIFI網絡是否可用 

[java] view plaincopy

  1. public boolean isWifiConnected(Context context) {   
  2. if (context != null) {   
  3. ConnectivityManager mConnectivityManager = (ConnectivityManager) context   
  4. .getSystemService(Context.CONNECTIVITY_SERVICE);   
  5. NetworkInfo mWiFiNetworkInfo = mConnectivityManager   
  6. .getNetworkInfo(ConnectivityManager.TYPE_WIFI);   
  7. if (mWiFiNetworkInfo != null) {   
  8. return mWiFiNetworkInfo.isAvailable();   
  9. }   
  10. }   
  11. return false;   
  12. }   

 

3)判斷MOBILE網絡是否可用 

[java] view plaincopy

  1. public boolean isMobileConnected(Context context) {   
  2. if (context != null) {   
  3. ConnectivityManager mConnectivityManager = (ConnectivityManager) context   
  4. .getSystemService(Context.CONNECTIVITY_SERVICE);   
  5. NetworkInfo mMobileNetworkInfo = mConnectivityManager   
  6. .getNetworkInfo(ConnectivityManager.TYPE_MOBILE);   
  7. if (mMobileNetworkInfo != null) {   
  8. return mMobileNetworkInfo.isAvailable();   
  9. }   
  10. }   
  11. return false;   
  12. }   

 

4)獲取當前網絡鏈接的類型信息 

[java] view plaincopy

  1. public static int getConnectedType(Context context) {   
  2. if (context != null) {   
  3. ConnectivityManager mConnectivityManager = (ConnectivityManager) context   
  4. .getSystemService(Context.CONNECTIVITY_SERVICE);   
  5. NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();   
  6. if (mNetworkInfo != null && mNetworkInfo.isAvailable()) {   
  7. return mNetworkInfo.getType();   
  8. }   
  9. }   
  10. return -1;   
  11. }   

 

在開發android應用時,涉及到要進行網絡訪問,時常須要進行網絡狀態的檢查,以提供給用戶必要的提醒。通常能夠經過ConnectivityManager來完成該工做。 

ConnectivityManager有四個主要任務 
1、監聽手機網絡狀態(包括GPRSWIFI, UMTS
2、手機狀態發生改變時,發送廣播 
3、當一個網絡鏈接失敗時進行故障切換 
4、爲應用程序提供能夠獲取可用網絡的高精度和粗糙的狀態 
當咱們要在程序中監聽網絡狀態時,只要一下幾個步驟便可: 

1、定義一個Receiver重載其中的onReceive函數,在其中完成所須要的功能,如根據WIFIGPRS是否斷開來改變空間的外觀 

[java] view plaincopy

  1. connectionReceiver = new BroadcastReceiver() {   
  2. @Override   
  3. public void onReceive(Context context, Intent intent) {   
  4. ConnectivityManager connectMgr = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);   
  5. NetworkInfo mobNetInfo = connectMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);   
  6. NetworkInfo wifiNetInfo = connectMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);   
  7. if (!mobNetInfo.isConnected() && !wifiNetInfo.isConnected()) {   
  8. Log.i(TAG, "unconnect");   
  9. // unconnect network   
  10. }else {   
  11. // connect network   
  12. }   
  13. }   
  14. };   

 

2、在適當的地方註冊Receiver,能夠在程序中註冊,在onCreate中調用以下函數便可: 

[java] view plaincopy

  1. IntentFilter intentFilter = new IntentFilter();   
  2. intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);   
  3. registerReceiver(connectionReceiver, intentFilter);   



3、在適當時取消註冊Receiver,能夠在程序中取消,在onDestroye中調用以下函數便可: 

[java] view plaincopy

  1. if (connectionReceiver != null) {   
  2. unregisterReceiver(connectionReceiver);   
  3. }   

 

Ps:網上還有不少關於使用TelephonyManager 的方法的,方法以下(可是我試了好幾回都有問題,如每次第一次進入一個Activity時會自動收到網絡斷開的信號,每次網絡狀態改變時收到屢次回調且狀態不正確。不知道有什麼要注意的地方,求指點!) 

[java] view plaincopy

  1. final TelephonyManager mTelephonyMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);   
  2. mTelephonyMgr.listen(new PhoneStateListener(){   
  3. @Override   
  4. public void onDataConnectionStateChanged(int state) {   
  5. switch(state){   
  6. case TelephonyManager.DATA_DISCONNECTED://網絡斷開   
  7. break;   
  8. case TelephonyManager.DATA_CONNECTING://網絡正在鏈接   
  9. break;   
  10. case TelephonyManager.DATA_CONNECTED://網絡鏈接上   
  11. break;   
  12. }   
  13. }   
  14. }, PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);   

 

至於第二種方法,本人並無去嘗試過。第一種方式仍是比較好用,若是要程序隱藏在後臺的話,建議開個service,將BroadcastReceiver註冊在service,但不要忘了取消註冊。 

在測試中遇到過這樣的情況,將一個當前鏈接wifi的路由設備關閉,可是程序並無捕捉到unconnect network,多是由於手機設備馬上鍊接另外一個路由設備了 

Android 監控網絡狀態 

[java] view plaincopy

  1. public static boolean isNetworkAvailable(Context context) {   
  2. ConnectivityManager connectivity = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);   
  3. if (connectivity == null) {   
  4. Log.i("NetWorkState", "Unavailabel");   
  5. return false;   
  6. } else {   
  7. NetworkInfo[] info = connectivity.getAllNetworkInfo();   
  8. if (info != null) {   
  9. for (int i = 0; i < info.length; i++) {   
  10. if (info[i].getState() == NetworkInfo.State.CONNECTED) {   
  11. Log.i("NetWorkState", "Availabel");   
  12. return true;   
  13. }   
  14. }   
  15. }   
  16. }   
  17. return false;   
  18. }   

 

上面這個方法就是判斷網絡是否鏈接的代碼,返回true表示有網絡,返回false表示無網絡。 在Android網絡應用程序開發中,常常要判斷網絡鏈接是否可用,所以常常有必要監聽網絡狀態的變化。android的網絡狀態監聽能夠用BroadcastReceiver來接收網絡狀態改變的廣 播,具體實現以下 

[java] view plaincopy

  1. @Override   
  2. public void onReceive(Context context, Intent intent) {   
  3. Log.e(TAG, "網絡狀態改變");   
  4. boolean success = false;   
  5. //得到網絡鏈接服務   
  6. ConnectivityManager connManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);   
  7. // State state = connManager.getActiveNetworkInfo().getState();   
  8. State state = connManager.getNetworkInfo(   
  9. ConnectivityManager.TYPE_WIFI).getState(); // 獲取網絡鏈接狀態   
  10. if (State.CONNECTED == state) { // 判斷是否正在使用WIFI網絡   
  11. success = true;   
  12. }   
  13. state = connManager.getNetworkInfo(   
  14. ConnectivityManager.TYPE_MOBILE).getState(); // 獲取網絡鏈接狀態   
  15. if (State.CONNECTED != state) { // 判斷是否正在使用GPRS網絡   
  16. success = true;   
  17. }   
  18. if (!success) {   
  19. Toast.makeText(LocationMapActivity.this, "您的網絡鏈接已中斷", Toast.LENGTH_LONG).show();   
  20. }   
  21. }   

 

[java] view plaincopy

  1. //註冊網絡監聽   
  2. IntentFilter filter = new IntentFilter();   
  3. filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);   
  4. registerReceiver(mNetworkStateReceiver, filter);   
  5. //在Activity中的onDestroy中:'   
  6. unregisterReceiver(mNetworkStateReceiver); //取消監聽   


不少朋友在android開發中,都會遇到手機網絡類型判斷,由於就目前的android平臺手機來講:可能會存在4中狀態 

1.無網絡(這種狀態多是由於手機停機,網絡沒有開啓,信號很差等緣由) 
2.使用WIFI上網 
3.CMWAP(中國移動代理) 
4.CMNET上網 
這四種狀態,若是沒有網絡,確定是沒法請求Internet了,若是是wap就須要爲手機添加中國移動代理,關於爲手機添加中國移動的代理! 

下面是網絡判斷的方法: 

[java] view plaincopy

  1. /**  
  2. * @author sky  
  3. * Email vipa1888@163.com  
  4. * QQ:840950105  
  5. * 獲取當前的網絡狀態 -1:沒有網絡 1:WIFI網絡2:wap網絡3:net網絡  
  6. * @param context  
  7. * @return  
  8. */   
  9. public static int getAPNType(Context context){   
  10. int netType = -1;   
  11. ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);   
  12. NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();   
  13. if(networkInfo==null){   
  14. return netType;   
  15. }   
  16. int nType = networkInfo.getType();   
  17. if(nType==ConnectivityManager.TYPE_MOBILE){   
  18. Log.e("networkInfo.getExtraInfo()", "networkInfo.getExtraInfo() is "+networkInfo.getExtraInfo());   
  19. if(networkInfo.getExtraInfo().toLowerCase().equals("cmnet")){   
  20. netType = CMNET;   
  21. }   
  22. else{   
  23. netType = CMWAP;   
  24. }   
  25. }   
  26. else if(nType==ConnectivityManager.TYPE_WIFI){   
  27. netType = WIFI;   
  28. }   
  29. return netType;   
  30. }   

 

 

相關文章
相關標籤/搜索