主要是基于HTTP协议与服务端进行交互。

涉及到的类和接口有:URL、HttpURLConnection、HttpClient等

URL

使用一个String类型的url构造一个URL对象,如:

URL url = new URL(http://10.0.2.2/index.php);

openConnection()方法返回一个对指定url的资源的连接。返回类型是URLConnection,但是,由于这里我们一般用的是http协议,所以返回的实际是HttpURLConnection对象,故一般可以进行类型转换。

HttpURLConnection conn = (HttpURLConnection)url.openConnection();

HttpURLConnection:

继承自URLConnection,常用方法有:

getInputStream()方法用来获取用来从网络连接中读取数据的输入流。

getOutputStream()方法用于获取用于向网络连接中写入数据的输出流。

setDoOutput()和setDoInput()方法分别用来设置是否允许向网络写入或读取数据。

setReadTimeout()方法用于设置读取数据超时时限。

setConnectTimeout()方法用于设置网络连接超时时限。

setRequestMethod()方法用于设置请求的方法,一般常用”GET”或”POST”。

getResponseCode()和getResponseMessage()方法分别用来获取服务端的响应码及响应信息字符串描述。

Disconnect()方法用于关闭网络连接。

1.使用HttpURLConnection与服务端进行交互

布局文件代码:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

     xmlns:tools="http://schemas.android.com/tools"

     android:layout_width="match_parent"

     android:layout_height="match_parent"

     android:orientation="vertical"

     tools:context="cn.csc.start.MainActivity" >

     <EditText

         android:id="@+id/et_username"

         android:layout_width="match_parent"

         android:layout_height="wrap_content"

         android:hint="@string/et_username_text"/>

     <EditText

         android:id="@+id/et_password"

         android:layout_width="match_parent"

         android:layout_height="wrap_content"

         android:inputType="textPassword"

         android:hint="@string/et_password_text"/>

     <Button

         android:id="@+id/btn_login"

         android:layout_width="wrap_content"

         android:layout_height="wrap_content"

         android:text="@string/btn_text"

         />

 </LinearLayout>

一个简单的php文件,模拟服务器端:

 <?php

 if(isset($_REQUEST["username"])&& isset($_REQUEST["password"])){

       $username = $_REQUEST["username"];

       $password = $_REQUEST["password"];

       if($username == "zhangsan" && $password == "123"){

            echo "login success";

       }else{

            echo "login failure";

       }

 }else{

       echo "no field allowed empty string";

 }

 ?>

客户端提交用户名密码,客户端返回登录的结果。

注意,在模拟器中用IP:10.0.2.2代表电脑的IP地址。

1.1使用GET方式与服务端进行交互

 public class MainActivity extends ActionBarActivity implements OnClickListener {

     protected static final int OK = 0;

       protected static final String TAG = "MYLOG";

       private EditText et_username;

       private EditText et_password;

       @Override

     protected void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         setContentView(R.layout.activity_main);

         Button btn = (Button) findViewById(R.id.btn_login);

         btn.setOnClickListener(this);

         et_username = (EditText) findViewById(R.id.et_username);

         et_password = (EditText) findViewById(R.id.et_password);

 }

   @Override

   public void onClick(View view) {

         // TODO Auto-generated method stub

         if(view.getId() == R.id.btn_login){

              get_test();

         }

   }

 private void get_test() {

         // TODO Auto-generated method stub

         String username = et_username.getText().toString();

         String password = et_password.getText().toString();

         try {

              URL url = new URL("http://10.0.2.2/index.php?username="+username+"&password="+password);

              HttpURLConnection conn =  (HttpURLConnection) url.openConnection();

              conn.setRequestMethod("GET");

              conn.setConnectTimeout(5000);

              conn.setReadTimeout(5000);

              if(conn.getResponseCode() == 200){

                    InputStream is = conn.getInputStream();

                    BufferedReader br = new BufferedReader(new InputStreamReader(is));

                    String result = br.readLine();

                    Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();

                    conn.disconnect();

              }

         } catch (Exception e) {

              // TODO Auto-generated catch block

              e.printStackTrace();

         }

   }

 }

1.2使用POST方式与服务端进行交互

添加一个post_test方法:

 private void post_test(){

         try {

              URL url = new URL("http://10.0.2.2/index.php");

              HttpURLConnection conn = (HttpURLConnection) url.openConnection();

              conn.setRequestMethod("POST");

              conn.setDoOutput(true);

              conn.setConnectTimeout(5000);

              conn.setReadTimeout(5000);

              String username = et_username.getText().toString();

              String password = et_password.getText().toString();

              OutputStream os = conn.getOutputStream();

              String req = "username="+username+"&password="+password;

              os.write(req.getBytes());

              if(conn.getResponseCode()== 200){

                    InputStream is = conn.getInputStream();

                    BufferedReader br = new BufferedReader(new InputStreamReader(is));

                    String result = br.readLine();

                    Toast.makeText(this, result, Toast.LENGTH_LONG).show();

                    is.close();

                    os.close();

                    conn.disconnect();

              }              

         } catch (Exception e) {

              // TODO Auto-generated catch block

              e.printStackTrace();

         }

 }

然后在onClick()中调用该方法。

注意到,这里由于只有一个线程,即在主线程(UI线程)中请求服务器,若有耗时操作,此时应用是不会响应用户操作的,这就是传说中的ANR异常

所以,就必须新建一个子线程执行耗时操作。

修改get_test()方法,新建一个线程执行该方法中的操作:

 private void get_test() {

         new Thread(new Runnable() {

              @Override

              public void run() {

                    String username = et_username.getText().toString();

                    String password = et_password.getText().toString();

                    try {

                         URL url = new URL("http://10.0.2.2/index.php?username="+username+"&password="+password);

                         HttpURLConnection conn =  (HttpURLConnection) url.openConnection();

                         conn.setRequestMethod("GET");

                         conn.setConnectTimeout(5000);

                         conn.setReadTimeout(5000);

                         if(conn.getResponseCode() == 200){

                               InputStream is = conn.getInputStream();

                               BufferedReader br = new BufferedReader(new InputStreamReader(is));

                               String result = br.readLine();

                               Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();

                               conn.disconnect();

                         }

                    } catch (Exception e) {

                         // TODO Auto-generated catch block

                         e.printStackTrace();

                    }

              }

         }).start();

   }

这时重新运行程序,会发现新的问题:

提示,无法在非UI线程中进行UI操作,因为这样不安全。

为了解决这个问题,android提供了一套消息处理机制,很像win32中的消息循环机制。

下面简单说明下这套机制:

引入消息机制后:

这套消息机制主要涉及到两个类:HandlerMessage

Handler

一般需要自定义Handler继承Handler类,并重写消息处理方法,一般将其对象在UI线程中定义,这样就可以在其消息处理方法中进行UI操作了。

常用方法:

消息处理回调函数,一般自定义的Handler类都要重写该方法,添加自己需要的消息处理业务逻辑。

sendMessage(Message msg)发送一条消息。

Message

消息类,其对象作为消息实体被handler对象发送或者接收处理。

使用无参构造创建一个消息对象,一般在发送之前还需要设置其两个主要的属性:

what属性,可以用来存放消息的类型

obj属性,可以用来存放想要传送的消息内容或者传递的其他参数等。

修改上面的应用,添加消息处理机制:

在MainActivity中添加个Handler类型的私有属性:

 private Handler handler = new Handler(){

            public void handleMessage(android.os.Message msg) {

                  if(msg.what == OK){

                       String str = msg.obj.toString();

                       Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();

                  }

            }

 };

重写的消息处理函数,很简单,就是把服务端返回的信息通过Toast显示出来。

添加一个方法,新建线程请求服务端数据,并通过消息机制发送消息:

 private void multi_thread_test(){

            new Thread(new Runnable() {

                  @Override

                  public void run() {

                       // TODO Auto-generated method stub

                       try {

                             URL url = new URL("http://10.0.2.2/index.php");

                             HttpURLConnection conn = (HttpURLConnection) url.openConnection();

                             conn.setRequestMethod("POST");

                             conn.setDoOutput(true);

                             conn.setConnectTimeout(5000);

                             conn.setReadTimeout(5000);

                             String username = et_username.getText().toString();

                             String password = et_password.getText().toString();

                             OutputStream os = conn.getOutputStream();

                             String req = "username="+username+"&password="+password;

                             os.write(req.getBytes());

                             if(conn.getResponseCode()== 200){

                                   InputStream is = conn.getInputStream();

                                   BufferedReader br = new BufferedReader(new InputStreamReader(is));

                                   String result = br.readLine();

                                   Message msg = new Message();

                                   msg.what = OK;

                                   msg.obj = result;

                                   handler.sendMessage(msg);

                                   is.close();

                                   os.close();

                                   conn.disconnect();

                             }                    

                       } catch (Exception e) {

                             // TODO Auto-generated catch block

                             e.printStackTrace();

                       }

                  }

            }).start();

 }

这样,在请求服务端数据时,应用还能响应用户的交互。

2.还有另一种与服务端进行交互的方式,那就是使用HttpClient

一般通过:

HttpClient client = new defaultHttpClient() 构造出HttpClient对象。

HttpClient类最主要的一个方法就是execute()方法。

常用的是只有一个参数的重载形式,注意到其参数类型是HttpUriRequest类型。

查看帮助手册:

HttpUriRequest是一个接口

已知的直接实现类,有那么多个,最常用的是HttpGet和HttpPost,从名字中便可知道,一个用于get方式与服务端交互,一个用于post方式与服务端交互。

HttpGet的使用比较简单

一般直接使用传入String类型的url构造出HttpGet对象,然后作为execute()的参数即可完成get方式请求。

HttpPost的使用要稍微麻烦一点,因为GET方式直接在URL中传入了请求参数,而POST方式需要另外一种传参方式。

POST方式的参数需要使用一个List<NameValuePair>类型的对象传递,

NameValuePair是一个接口,一般使用的是其直接实现类BasicNameValuPair类:

如:

 List<NameValuePair> params = new ArrayList<NameValuePair>();

 params.add(new BasicNameValuePair("username", username));

 params.add(new BasicNameValuePair("password", password));

要POST的参数存储完成,如何通过HttpPost提交呢?

注意到,帮助手册中关于HttpPost的信息:

HttpPost是通过继承HttpEntitiyEnclosingRequestBase类间接实现HttpUriRequest接口的。

该类中有一个方法:

可以通过setEntity()方法将参数传递给HttpPost对象,具体做法如下:

 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params,"utf-8");

 httppost.setEntity(entity);

下面在MainActivity中添加方法,通过HttpClient方法与服务端进行交互:

 private void client_get_test(){

            new Thread(new Runnable() {

                  @Override

                  public void run() {

                       // TODO Auto-generated method stub

                       String username = et_username.getText().toString();

                       String password = et_password.getText().toString();

                       HttpClient client = new DefaultHttpClient();

                       HttpGet get = new HttpGet("http://10.0.2.2/index.php?username="+username+"&password="+password);

                       try {

                             HttpResponse response = client.execute(get);

                             if(response.getStatusLine().getStatusCode() == 200){

                                   HttpEntity entity = response.getEntity();

                                   String result = EntityUtils.toString(entity, "utf-8");

                                   Message msg = new Message();

                                   msg.what = OK;

                                   msg.obj = result;

                                   handler.sendMessage(msg);

                             }

                       } catch (ClientProtocolException e) {

                             // TODO Auto-generated catch block

                             e.printStackTrace();

                       } catch (IOException e) {

                             // TODO Auto-generated catch block

                             e.printStackTrace();

                       }

                  }

            }).start();

       }

使用HttpClient采用GET方式向服务端请求数据

 private void client_post_test(){

            new Thread(new Runnable() {

                  @Override

                  public void run() {

                       // TODO Auto-generated method stub

                       try {

                             String username = et_username.getText().toString();

                             String password = et_password.getText().toString();

                             HttpClient client = new DefaultHttpClient();

                             HttpPost post = new HttpPost("http://10.0.2.2/index.php");

                             List<NameValuePair> params = new ArrayList<NameValuePair>();

                             params.add(new BasicNameValuePair("username", username));

                             params.add(new BasicNameValuePair("password", password));

                             UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params,"utf-8");

                             post.setEntity(entity);

                             HttpResponse response = client.execute(post);

                             if(response.getStatusLine().getStatusCode() == 200){

                                   HttpEntity entity1 = response.getEntity();

                                   String result = EntityUtils.toString(entity1, "utf-8");

                                   Message msg = new Message();

                                   msg.what = OK;

                                   msg.obj = result;

                                   handler.sendMessage(msg);

                             }

                       } catch (ClientProtocolException e) {

                             // TODO Auto-generated catch block

                             e.printStackTrace();

                       } catch (IOException e) {

                             // TODO Auto-generated catch block

                             e.printStackTrace();

                       }

                  }

            }).start();

 }

使用HttpClient采用POST方式向服务端请求数据。

以上就是向服务端请求数据的简单学习。

最新文章

  1. Microsoft Visual Studio 文件识别及其用途简述
  2. LINQ to SQL语句(11)之Update
  3. 【整理】C#文件操作大全(SamWang)&lt;转&gt;
  4. JAVA与指针
  5. 数据库语言(一):SQL语法实例整理
  6. Jenkins 八: 构建Git项目
  7. start with connect by prior学习
  8. rtmpdump代码分析 转
  9. centos 下mysql操作
  10. 构建一个用于产品介绍的WEB应用
  11. POJ 1700 经典过河问题(贪心)
  12. 使用Post方法模拟登陆爬取网页
  13. 4.VUEX到底是什么
  14. PyCharm 专题
  15. qml demo分析(threadedanimation-线程动画)
  16. Tesseract 在 windows 下的安装及简单应用
  17. Django 中的JsonResponse 和 json区别
  18. 【20】策略者模式(Strategy Pattern)
  19. javascript ----&gt; Immediately-Invoked Function Expression (IIFE)(翻译)
  20. 读DataSnap源代码(三)

热门文章

  1. log4j教程 5、示例程序
  2. boolean类型的特殊的get和set方法
  3. mysql 修改字符集为utf8mb4
  4. iOS_新版iOS11 UITbleView适配的一些问题及解决方法
  5. vscode - 更改emmet生成代码
  6. web前端性能优化汇总
  7. Singleton单例模式是最简单的设计模式,它的主要作用是保证在程序执行生命周期中,使用了单类模式的类仅仅能有一个实例对象存在。
  8. 代理工具Charles使用
  9. 超高逼格Log日志打印
  10. PHP面试题及答案解析(8)—PHP综合应用题