如前文所示的TCP局域网传送东西,除了对传输层的TCP/UDP支持良好外,Android对HTTP(超文本传输协议)也提供了很好的支持,这里包括两种接口:
1、标准Java接口(java.net) ----HttpURLConnection,可以实现简单的基于URL请求、响应功能;
2、Apache接口(org.appache.http)----HttpClient,使用起来更方面更强大。一般来说,用这种接口。不过本文还是把第一种接口过一下。
任何一种接口,无外乎四个基本功能:访问网页、下载图片或文件、上传文件.本文示范的是访问网页和下载图片。HttpURLConnection继承自URLConnection类,用它可以发送和接口任何类型和长度的数据,且预先不用知道数据流的长度,可以设置请求方式get或post、超时时间。
下面直接贴代码,代码目的有两个,一是访问百度首页,获取其返回的html字符串,二是给定URL下载个图片并显示出来。后续将展开系列博文介绍HTTP相关知识。
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/parent_view" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/textview_show" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> <ImageView android:id="@+id/imagview_show" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" /> </FrameLayout> <Button android:id="@+id/btn_visit_web" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:text="访问百度" /> <Button android:id="@+id/btn_download_img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_toRightOf="@id/btn_visit_web" android:text="下载图片"/> </RelativeLayout>
package org.yanzi.httpurlconnection; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; public class MainActivity extends Activity { Button visitWebBtn = null; Button downImgBtn = null; TextView showTextView = null; ImageView showImageView = null; String resultStr = ""; ProgressBar progressBar = null; ViewGroup viewGroup = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initUI(); visitWebBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub showImageView.setVisibility(View.GONE); showTextView.setVisibility(View.VISIBLE); Thread visitBaiduThread = new Thread(new VisitWebRunnable()); visitBaiduThread.start(); try { visitBaiduThread.join(); if(!resultStr.equals("")){ showTextView.setText(resultStr); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); downImgBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub showImageView.setVisibility(View.VISIBLE); showTextView.setVisibility(View.GONE); String imgUrl = "http://www.shixiu.net/d/file/p/2bc22002a6a61a7c5694e7e641bf1e6e.jpg"; new DownImgAsyncTask().execute(imgUrl); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } public void initUI(){ showTextView = (TextView)findViewById(R.id.textview_show); showImageView = (ImageView)findViewById(R.id.imagview_show); downImgBtn = (Button)findViewById(R.id.btn_download_img); visitWebBtn = (Button)findViewById(R.id.btn_visit_web); } /** * 获取指定URL的响应字符串 * @param urlString * @return */ private String getURLResponse(String urlString){ HttpURLConnection conn = null; //连接对象 InputStream is = null; String resultData = ""; try { URL url = new URL(urlString); //URL对象 conn = (HttpURLConnection)url.openConnection(); //使用URL打开一个链接 conn.setDoInput(true); //允许输入流,即允许下载 conn.setDoOutput(true); //允许输出流,即允许上传 conn.setUseCaches(false); //不使用缓冲 conn.setRequestMethod("GET"); //使用get请求 is = conn.getInputStream(); //获取输入流,此时才真正建立链接 InputStreamReader isr = new InputStreamReader(is); BufferedReader bufferReader = new BufferedReader(isr); String inputLine = ""; while((inputLine = bufferReader.readLine()) != null){ resultData += inputLine + "\n"; } } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); }catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ if(is != null){ try { is.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(conn != null){ conn.disconnect(); } } return resultData; } /** * 从指定URL获取图片 * @param url * @return */ private Bitmap getImageBitmap(String url){ URL imgUrl = null; Bitmap bitmap = null; try { imgUrl = new URL(url); HttpURLConnection conn = (HttpURLConnection)imgUrl.openConnection(); conn.setDoInput(true); conn.connect(); InputStream is = conn.getInputStream(); bitmap = BitmapFactory.decodeStream(is); is.close(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); }catch(IOException e){ e.printStackTrace(); } return bitmap; } class VisitWebRunnable implements Runnable{ @Override public void run() { // TODO Auto-generated method stub String data = getURLResponse("http://www.baidu.com/"); resultStr = data; } } class DownImgAsyncTask extends AsyncTask<String, Void, Bitmap>{ @Override protected void onPreExecute() { // TODO Auto-generated method stub super.onPreExecute(); showImageView.setImageBitmap(null); showProgressBar();//显示进度条提示框 } @Override protected Bitmap doInBackground(String... params) { // TODO Auto-generated method stub Bitmap b = getImageBitmap(params[0]); return b; } @Override protected void onPostExecute(Bitmap result) { // TODO Auto-generated method stub super.onPostExecute(result); if(result!=null){ dismissProgressBar(); showImageView.setImageBitmap(result); } } } /** * 在母布局中间显示进度条 */ private void showProgressBar(){ progressBar = new ProgressBar(this, null, android.R.attr.progressBarStyleLarge); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); params.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE); progressBar.setVisibility(View.VISIBLE); Context context = getApplicationContext(); viewGroup = (ViewGroup)findViewById(R.id.parent_view); // MainActivity.this.addContentView(progressBar, params); viewGroup.addView(progressBar, params); } /** * 隐藏进度条 */ private void dismissProgressBar(){ if(progressBar != null){ progressBar.setVisibility(View.GONE); viewGroup.removeView(progressBar); progressBar = null; } } }
<uses-permission android:name="android.permission.INTERNET"/>
注意事项:
1、使用HttpURLConnection的步骤是先实例化一个URL对象,通过URL的openConnection实例化HttpURLConnection对象。然后设置参数,注意此时并没有发生连接。真正发生连接是在获得流时即conn.getInputStream这一句时,这点跟TCP Socket是一样的。并非阻塞在ServerSocket.accept()而是阻塞在获取流。所以在获取流之前应该设置好所有的参数。
2、Get和POST两种方式访问服务器,区别见链接1 链接2
3、[Android4.0后所有网络方面的操作都不能再主线程!!!]在获取网页响应字符串时本文代码使用了Thread,在下载图片时使用了AsyncTask,可以对比其使用的异同。很明显,AsyncTask更加方面。在onPreExecute和onPostExecute里可以很方面的做主线程UI的事。
4、在获取网页字符串时,使用了线程的Thread.join函数,这会使在onClick里在join处进行阻塞,直到Thread的run执行完才会进行判断,界面卡死。因此在实际开发中要尽量避免之中,解决方法是使用Thread+Handle的方式,或AsyncTask。实际上后者就是前者的封装。
5、访问图片比较简单,得到输入流后直接用BitmapFactory解析即可。
6、showProgressBar() 、dismissProgressBar()用来显示和隐藏下载图片时的提示框。
运行效果:
初始界面:
按下访问百度后:
按下下载图片后:
--------------------------------本文系原创,转载请注明作者:yanzi1225627
源码下载链接:http://download.csdn.net/detail/yanzi1225627/7104645