好不容易撑到学习HttpService了,也是我最喜欢学习的部分。
首先介绍一下Apache HttpClient,HttpClient是一个完善的HTTP客户端。虽然它提供了对HTTP协议的全面支持,但我们仅可以使用HTTP GET和HTTP POST。
HttpClient的一般使用模式: (1)创建一个HttpClient(或者获取现有的进行引用) (2)实例化HTTP方法,例如PostMethod或者GetMethod (3)设置HTTP参数名称/值 (4)使用HttpClient执行HTTP调用 (5)处理HTTP响应 (6)释放资源
案例:HttpGet请求 //创建一个HttpClient对象 HttpClient client = new DefaultHttpClient(); //实例化GetMethod HttpGet request = new HttpGet("http://baidu.com"); //使用HttpClient执行HTTP调用 HttpResponse response = client.execute(request); //处理HTTP响应 in = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); StringBuffer sb = new StringBuffer(); String line =""; String NL = System.getProperty("line.separator"); while((line = in.readLine())!=null){ sb.append(line+NL); } //释放资源 in.close();
在这个过程中发生了一件事,HttpClient不能直接在主线程中运行,因为HttpClient的等待响应时间大于ANR时间,因此会导致主线程阻塞。要想让程序顺利运行下去,必须创建一个新的线程去运行HttpClient
案例:HttpPost请求(最完整的HttpClient操作)
//1、创建一个HttpClient对象 HttpClient client = new DefaultHttpClient();
//2、实例化HttpPost方法 HttpPost request = new HttpPost("http://jwc.gduf.edu.cn/(xei1zg45hj3rzsq5hschua45)/default2.aspx");
//3、设置HttpClient参数名称/值 List<NameValuePair> postParameters = new ArrayList<NameValuePair>(); postParameters.add(new BasicNameValuePair("__VIEWSTATE","dDwtMTIwMTU3OTE3Nzs7PnRIU+Pu3kIAnAE8HYvHVoTzlsiA")); postParameters.add(new BasicNameValuePair("TextBox1", xh)); postParameters.add(new BasicNameValuePair("TextBox2", pw)); postParameters.add(new BasicNameValuePair("RadioButtonList1","学生")); postParameters.add(new BasicNameValuePair("Button1","")); postParameters.add(new BasicNameValuePair("lbLanguage","")); UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(postParameters); request.setEntity(formEntity);
//4、使用HttpClient执行HTTP调用 HttpResponse response = client.execute(request);
//5、处理HTTP响应 BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); String line = null; StringBuilder sb = new StringBuilder(); while((line=in.readLine())!=null){ sb.append(line+" "); }
//6、释放资源 in.close();
通常在用户注册时候需要填文字又需要传头像,这时候就需要用到多部分Post技术(涉及Commons IO、Mime4j、HttpMime这三个jar包) HttpClient client = new DefaultHttpClient(); HttpPost request = new HttpPost("http://mysomewebserver.com/services/doSomething.do"); InputStream is = this.getAssets().open("data.xml"); byte[] data = IOUtils.toByteArray(is); InputStreamBody isb = new InputStreamBody(new ByteArrayInputStream(data), "uploadedFile"); StringBody sb1 = new StringBody("some text goes here"); StringBody sb2 = new StringBody("some text goes here too"); MultipartEntity multipartEntity = new MultipartEntity(); multipartEntity.addPart("uploadedFile",isb); multipartEntity.addPart("one",sb1); multipartEntity.addPart("two",sb2); request.setEntity(multipartEntity); HttpResponse response = client.execute(request); String result = response.getEntity().toString();
解决HttpClient多线程的问题,为整个应用程序创建一个HttpClient,并将其用于所有HTTP通信 public class CustomHttpClient { private static HttpClient customHttpClient; /** A private Constructor prevents any other class from instantiating. */ private CustomHttpClient() { } public static synchronized HttpClient getHttpClient() { if (customHttpClient == null) { HttpParams params = new BasicHttpParams(); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET); HttpProtocolParams.setUseExpectContinue(params, true); HttpProtocolParams.setUserAgent(params, "Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; Nexus One Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1" ); ConnManagerParams.setTimeout(params, 1000); HttpConnectionParams.setConnectionTimeout(params, 5000); HttpConnectionParams.setSoTimeout(params, 10000); SchemeRegistry schReg = new SchemeRegistry(); schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params,schReg); customHttpClient = new DefaultHttpClient(conMgr, params); } return customHttpClient; } public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } }
下面将进行一些利用AsyncTask进行下载文件的实例
/** * 下载图片 * @author Administrator * */ public class DownloadImageTask extends AsyncTask<String, Integer, Bitmap> { private Context context; public DownloadImageTask(Context context){ this.context = context; } /** * onPreExecute方法可以在doInBackground执行前执行,是下载文件的准备工作 * 此方法在主线程上运行 */ @Override protected void onPreExecute(){ Log.e("DownImage", "准备进行"); } /** * 运行后台线程 */ @Override protected Bitmap doInBackground(String... urls) { // TODO Auto-generated method stub try { return downloadImage(urls); } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } /** * doInBackground正在执行中所要执行的代码,通常是进度条更新 */ @Override protected void onProgressUpdate(Integer... progress){ Log.e("DownImage", "正在下载中:"+progress[0]+"%"); } /** * 处理doInBackground执行完后的结果 * 使用结果更新UI */ @Override protected void onPostExecute(Bitmap result){ if(result!=null){ ImageView mImage = (ImageView)((Activity)context).findViewById(R.id.imageView1); mImage.setImageBitmap(result); }else{ TextView errorMsg = (TextView)((Activity)context).findViewById(R.id.textView1); errorMsg.setText("下载失败,请检查网络"); } } /** * 下载图片的代码 * @param urls * @return * @throws IOException * @throws ClientProtocolException */ private Bitmap downloadImage(String... urls) throws ClientProtocolException, IOException{ HttpClient client = CustomHttpClient.getHttpClient(); this.publishProgress(10); HttpGet request = new HttpGet(urls[0]); this.publishProgress(20); HttpParams params = new BasicHttpParams(); this.publishProgress(30); HttpConnectionParams.setSoTimeout(params, 60000); this.publishProgress(40); request.setParams(params); this.publishProgress(50); HttpResponse response = client.execute(request); this.publishProgress(60); byte[] image = EntityUtils.toByteArray(response.getEntity()); this.publishProgress(80); Bitmap mBitmap = BitmapFactory.decodeByteArray(image, 0, image.length); this.publishProgress(100); return mBitmap; } }
再介绍一个利用BroadcastReceiver进行下载文件的实例
/** * 下载大型文件 * @author Administrator * */ public class DownBigFileActivity extends Activity implements View.OnClickListener{ private DownloadManager downloadManager; private ProgressBar progressBar; private long downloadId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_down_big_file); this.findViewById(R.id.button1).setOnClickListener(this); progressBar = (ProgressBar)findViewById(R.id.progressBar1); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.down_big_file, menu); return true; } protected void onResume(){ super.onResume(); downloadManager = (DownloadManager)this.getSystemService(DOWNLOAD_SERVICE); } @SuppressLint("InlinedApi") public BroadcastReceiver mReceiver = new BroadcastReceiver(){ @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub Bundle extras = intent.getExtras(); long doneDownloadId = extras.getLong(DownloadManager.EXTRA_DOWNLOAD_ID); Log.e("DownBigfile1",String.valueOf(doneDownloadId)); if(downloadId==doneDownloadId) Log.e("DownBigfile", "Finished"); } }; @Override protected void onPause(){ super.onPause(); this.unregisterReceiver(mReceiver); downloadManager = null; } @SuppressLint("NewApi") @Override public void onClick(View v) { // TODO Auto-generated method stub switch(v.getId()){ case R.id.button1: DownloadManager.Request dmReq = new DownloadManager.Request(Uri.parse("http://dl-ssl.google.com/android/repository/"+ "platform-tools_r01-linux.zip")); dmReq.setTitle("Platform Tools"); dmReq.setDescription("Download for Linux"); dmReq.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE); IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE); this.registerReceiver(mReceiver, filter); downloadId = downloadManager.enqueue(dmReq); Log.e("DownBigfile2",String.valueOf(downloadId)); progressBar.setProgress((int) downloadId); break; } } }