Android开发之网络通讯详解

  1. WebView的用法

      Android提供了一个WebView控件,借助它我们就可以在自己的应用程序里嵌入一个浏览器,从而非常轻松地展示各种各样的网页。WebView的用法也是相当简单,下面我们就通过一个例子来学习一下吧。新建一个WebViewTest项目,然后修改activity_main.xml中的代码,如下所示:

<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">

    <WebView
        android:id="@+id/web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

  然后修改MainActivity中的代码,如下所示:

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.webkit.WebView;
import android.webkit.WebViewClient;
 public class MainActivity extends Activity {
  private WebView webView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webView=(WebView) findViewById(R.id.web_view);
             webView.getSettings().setJavaScriptEnabled(true);//调用了setJavaScriptEnabled()
        //方法来让WebView支持JavaScript脚本
        webView.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {    
                    view.loadUrl(url); // 根据传入的参数再去加载新的网页
                    return true; // 表示当前WebView可以处理打开新网页的请求,不用借助系统浏览器
                    }
        });
        webView.loadUrl("http://www.baidu.com/");
    }
    @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;
    }
}

***MainActivity中的代码也很短,首先使用findViewById()方法获取到了WebView的实例,然后调用WebView的getSettings()方法可以去设置一些浏览器的属性,这里我们并不去设置过多的属性,只是调用了setJavaScriptEnabled()方法来让WebView支持JavaScript脚本。
接下来是非常重要的一个部分,我们调用了WebView的setWebViewClient()方法,并传入了WebViewClient的匿名类作为参数,然后重写了shouldOverrideUrlLoading()方法。这就表明当需要从一个网页跳转到另一个网页时,我们希望目标网页仍然在当前WebView中显示,而不是打开系统浏览器。
最后一步就非常简单了,调用WebView的loadUrl()方法,并将网址传入,即可展示相应网页的内容,这里就让我们看一看百度的首页是长什么样的吧。
另外还需要注意,由于本程序使用到了网络功能,而访问网络是需要声明权限的,因此我们还得修改AndroidManifest.xml文件,并加入权限声明,如下所示:


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.webviewtest"
    android:versionCode="1"
    android:versionName="1.0" >
<uses-permission **android:name="android.permission.INTERNET"/>**
    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="17" />

效果如图1所示:
2. 使用HTTP协议访问网络
  它的工作原理特别的简单,就是客户端向服务器发出一条HTTP请求,服务器收到请求之后会返回一些数据给客户端,然后客户端再对这些数据进行解析和处理就可以了。
  2.1 使用HttpURLConnection
  在Android上发送HTTP请求的方式一般有两种,HttpURLConnection和HttpClient,本小节我们先来学习一下HttpURLConnection的用法。
  首先需要获取到HttpURLConnection的实例,一般只需new出一个URL对象,并传入目标的网络地址,然后调用一下openConnection()方法即可,如下所示:
URL url = new URL(“http://www.baidu.com“);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
  得到了HttpURLConnection的实例之后,我们可以设置一下HTTP请求所使用的方法。常用的方法主要有两个,GET和POST。GET表示希望从服务器那里获取数据,而POST则表示希望提交数据给服务器。写法如下:
connection.setRequestMethod(“GET”);
  接下来就可以进行一些自由的定制了,比如设置连接超时、读取超时的毫秒数,以及服务器希望得到的一些消息头等。这部分内容根据自己的实际情况进行编写,示例写法如下:
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
  之后再调用getInputStream()方法就可以获取到服务器返回的输入流了,剩下的任务就是对输入流进行读取,如下所示:
InputStream in = connection.getInputStream();
  最后可以调用disconnect()方法将这个HTTP连接关闭掉,如下所示:
connection.disconnect();

  下面就让我们通过一个具体的例子来真正体验一下HttpURLConnection的用法。新建一个NetworkTest项目,首先修改activity_main.xml中的代码,如下所示:
  

<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"
    >
        <Button
        android:id="@+id/send_request"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Send Request" />
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent" >  
        <TextView
            android:id="@+id/response"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

   </ScrollView>
</LinearLayout>

 借助ScrollView控件的话就可以允许我们以滚动的形式查看屏幕外的那部分内容。另外,布局中还放置了一个Button和一个TextView,Button用于发送HTTP请求,TextView用于将服务器返回的数据显示出来。
 接着修改MainActivity中的代码,如下所示:
 

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Connection;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.content.DialogInterface;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity implements OnClickListener{
   public static final int SHOW_RESPONSE=0;
   private Button sendRequest;
   private TextView responseText;
   private Handler handler=new Handler(){
       public void handleMessage(Message msg){
           switch (msg.what) {
        case SHOW_RESPONSE:
            String response=(String) msg.obj;//在这里进行ui操作,将结果显示在界面上
            responseText.setText(response);
        }
       }
   };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sendRequest=(Button) findViewById(R.id.send_request);
        responseText=(TextView) findViewById(R.id.response);
        sendRequest.setOnClickListener(this);
    }

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

    @Override
    public void onClick(View v) {
        if(v.getId()==R.id.send_request){
            sendRequestWithHttpURLConnection();
        }

    }

    private void sendRequestWithHttpURLConnection() {
        // TODO Auto-generated method stub
        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                HttpURLConnection connection=null;
                try{
                    URL url=new URL("http://www.baidu.com");
                    connection=(HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(8000);
                    //设置链接超时的时间  
                    //将读超时设置为指定的超时值,以毫秒为单位。用一个非零值指定在建立到资源的连接后从input流读入时的超时时间。  
                    //如果在数据可读取之前超时期满,则会引发一个 java.net.sockettimeoutexception。超时时间为零表示无穷大超时。  
                    connection.setReadTimeout(8000);
                    InputStream in=connection.getInputStream();
                    //下面对获取到的输入流进行读取
                    BufferedReader reader=new BufferedReader(new InputStreamReader(in));
                    StringBuilder response=new StringBuilder();
                    String line;
                    while((line=reader.readLine())!=null){
                        response.append(line);
                    }
                    Message message=new Message();
                    message.what=SHOW_RESPONSE;
                    //将服务器返回的结果存放到Message中
                    message.obj=response.toString();
                    handler.sendMessage(message);
                }catch (Exception e) {
                    // TODO: handle exception
                    e.printStackTrace();
                }finally{
                    if(connection!=null){
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }


}

仍然别忘了要声明一下网络权限
现在运行一下程序,并点击Send Request按钮,结果如图2所示:
这里写图片描述
2.2 使用HttpClient
  HttpClient是Apache提供的HTTP网络访问接口,从一开始的时候就被引入到了Android API中。它可以完成和HttpURLConnection几乎一模一样的效果,但两者之间的用法却有较大的差别,那么我们自然要看一下HttpClient是如何使用的了。
  首先你需要知道,HttpClient是一个接口,因此无法创建它的实例,通常情况下都会创建一个DefaultHttpClient的实例,如下所示:
HttpClient httpClient = new DefaultHttpClient();
  接下来如果想要发起一条GET请求,就可以创建一个HttpGet对象,并传入目标的网络地址,然后调用HttpClient的execute()方法即可:
  HttpGet httpGet = new HttpGet(“http://www.baidu.com“);
  httpClient.execute(httpGet);
  如果是发起一条POST请求会比GET稍微复杂一点,我们需要创建一个HttpPost对象,并传入目标的网络地址,如下所示:
HttpPost httpPost = new HttpPost(“http://www.baidu.com“);
然后通过一个NameValuePair集合来存放待提交的参数,并将这个参数集合传入到一个UrlEncodedFormEntity中,然后调用HttpPost的setEntity()方法将构建好的UrlEncodedFormEntity传入,如下所示:
List params = new ArrayList();
params.add(new BasicNameValuePair(“username”, “admin”));
params.add(new BasicNameValuePair(“password”, “123456”));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, “utf-8”);
httpPost.setEntity(entity);
  接下来的操作就和HttpGet一样了,调用HttpClient的execute()方法,并将HttpPost对象传入即可:
httpClient.execute(httpPost);
  执行execute()方法之后会返回一个HttpResponse对象,服务器所返回的所有信息就会包含在这里面。通常情况下我们都会先取出服务器返回的状态码,如果等于200就说明请求和响应都成功了,如下所示:
if (httpResponse.getStatusLine().getStatusCode() == 200) {
// 请求和响应都成功了
}
  接下来在这个if判断的内部取出服务返回的具体内容,可以调用getEntity()方法获取到一个HttpEntity实例,然后再用EntityUtils.toString()这个静态方法将HttpEntity转换成字符串即可,如下所示:
HttpEntity entity = httpResponse.getEntity();
String response = EntityUtils.toString(entity);
  注意如果服务器返回的数据是带有中文的,直接调用EntityUtils.toString()方法进行转换会有乱码的情况出现,这个时候只需要在转换的时候将字符集指定成utf-8就可以了,如下所示:
String response = EntityUtils.toString(entity, “utf-8”);

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Connection;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
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.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.content.DialogInterface;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity implements OnClickListener{
   public static final int SHOW_RESPONSE=0;
   private Button sendRequest;
   private TextView responseText;
   private Handler handler=new Handler(){
       public void handleMessage(Message msg){
           switch (msg.what) {
        case SHOW_RESPONSE:
            String response=(String) msg.obj;//在这里进行ui操作,将结果显示在界面上
            responseText.setText(response);
        }
       }
   };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sendRequest=(Button) findViewById(R.id.send_request);
        responseText=(TextView) findViewById(R.id.response);
        sendRequest.setOnClickListener(this);
    }

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

    @Override
    public void onClick(View v) {
        if(v.getId()==R.id.send_request){
            sendRequestWithHttpURLConnection();
        }

    }

    private void sendRequestWithHttpURLConnection() {
        // TODO Auto-generated method stub
        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                HttpURLConnection connection=null;
                try{
                    HttpClient httpClient = new DefaultHttpClient();
                    HttpGet httpGet = new HttpGet("http://www.baidu.com");
                    HttpResponse httpResponse = httpClient.execute(httpGet);
                    if (httpResponse.getStatusLine().getStatusCode() == 200) {
                        // 请求和响应都成功了
                        HttpEntity entity = httpResponse.getEntity();
                        String response = EntityUtils.toString(entity, "utf-8");
                        Message message = new Message();
                        message.what = SHOW_RESPONSE;
                        // 将服务器返回的结果存放到Message中
                        message.obj = response.toString();
                        handler.sendMessage(message);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }


}
发布了37 篇原创文章 · 获赞 7 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章