Android-----HttpService

好不容易撑到学习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;
        }
    }
}
原文地址:https://www.cnblogs.com/vijay/p/3535559.html