Android学习笔记之HttpClient实现Http请求....

PS:最近光忙着考试了....破组成原理都看吐了....搞的什么也不想干...写篇博客爽爽吧....貌似明天就考试了...sad...

学习笔记:

1.如何实现Http请求来实现通信....

2.解决Android 2.3 版本以后无法使用Http请求问题....

  这里我使用HttpClient来开发Http程序来完成简单的网络通信....其实使用HttpUrlConnection也可以实现,不过HttpClient可以完成HttpUrlConnection的所有功能,并且还自己增加了其他的功能,那相比之下就直接使用HttpClient就得了...Http通信有两种方式,相比大家都清楚,一种是使用GET请求,另一种则是使用POST请求来完成...GET请求可以获取静态页面,也可以把参数放在URL参数后面进行传递...POST与GET不同的地方就在于这里,POST请求无法将数据放到字符串的后面...而是放在Http传递的数据当中...这些参数会通过cookie或者是session来进行传递...POST更加适合传递保密的数据信息...比如说用户的账户密码...这样使用GET方式就不是很合理了...因此把保密的数据信息放入到Http请求数据中更加的安全...

  那么Android是如何通过Http请求来实现GET或者是POST请求呢?这里简单的介绍一下...先介绍一下GET方式...如何使用GET请求来获取数据信息....GET请求需要几个步骤...

  首先:我们需要建立GET对象...通过创建对象来告诉服务器我们使用的GET请求来获取数据信息的...因为Http请求是以URL的形式进行来完成数据传递的...因此我们需要传递一个URL来实例化对象...我这个地址是服务器上的一个jsp文件...通过使用Http请求来获取JSP界面的数据信息...

String path="http://10.0.2.2:8080/JSP/text.jsp":
HttpGet get=new HttpGet(path);

  然后我们需要使用DefaultHttpClient类中的execute()方法来发送Http GET请求...并返回一个HttpResponse对象,HttpResponse对象的目的是当一个Http连接建立成功之后,我们就可以使用其类中的方法来获取到服务器的响应信息...

HttpClient client=new DefaultHttpClient();
HttpResponse response=client.execute(get);

  最后我们就可以通过HttpResponse对象来获取服务器的响应数据信息了...这里我使用了一个getEntity()方法来返回响应信息,然后获取GET提交的URL后面的数据信息...

if(response.getStatusLine().getStatusCode()==HttpStatuse.SC_OK){
     String result=EntityUtils.toString(resopnse.getEntity());
     tv.setText(result);
}

最后我们需要在AndroidManifest.xml文件中配置权限属性...只需要添加<user-permission android:name="android.permission.INTERNET"/>那么简单的举一个小例子来实现Http的GET请求...

  首先我们先写一个JSP页面.....这个页面要在Tomcat上进行发布...当没有参数值进行传递的时候,会显示Your message are wrong!这个信息...

<%
    String name=request.getParameter("name");
    String password=request.getParameter("password");
    if("DARKER".equals(name) && "4968188".equals(password)){
        out.println("Receive name is:"+name);
        out.println("Receive password is:"+password);%>
    Your message are right!
    <%}else{
        out.println("Receive name is:"+name);
        out.println("Receive password is:"+password); %>
        Your message are wrong!
    <%}%>

  然后有了这个东西,我们就可以通过Http传递数据信息来提交数据...然后通过这个界面返回的信息来告知我们服务器响应的信息数据...一个简单的布局文件...就一个文本框...目的就是为了返回服务器的响应信息...

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/msg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

  如何实现才是一个重要的过程...在实现的过程中会出现一个问题,就是在Android2.3版本以后就不允许在主线程中去使用Http请求了...相信大部分的学习资料上都没有这个提示问题,但是确实是存在着这样一个问题的...那么上有政策那么就下有对策...我们可以使用三种方法去解决这个问题...非常的简单,也很好理解...那么既然我们无法在主线程中去使用Http请求,那么我们可以新开启一个线程啊...或者是我们可以去使用异步线程类AsyncTask去实现不就完了吗...还有一种方法就是在主线程中加入某些东西...就是下面的在setContentView()这个函数下面加入的那两句话...但是这种方法在网上说并不是很推荐...因此本人也没怎么研究...其他两种方式先对就很好理解...这三种方式我都进行了列举...只要使用其中的任意一种方式就可以实现Http的GET请求....

package com.example.httpclient;
/* HttpCilent 通过Get与服务器进行通信...
 * HttpClient比HttpUrlConnection更加的有优势...前者能做后者所有能做的事情...
 * 那就干脆就使用这种方式吧....
 *
 *
 * */
import java.io.IOException;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {

    /*
     * 由于在Android2.3版本以后就不允许在主线程使用Http请求...
     * 但是我们可以使用其他的方法来解决这个问题...
     * 第一种方法在主线程onCreate()方法中加入StrictMode方法..不过这种方法不被推荐...
     * 第二种使用异步线程AsyncTask<Param,Progress,Result>也可以实现...在异步线程中完成Http请求..
     * 第三种方法单开启一个线程Runnable()来实现,其实也是延续异步线程的思想...
     *
     * */
    private TextView tv;
//    private String path="http://10.0.2.2:8080/JSP/get.jsp?name=DARKER&password=49681888";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
//        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());
//        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build());
        tv=(TextView) findViewById(R.id.msg);
        new Thread(runnable).start();
//        HttpGet httpRequest=new HttpGet(path);
//        HttpClient httpcilents=new DefaultHttpClient();
//        try {
//            HttpResponse response=httpcilents.execute(httpRequest);
//            if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK){
//                String result=EntityUtils.toString(response.getEntity());
//                tv.setText(result);
//            }else{
//                tv.setText("请求错误");
//            }
//        } catch (ClientProtocolException e) {
//            // TODO Auto-generated catch block
//            e.printStackTrace();
//        } catch (IOException e) {
//            // TODO Auto-generated catch block
//            e.printStackTrace();
//        }
    }
    @SuppressWarnings("unused")
    private class http extends AsyncTask<Integer, Integer, Integer>{

        @Override
        protected Integer doInBackground(Integer... params) {
            // TODO Auto-generated method stub
            String url="http://10.0.2.2:8080/JSP/get.jsp?name=DARKER&password=49681888";
            HttpGet hget=new HttpGet(url);
            HttpClient htclient=new DefaultHttpClient();
            try {
                HttpResponse hresonse=htclient.execute(hget);
                if(hresonse.getStatusLine().getStatusCode()==HttpStatus.SC_OK){
                    String resul=EntityUtils.toString(hresonse.getEntity());
                    tv.setText(resul);
                }else{
                    tv.setText("连接失败...");
                }
            } catch (ClientProtocolException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
        }

    }

    Runnable runnable=new Runnable() {

        String path_1="http://10.0.2.2:8080/JSP/get.jsp?name=DARKER&password=49681888";
        @Override
        public void run() {
            // TODO Auto-generated method stub
            HttpGet get=new HttpGet(path_1);
            HttpClient cilent=new DefaultHttpClient();
            try {
                HttpResponse responses=cilent.execute(get);
                if(responses.getStatusLine().getStatusCode()==HttpStatus.SC_OK){
                    String result_1=EntityUtils.toString(responses.getEntity());
                    tv.setText(result_1);
                }else{
                    tv.setText("无法获取信息...");
                }
            } catch (ClientProtocolException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };
    @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;
    }
}

  其实上面代码使用异步线程类是没问题的,不过上面的代码会报错,由于我的代码写错了位置...这个错误其实是在doInBackground()方法中出现的...因为在这个方法中是不能够更新控件的数据信息的...这个问题我将在下面进行解决....下面是实现Http的POST请求...然后解决刚才说的问题....下面使用了Handler类...简答的说一下这个类...其实这个类并不是用在这个异步线程类里面的...这个异步线程类内部还有三个没有实现的方法...就是onPreExecute(),publishProgress(),onProgressUpdate()...这三个方法内部都可以完成控件数据信息的更新,唯独这个doInBackground()是无法实现的...使用一个AsyncTask类,再使用Handler是完全没有必要的...其实Handler和AsyncTask是为了实现子线程无法去更新主线程中控件的数据信息而存在的...因为控件对于线程来说是不安全的,因此在子线程中也就无法完成主线程中控件数据信息的更新操作...但是在Android中往往是需要这样做的...因此出现了这两个类去解决这个问题...

  首先说一句主要的事,就是使用到了Runnable并不代表一定使用到了多线程...就拿上面那个Runnable类来说,这个runnable虽然重写了run()方法,并且还在主函数中使用了start进行调用,但是这个线程仍然是属于主线程Activity的,并不属于我们单独开启了一个新的线程,然后去执行任务...这是必然的,否则一定会报错...因为在一个新的线程内部是无法去更新主线程中控件的数据信息的...然后在说一下Handler是如何能够完成在子线程中能够对主线程中的控件完成对数据的更新...首先Handler通过传递Message或者是Runnable对象...一般来说都是Message对数据进行封装...Handler主要用来与Looper进行沟通..把信息加入到特定的Looper消息队列中,或者是获取Looper的信息,然后调用handlemessage方法来对获取的信息进行操作...然后将Message发送到MessageQueue中,MessageQueue是一个线性队列,用来保存获取到的消息数据...当Looper发现MessageQueue中有未处理的信息就将这个信息广播出去...Looper就是对MessageQueue队列中然后主线程Handler接收到信息,然后做相应的处理...最后完成更新操作...这就是实现的一个过程...

package com.example.httpclientpost;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {

    TextView tv;
    String result;
    @SuppressLint("HandlerLeak")
    private Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg){
            if(msg.what==1){
                tv.setText(result);
            }else{
                tv.setText("无法连接服务器...");
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv=(TextView) findViewById(R.id.show);
        http h=new http();
        h.execute();
    }

    class http extends AsyncTask<Integer, Integer, Integer>{

        String url="http://10.0.2.2:8080/JSP/get.jsp";
        @Override
        protected Integer doInBackground(Integer... params) {
            // TODO Auto-generated method stub
            HttpPost post=new HttpPost(url);
            List<NameValuePair> param=new ArrayList<NameValuePair>();
            param.add(new BasicNameValuePair("name", "DARKER"));
            param.add(new BasicNameValuePair("password", "49681888"));
            try {
                HttpEntity entity=new UrlEncodedFormEntity(param,"gb2312");
                post.setEntity(entity);
                HttpClient client=new DefaultHttpClient();
                HttpResponse response=client.execute(post);
                if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK){
                     result=EntityUtils.toString(response.getEntity());
                     Message msg=new Message();
                     msg.what=1;
                     handler.sendMessage(msg);
                }else{
                    Message msg=new Message();
                    msg.what=0;
                    handler.sendMessage(msg);
                }
            }catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClientProtocolException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return null;
        }

    }
    @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;
    }

}

  其实我觉得使用Android中使用AsyncTask这个异步线程类其实就行,因为这个异步线程类是结合了handler+Thread才得以实现的,当然我们也可以使用handler去进行处理,个人推荐还是使用这个异步线程类更好...好了有点说跑题了...返回Http的POST请求,Http的POST请求比GET能多了一点东西,它使用NameValuePair以键值对的形式对数据进行保存...并且POST请求需要制定字符集...否则数据会出现乱码现象...剩下的东西基本就类似了...这样就实现了Http的POST请求....

时间: 2024-10-11 07:23:55

Android学习笔记之HttpClient实现Http请求....的相关文章

Android学习笔记(四五):互联网通信-HttpClient、XML解析(W3C)

前几日Android发布了4.0 Icecream,昨天上网发现Begining Book中有Edition 3的版本,比对一下,还是有相当的改动,不仅仅增加了tablet的部分,对原有的章节有有一些修订,前后的调整等等.先按Edtion 2的顺序看,相同章节的看Edtion 3,然后回头看Edition 3的Chapter 24.25(E2的36).26.27.28.29.44.45.46.47几个新增章节.同时将模拟器改为Android 2.3的版本,已适应可能新增的改动. 访问Intern

Android学习笔记(四六):互联网通信-文件下载

在Android 2.3引入了DownloadManager可以处理复杂的文件下载,包括检查用户是否有数据联系(WIFI或者移动数据),当用户从一个有数据连接的地方移动到无连接的地方(例如离开了wifi或者3G data的access point),确保设备在下载过程中保持awake状态.DownloadManager可以处理HTTP URLs,但是不能处理HTTPS(SSL) URLs. 设置下载文件条件许可 在这个例子,将学习通过DownloadManager从Internet下载文件,并存

【转】 Pro Android学习笔记(六七):HTTP服务(1):HTTP GET

目录(?)[-] HTTP GET小例子 简单小例子 出现异常NetworkOnMainThreadException 通过StrictMode进行处理 URL带键值对 Andriod应用可利用service提供很多功能,例如利用Google Maps API,现在我们将聚焦在HTTP serice中. Android SDK提供HttpClient,和J2EE中的接口非常相似.最常用的就是HTTP GET和HTTP POST.相关内容也可以阅读Android学习笔记(四五):互联网通信-Htt

【转】 Pro Android学习笔记(六九):HTTP服务(3):HTTP POST MultiPart

目录(?)[-] 建立测试环境 开发环境导入第三方JAR HTTP Post Multipart小例子 HTTP POST不仅可以通过键值对传递参数,还可以携带更为复杂的参数,例如文件.HTTP Post支持携带body,content-type为multipart.本次我们将尝试通过http post上传一个小文件. 建立测试环境 上传文件的测试环境很难找,下载了Tomcat,想装一个环境,打开后,发现忘得也差不多,要看帮助,比较麻烦,下面是我上传文件到189网盘抓的包,上传一个图片文件,整个

Android学习笔记(十一)——从意图返回结果

从意图返回结果 startActivity()方法调用另一个活动,但并没有返回结果给当前活动.此时如想从一个活动中回传数据,就要使用startActivityForResult()方法. 点此获取完整代码~                                                                  1.使用上一篇中创建的项目,在secondactivity.xml文件中添加文本框和按钮,代码如下: <TextView android:layout_width

Android学习笔记二十九之SwipeRefreshLayout、RecyclerView和CardView

Android学习笔记二十九之SwipeRefreshLayout.RecyclerView和CardView 前面我们介绍了AlertDialog和几个常用的Dialog,ProgressDialog进度条提示框.DatePickerDialog日期选择对话框和TimePickerDialog时间选择对话框.这一节我们介绍几个新的API控件SwipeRefreshLayout.RecyclerView和CardView,这几个API控件都是google在Android5.0推出的.下面我们来学

Android学习笔记(三五):再谈Intent(下)-一些实践

Android的UI框架要求用户将他们的app分为activity,通过itent来进行调度,其中有一个main activity由Android的launcher在桌面中调用.例如一个日历的应用,需要查看日历的activity,查看单个事件的activity,编辑事件的activity等等.在查看日历的activity中,如果用户选择的某个事件,需要通过查看事件的activity来处理.这就是最近本的app UI框架,本次,我们将学习如何通过intent来完成. Activity之间的关系 某

Android学习笔记二

17. 在ContentProvider中定义的getType()方法是定义URI的内容类型. 18. SQLiteDatabase类中的insert/delete/update/query方法其实也挺好用的,我在EquipmentProvider类中做了实现 19. Android专门有个单元测试项目(Android Test Project),在这个项目中,可以新建一个继承AndroidTestCase类的具体测试类来单元测试某个功能.我新建了一个AndroidTestProject项目,在

【转】 Pro Android学习笔记(七四):HTTP服务(8):使用后台线程AsyncTask

目录(?)[-] 5秒超时异常 AsyncTask 实现AsyncTask抽象类 对AsyncTask的调用 在哪里运行 其他重要method 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件,转载须注明出处:http://blog.csdn.net/flowingflying/ 之前,我们直接在activity中执行http通信,在通信过程中可能会出现连接超时.socket超时等情况,超时阈值一般是秒级,例如AndroidHttpClient中设置的20秒,如果出现超时,就