Android通常經過http協議向服務端接口發送請求,經常使用有POST和GET傳輸方式。這種請求一般藉助於HttpClient,HttpClient 是 Apache Jakarta Common 下的子項目,能夠用來提供高效的、最新的、功能豐富的支持 HTTP 協議的客戶端編程工具包。經過HttpClient能夠不借助瀏覽器,從而簡化了客戶端與服務器端之間的交互。
html
HttpPost httpPost=new HttpPost(reqUrl);
java
HttpResponse httpResponse=new DefaultHttpClient().execute(httpPost);
android
DefaultHttpClient是HttpClient接口的默認實現,new DefaultHttpClient().execute(httpPost);則是使用一個匿名內部類來處理請求。該匿名內部類繼承自DefaultHttpClient,而DefaultHttpClient實現了HttpClient接口,全部能夠重寫HttpClient接口下execute的方法來處理請求。
編程
Android Post請求的兩種方式瀏覽器
(1)、HttpPost緩存
HttpPost httpRequest =new HttpPost(url); List <NameValuePair> params=new ArrayList<NameValuePair>();//Post方式用NameValuePair[]陣列儲存 params.add(new BasicNameValuePair("name","name")); try{ //設置請求參數 httpRequest.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8)); //建立HttpClient實例 HttpClient client = new DefaultHttpClient(); //請求超時 client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 20000); //讀取超時 client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 20000 ); //取得HTTP response HttpResponse httpResponse = client.execute(httpRequest); //若狀態碼爲200 ok if(httpResponse.getStatusLine().getStatusCode()==200){ //取出迴應字串 String strResult=EntityUtils.toString(httpResponse.getEntity()); }else{; } }catch(ClientProtocolException e){ Toast.makeText(getApplicationContext(), e.getMessage().toString(),Toast.LENGTH_SHORT).show(); e.printStackTrace(); } catch (UnsupportedEncodingException e) { Toast.makeText(getApplicationContext(), e.getMessage().toString(),Toast.LENGTH_SHORT).show(); e.printStackTrace(); } catch (IOException e) { Toast.makeText(getApplicationContext(), e.getMessage().toString(),Toast.LENGTH_SHORT).show(); e.printStackTrace(); }
(2)、HttpURLConnection
try{
//創建鏈接
URL url=new URL(url);
HttpURLConnection httpConn=(HttpURLConnection)url.openConnection();
////設置鏈接屬性
httpConn.setDoOutput(true);//使用 URL 鏈接進行輸出
httpConn.setDoInput(true);//使用 URL 鏈接進行輸入
httpConn.setUseCaches(false);//忽略緩存
httpConn.setRequestMethod("POST");//設置URL請求方法
String requestString = "客服端要以以流方式發送到服務端的數據...";
//設置請求屬性
//得到數據字節數據,請求數據流的編碼,必須和下面服務器端處理請求流的編碼一致
byte[] requestStringBytes = requestString.getBytes("utf-8");
httpConn.setRequestProperty("Content-length", "" + requestStringBytes.length);
httpConn.setRequestProperty("Content-Type", "application/octet-stream");
httpConn.setRequestProperty("Connection", "Keep-Alive");// 維持長鏈接
httpConn.setRequestProperty("Charset", "UTF-8");
//
String name=URLEncoder.encode("張三","utf-8");
httpConn.setRequestProperty("name", name);
//創建輸出流,並寫入數據
OutputStream outputStream = httpConn.getOutputStream();
outputStream.write(requestStringBytes);
outputStream.close();
//得到響應狀態
int responseCode = httpConn.getResponseCode();
if(HttpURLConnection.HTTP_OK == responseCode){//鏈接成功
//當正確響應時處理數據
StringBuffer sb = new StringBuffer();
String readLine;
BufferedReader responseReader;
//處理響應流,必須與服務器響應流輸出的編碼一致
responseReader = new BufferedReader(new InputStreamReader(httpConn.getInputStream(), ENCODING_UTF_8));
while ((readLine = responseReader.readLine()) != null) {
sb.append(readLine).append("\n");
}
responseReader.close();
}
}catch(Exception ex){
ex.printStackTrace();
}服務器
HttpClient和HttpURLConnection是訪問HTTP的兩種方式,
HttpURLConnection是一個抽象類,繼承自URLConnection抽象類,基於標準Java接口(java.net),能夠實現簡單的基於URL請求、響應功能;HttpClient基於Apache接口(org.appache.http),使用起來更方面更強大。通常來講,使用這種接口比較多。運用這兩種方式,android能夠訪問網頁、下載圖片或文件、上傳文件,甚至參數配置適當時,能夠抓取服務器的不少數據。如用android作多圖上傳到服務器。
網絡
首先咱們先解析目標url請求時的一些參數app
如提請求的url地址Request URL,提交的方式Request Method,服務器端的IP地址及端口Remote Address,請求頭Request Headers,請求負載(表單參數)Request Payload,進而咱們就能夠在代碼裏面進行設置,而後發送請求ide
/** * 解析multipart/form-data方式提交的請求,並以一樣的方式再提交 */ @SuppressWarnings("unchecked") public static HttpURLConnection doPostMultipartFormData(java.net.URL url,MultipartHttpServletRequest request){ //分割字符串 String BOUNDARY = UUIDTool.getUUID().toUpperCase(); String BOUNDARYSP = "--"; String BOUNDARYSTR = BOUNDARYSP + BOUNDARY; String LINESP = "\r\n"; HttpURLConnection conn = null; try{ conn = (HttpURLConnection) url.openConnection(); conn.setUseCaches(false); conn.setDoOutput(true);// 是否輸入參數 conn.setConnectTimeout(3000); conn.setRequestMethod("POST"); conn.setRequestProperty( "Accept", "text/html, application/xhtml+xml, */*"); conn.setRequestProperty("Accept-Language", "zh-CN"); 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.setRequestProperty("Accept-Charset", "UTF-8"); //conn.setRequestProperty("contentType", "UTF-8"); conn.setRequestProperty("Content-Type","multipart/form-data; boundary=" + BOUNDARY+"; charset=UTF-8"); OutputStream out = new DataOutputStream(conn.getOutputStream()); //byte[] end_data = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();// 定義最後數據分隔線 StringBuffer multiParamsData = new StringBuffer(); //組裝普通參數 Map params = request.getParameterMap(); for(Object key : params.keySet()){ Object paramvalue = params.get(key); if(paramvalue!=null){ if(paramvalue instanceof String[]){ for(String param : (String[])paramvalue){ multiParamsData.append(BOUNDARYSTR); multiParamsData.append(LINESP); multiParamsData.append("Content-Disposition: form-data; name=\""+key+"\""); multiParamsData.append(LINESP); multiParamsData.append("Content-Type: text/plain; charset=UTF-8"); multiParamsData.append(LINESP); multiParamsData.append(LINESP); multiParamsData.append(param); multiParamsData.append(LINESP); } }else{ multiParamsData.append(BOUNDARYSTR); multiParamsData.append(LINESP); multiParamsData.append("Content-Disposition: form-data; name=\""+key+"\""); multiParamsData.append(LINESP); multiParamsData.append("Content-Type: text/plain; charset=UTF-8"); multiParamsData.append(LINESP); multiParamsData.append(LINESP); multiParamsData.append(paramvalue); multiParamsData.append(LINESP); } } } //System.out.println(multiParamsData.toString()); out.write(multiParamsData.toString().getBytes("UTF-8")); //組裝文件 Map<String, MultipartFile> files = request.getFileMap(); int i = 1; for(String key : files.keySet()){ StringBuffer multiFilesData = new StringBuffer(); MultipartFile multipartFile = files.get(key); multiFilesData.append(BOUNDARYSTR); multiFilesData.append(LINESP); multiFilesData.append("Content-Disposition: form-data; name=\""+key+"\"; filename=\""+multipartFile.getOriginalFilename()+"\""); multiFilesData.append(LINESP); multiFilesData.append("Content-Type:application/octet-stream"); multiFilesData.append(LINESP); multiFilesData.append(LINESP); //multiData.append(paramvalue); out.write(multiFilesData.toString().getBytes("UTF-8")); DataInputStream in = new DataInputStream(multipartFile.getInputStream()); int bytes = 0; byte[] bufferOut = new byte[1024]; while ((bytes = in.read(bufferOut)) != -1) { out.write(bufferOut, 0, bytes); } out.write(LINESP.getBytes("UTF-8")); in.close(); // System.out.println(multiFilesData.toString()+"<file content; length:"+readStream(multipartFile.getInputStream()).length+">"); } //System.out.println(BOUNDARYSTR+BOUNDARYSP); out.write((BOUNDARYSTR+BOUNDARYSP+LINESP).getBytes("UTF-8")); out.flush(); out.close(); //byte[] bypes = params.getBytes("UTF-8"); //System.out.println("2>>>>>>"+new String(params,"UTF-8")); // conn.getOutputStream().write(params); } catch(ConnectException e){ } catch(Exception e){ logger.error("HttpRequest Error:",e); } return conn; }
HttpPsot結合Handle
new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub Message message=new Message(); HttpPost httpPost=new HttpPost(reqUrl); try{ httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); HttpResponse httpResponse; try{ httpResponse=new DefaultHttpClient().execute(httpPost); if(httpResponse.getStatusLine().getStatusCode()==200){ String result = EntityUtils.toString(httpResponse.getEntity()); if(!result.isEmpty()){ message.what=0; message.obj=result; myHandler.sendMessage(message); }else{ message.what=1; myHandler.sendMessage(message); } }else{ message.what=1; myHandler.sendMessage(message); } }catch(Exception e){ e.printStackTrace(); } }catch(Exception e){ e.printStackTrace(); } } }).start();
static Handler myHandler=new Handler(){ @Override public void handleMessage(android.os.Message msg) { if(msg.what==1){ resultCallback.getReslt("1"); }else if(msg.what==0){ String result=(String) msg.obj; } }; };
涉及到網絡數據傳輸,AndroidManifest.xml中要設置相應的權限。
<uses-permission android:name="android.permission.INTERNET" />
同時能夠對網絡狀態作一些相應的處理。
/** * 檢測網絡是否鏈接 * @return */ private boolean isNetConnected() { ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); if (cm != null) { NetworkInfo[] infos = cm.getAllNetworkInfo(); if (infos != null) { for (NetworkInfo ni : infos) { if (ni.isConnected()) { return true; } } } } return false; } /** * 設置網絡 * @param context */ private void isNetworkAvailable(Context context) { new AlertDialog.Builder(LoginActivity.this) .setTitle("網絡設置提示") .setMessage("網絡不可用,是否如今設置網絡?") .setPositiveButton("設置", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if(android.os.Build.VERSION.SDK_INT > 10 ){ //3.0以上打開設置界面,也能夠直接用ACTION_WIRELESS_SETTINGS打開到wifi界面 startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS)); } else { startActivity(new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS)); } overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out); } }).setNegativeButton("取消", null).show();