你的位置:首页 > 操作系统

[操作系统]android菜鸟学习笔记24


主要是基于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与服务端进行交互

布局文件代码:

 1 <LinearLayout ="http://schemas.android.com/apk/res/android" 2  3   ="http://schemas.android.com/tools" 4  5   android:layout_width="match_parent" 6  7   android:layout_height="match_parent" 8  9   android:orientation="vertical"10 11   tools:context="cn.csc.start.MainActivity" >12 13   <EditText14 15     android:id="@+id/et_username"16 17     android:layout_width="match_parent"18 19     android:layout_height="wrap_content"20 21     android:hint="@string/et_username_text"/>22 23   <EditText24 25     android:id="@+id/et_password"26 27     android:layout_width="match_parent"28 29     android:layout_height="wrap_content"30 31     android:inputType="textPassword"32 33     android:hint="@string/et_password_text"/>34 35   <Button36 37     android:id="@+id/btn_login"38 39     android:layout_width="wrap_content"40 41     android:layout_height="wrap_content"42 43     android:text="@string/btn_text"44 45     />46 47 </LinearLayout>

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

 1 <?php 2  3 if(isset($_REQUEST["username"])&& isset($_REQUEST["password"])){ 4  5    $username = $_REQUEST["username"]; 6  7    $password = $_REQUEST["password"]; 8  9    if($username == "zhangsan" && $password == "123"){10 11      echo "login success";12 13    }else{14 15      echo "login failure";16 17    }18 19 }else{20 21    echo "no field allowed empty string";22 23 }24 25 ?>

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

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

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

 1 public class MainActivity extends ActionBarActivity implements OnClickListener { 2  3  4  5   protected static final int OK = 0; 6  7    protected static final String TAG = "MYLOG"; 8  9    private EditText et_username;10 11    private EditText et_password;12 13    @Override14 15   protected void onCreate(Bundle savedInstanceState) {16 17     super.onCreate(savedInstanceState);18 19     setContentView(R.layout.activity_main);20 21     Button btn = (Button) findViewById(R.id.btn_login);22 23     btn.setOnClickListener(this);24 25     et_username = (EditText) findViewById(R.id.et_username);26 27     et_password = (EditText) findViewById(R.id.et_password);28 29 }30 31  @Override32 33  public void onClick(View view) {34 35     // TODO Auto-generated method stub36 37     if(view.getId() == R.id.btn_login){38 39        get_test();40 41     }42 43  }44 45 private void get_test() {46 47     // TODO Auto-generated method stub48 49     String username = et_username.getText().toString();50 51     String password = et_password.getText().toString();52 53     try {54 55       URL url = new URL("http://10.0.2.2/index.php?username="+username+"&password="+password);56 57       HttpURLConnection conn = (HttpURLConnection) url.openConnection();58 59       conn.setRequestMethod("GET");60 61       conn.setConnectTimeout(5000);62 63       conn.setReadTimeout(5000);64 65       if(conn.getResponseCode() == 200){66 67          InputStream is = conn.getInputStream();68 69          BufferedReader br = new BufferedReader(new InputStreamReader(is));70 71          String result = br.readLine();72 73          Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();74 75           conn.disconnect();76 77        }78 79       80 81     } catch (Exception e) {82 83       // TODO Auto-generated catch block84 85        e.printStackTrace();86 87     }88 89  }90 91 }

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

添加一个post_test方法:

 1 private void post_test(){ 2  3     try { 4  5       URL url = new URL("http://10.0.2.2/index.php"); 6  7       HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 8  9       conn.setRequestMethod("POST");10 11       conn.setDoOutput(true);12 13       conn.setConnectTimeout(5000);14 15       conn.setReadTimeout(5000);16 17       String username = et_username.getText().toString();18 19       String password = et_password.getText().toString();20 21       OutputStream os = conn.getOutputStream();22 23       String req = "username="+username+"&password="+password;24 25       26 27        os.write(req.getBytes());28 29       if(conn.getResponseCode()== 200){30 31          InputStream is = conn.getInputStream();32 33          BufferedReader br = new BufferedReader(new InputStreamReader(is));34 35          String result = br.readLine();36 37          Toast.makeText(this, result, Toast.LENGTH_LONG).show();38 39           is.close();40 41           os.close();42 43           conn.disconnect();44 45        }       46 47     } catch (Exception e) {48 49       // TODO Auto-generated catch block50 51        e.printStackTrace();52 53     }54 55 }

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

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

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

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

 1 private void get_test() { 2  3     new Thread(new Runnable() { 4  5        @Override 6  7       public void run() { 8  9          String username = et_username.getText().toString();10 11          String password = et_password.getText().toString();12 13          try {14 15             URL url = new URL("http://10.0.2.2/index.php?username="+username+"&password="+password);16 17             HttpURLConnection conn = (HttpURLConnection) url.openConnection();18 19             conn.setRequestMethod("GET");20 21             conn.setConnectTimeout(5000);22 23             conn.setReadTimeout(5000);24 25             if(conn.getResponseCode() == 200){26 27                InputStream is = conn.getInputStream();28 29                BufferedReader br = new BufferedReader(new InputStreamReader(is));30 31                String result = br.readLine();32 33                Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();34 35                conn.disconnect();36 37             }38 39            40 41          } catch (Exception e) {42 43             // TODO Auto-generated catch block44 45             e.printStackTrace();46 47           }48 49        }50 51     }).start();52 53  }

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

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

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

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

 

引入消息机制后:

 

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

Handler

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

常用方法:

 

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

 

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

Message

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

 

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

 

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

 

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

 

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

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

 1 private Handler handler = new Handler(){ 2  3      public void handleMessage(android.os.Message msg) { 4  5         if(msg.what == OK){ 6  7            String str = msg.obj.toString(); 8  9            Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();10 11           12 13          }14 15       }16 17 };

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

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

 1 private void multi_thread_test(){ 2  3      new Thread(new Runnable() { 4  5          6  7          @Override 8  9         public void run() {10 11            // TODO Auto-generated method stub12 13            try {14 15               URL url = new URL("http://10.0.2.2/index.php");16 17               HttpURLConnection conn = (HttpURLConnection) url.openConnection();18 19               conn.setRequestMethod("POST");20 21               conn.setDoOutput(true);22 23               conn.setConnectTimeout(5000);24 25               conn.setReadTimeout(5000);26 27               String username = et_username.getText().toString();28 29               String password = et_password.getText().toString();30 31               OutputStream os = conn.getOutputStream();32 33               String req = "username="+username+"&password="+password;34 35              36 37               os.write(req.getBytes());38 39               if(conn.getResponseCode()== 200){40 41                  InputStream is = conn.getInputStream();42 43                  BufferedReader br = new BufferedReader(new InputStreamReader(is));44 45                  String result = br.readLine();46 47                  Message msg = new Message();48 49                  msg.what = OK;50 51                  msg.obj = result;52 53                  handler.sendMessage(msg);54 55                  is.close();56 57                  os.close();58 59                  conn.disconnect();60 61               }          62 63            } catch (Exception e) {64 65               // TODO Auto-generated catch block66 67               e.printStackTrace();68 69            }70 71          }72 73       }).start();74 75 }

 

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

 

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类:

如:

1 List<NameValuePair> params = new ArrayList<NameValuePair>();2 3 params.add(new BasicNameValuePair("username", username));4 5 params.add(new BasicNameValuePair("password", password));

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

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

 

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

该类中有一个方法:

 

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

1 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params,"utf-8");2 3 httppost.setEntity(entity);

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

 1 private void client_get_test(){ 2  3      new Thread(new Runnable() { 4  5          6  7          @Override 8  9         public void run() {10 11            // TODO Auto-generated method stub12 13            String username = et_username.getText().toString();14 15            String password = et_password.getText().toString();16 17            HttpClient client = new DefaultHttpClient();18 19            HttpGet get = new HttpGet("http://10.0.2.2/index.php?username="+username+"&password="+password);20 21            try {22 23               HttpResponse response = client.execute(get);24 25               if(response.getStatusLine().getStatusCode() == 200){26 27                  HttpEntity entity = response.getEntity();28 29                  String result = EntityUtils.toString(entity, "utf-8");30 31                  Message msg = new Message();32 33                  msg.what = OK;34 35                  msg.obj = result;36 37                  handler.sendMessage(msg);38 39               }40 41            } catch (ClientProtocolException e) {42 43               // TODO Auto-generated catch block44 45               e.printStackTrace();46 47            } catch (IOException e) {48 49               // TODO Auto-generated catch block50 51               e.printStackTrace();52 53            }54 55          }56 57       }).start();58 59    }

 

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

 1 private void client_post_test(){ 2  3      new Thread(new Runnable() { 4  5          6  7          @Override 8  9         public void run() {10 11            // TODO Auto-generated method stub12 13           14 15            try {16 17               String username = et_username.getText().toString();18 19               String password = et_password.getText().toString();20 21               HttpClient client = new DefaultHttpClient();22 23               HttpPost post = new HttpPost("http://10.0.2.2/index.php");24 25               List<NameValuePair> params = new ArrayList<NameValuePair>();26 27               params.add(new BasicNameValuePair("username", username));28 29               params.add(new BasicNameValuePair("password", password));30 31               UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params,"utf-8");32 33               post.setEntity(entity);34 35               HttpResponse response = client.execute(post);36 37               if(response.getStatusLine().getStatusCode() == 200){38 39                  HttpEntity entity1 = response.getEntity();40 41                  String result = EntityUtils.toString(entity1, "utf-8");42 43                  Message msg = new Message();44 45                  msg.what = OK;46 47                  msg.obj = result;48 49                  handler.sendMessage(msg);50 51               }52 53            } catch (ClientProtocolException e) {54 55               // TODO Auto-generated catch block56 57               e.printStackTrace();58 59            } catch (IOException e) {60 61               // TODO Auto-generated catch block62 63               e.printStackTrace();64 65            }66 67          }68 69       }).start();70 71 }

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

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

 




安徽旅游必去景点排名安徽旅游地图线路大全安徽旅游多少钱安徽旅游攻略大全安徽旅游攻略自助游广州南沙水鸟世界有出租单车吗?南沙水鸟世界骑单车怎么收费? 南沙水鸟世界生态园有游览车吗?广州南沙水鸟世界门票包括游览车吗? 南沙水鸟世界生态园电瓶车怎么收费?广州南沙水鸟世界景区游览车价格? 南沙水鸟世界套票多少钱?广州南沙水鸟世界套票优惠吗? 到统景泡汤玩蹦极 蹦极篇 到统景泡汤玩蹦极 体验别样玩法 西安能看欧巴的韩式咖啡馆 漫咖啡 西安那些能看欧巴的韩式咖啡馆 海陵岛敏捷黄金海岸广州开车怎么去?广州到阳江海陵岛敏捷黄金海岸路线? 番禺南沙湿地公园钓鱼攻略?南沙湿地公园玩什么? 番禺南沙湿地公园路线?南沙湿地公园游玩时间? 广州番禺南沙湿地公园好玩么?番禺南沙湿地公园游玩攻略? 学生去澳门旅游住哪里好? 澳门DFS环球免税店在哪?怎么去? 香港圣诞节放假吗?放几天啊? 去香港旅游住旅馆要注意什么? SQCA5A301JA1ME Datasheet SQCA5A301JA1ME Datasheet 08055C683J4T4A Datasheet 08055C683J4T4A Datasheet AQ12EA430GAJME Datasheet AQ12EA430GAJME Datasheet 连云港去港澳旅游 连云港去港澳旅游 连云港去港澳旅游 内蒙古去港澳旅游 内蒙古去港澳旅游 内蒙古去港澳旅游 温州去香港旅游 温州去香港旅游 温州去香港旅游