《精通android网络开发》--HTTP数据通信

Posted 嘉禾世兴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《精通android网络开发》--HTTP数据通信相关的知识,希望对你有一定的参考价值。

No1:

例如:http://www.*****.com/china/index.htm

1)http://  代表超文本传送协议,通知*****.com服务器显示web页,通常不用输入

2)www  代表一个web(万维网)服务器

3)*****.com/  这是装有网页的服务器的域名,或站点服务器的名称

4)china/  为该服务器上的子目录,就好像文件夹

5)index.htm  index.htm是文件夹中的一个html文件(网页)

No2:

HTTP协议(超文本传送协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议。

No3:

android系统提供了以下3种通信接口

1)标准Java接口:java.net

2)Apache接口:org.apache.http

3)android网络接口:android.net.http

在android系统中包括apache httpclient库,此库为执行android中的网络操作之首选方法。

此外,android还允许通过标准的java联网api(java.net包)来访问网络。即使java.net包,也是在内部使用该apache库

No4:

android系统中,存在以下与网络连接相关的包

1)java.net

提供联网相关的类,包括流和数据报套接字、互联网协议以及通用的HTTP处理。此为多用途的联网资源。经验丰富的java开发人员可立即使用此惯用的包来创建应用程序

2)java.io

尽管未明确联网,但其仍然非常重要。此包中的各种类通过其他java包中提供的套接字和链接来使用。它们也可用来与本地文件进行交互(与网络进行交互时经常发生)

3)java.nio

包含表示具体数据类型的缓冲的各种类。便于基于java语言的两个端点之间的网络通信

4)org.apache.*

表示可为进行HTTP通信提供精细控制和功能的各种包。可以将apache识别为普通的开源web服务器

5)android.net

包括核心java.net.*类之外的各种附加的网络接入套接字。此包包括URL类,其通常在传统联网之外的android应用程序开发中使用

6)android.net.http

包含可操作SSL证书的各种类

7)android.net.wifi

包含可管理android平台中wi-fi(802.11无线以太网)所有方面的各种类。并非所有的设备均配备有wi-fi能力,尤其随着android在对制造商(如诺基亚和LG)手机的翻盖手机研发方面取得了进展

8)android.telephony.gsm

包含管理和发送短信(文本)消息所要求的各种类。随着时间的推移,可能将引入一种附加的包,以提供有关GSM网络(如CDMA或类似android.telephony.cdma)的类似功能

No5:

Apache联网流程

在android系统中,可以采用HttpPost和HttpGet来封装Post请求和HttpGet来封装Post请求和Get请求,再使用HttpClient的execute方法发送Post或者Get请求并返回服务器的响应数据。
1)设置连接和读取超时时间,并新建HttpClient对象

//设置连接超时时间和数据读取超时时间
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams,KeySource.CONNECTION_TIMEOUT_INT);
HttpConnectionParams.setSoTimeout(httpParams,KeySource.SO_TIMEOUT_INT);
//新建HttpClient对象
HttpClient httpClient = new DefaultHttpClient(httpParams);

2)实现Get请求

//获取请求
HttpGet get = new HttpGet(url);
//set Http head parameters
//Map<String,String> headers
if(headers!=null){
    Set<String> setHead = headers.keySet();
    Iterator<String> iteratorHead = setHead.iterator();
    while(iteratorHead.hasNext()){
        String headerName = iteratorHead.next();
        String headValue = (String)headers.get(headerName);
        MyLog.d(headerName,headValue);
        get.setHeader(headerName,headValue);
    }
}
//connect
//need try catch
response = httpClient.execute(get);

3)实现Post发送请求处理

HttpPost post = new HttpPost(KeySource.HOST_URL_STR);
//set HTTP head parameters
Map<String,String> headers = heads;
Set<String> setHead = headers.keySet();
Iterator<String> iteratorHead = setHead.iterator();
while(iteratorHead.hasNext()){
    String headName = iteratorHead.next();
    String headValue = (String)headers.get(headName);
    post.setHeader(headName,headValue);
}
/**
  * 通常的HTTP实体需要在执行上下文的时候动态生成的。
  * HttpClient的提供使用EntityTemplate实体类和ContentProducer接口支持动态实体
  * 内容制作是通过写需求的内容到一个输出流,每次请求的时候都会产生
  * 因此,通过EntityTemplate创建实体通常是独立的,重复性好
  */
ContentProducer cp = new ContentProducer(){
    public void writeTo(OutputStream outstream) throws IOException{
        Writer writer = new OutputStreamWriter(outstream,"UTF-8");
        writer.write(requestBody);
        writer.flush();
        writer.close();
    };
    HttpEntity entity = new EntityTemplate(cp);
    post.setEntity(entity);
} 
//connect,need try catch
response = httpClient.execute(post);

4)通过Response响应请求

if(response.getStatusLine().getStatusCode() == 200){
    /**
     * 因为直接调用toString()可能会导致某些中文字符出现乱码的情况,所以此处使用toByteArray.
     * 如果需要转成String对象,可以先调用EntityUtils.toByteArray()方法将消息实体转成byte数组,再由new String(byte[] bArray)转换成字符串
     */
    byte[] bResultXml = EntityUtils.toByteArray(response.getEntity());
    if(bResultXml != null){
        String strXml = new String(bResultXml,"utf-8");
    }
}

无论多么复杂的项目,都需要遵循上面的流程

No6:

Apache的核心功能是HttpClient,android的SDK提供了apache的httpClient来方便我们使用各种HTTP服务。可以把HttpClient想象成一个浏览器,通过它的API我们可以很方便的发出Get请求和Post请求

try{
    //创建一个默认的HttpClient
    HttpClient httpClient = new DefaultHttpClient();
    //创建一个Get请求
    HttpGet request = new HttpGet("www.google.com");
    //发送Get请求,并将响应内容转换成字符串
    String response = httpClient.execute(request,new BasicResponseHandler());
    Log.v("response text",response);
}catch(ClientProtocolException e){
    e.printStackTrace();
}catch(IOException e){
    e.printStackTrace();
}

No7:

多线程HttpClient

public class CustomerHttpClient{
    private static final String CHARSET = HTTP.UTF_8;
    private static HttpClient customerHttpClient;
    private CustomerHttpClient(){}
    public static synchronized HttpClient getHttpClient(){
        if(null == customerHttpClient){
            HttpParams params = new BasicHttpParams();
            //设置一些基本参数
            HttpProtocolParams.setVersion(params,HttpVersion.HTTP_1_1);
            HttpProtocolParams.setContentCharset(params,CHARSET);
            HttpprotocolParams.setUseExpectContinue(params,true);
            HttpProtocolParams.setUserAgent(params,"Mozilla/5.0(Linux;U;Android 2.2.1;en-us;Nexus One Build.FRG83)"+"AppleWebKit/553.1(KHTML,like Cecko) Version/4.0 Mobile Safari/533.1");
            //超时设置
            /*从连接池中取连接的超时时间*/
            ConManagerParams.setTimeout(params,1000);
            /*连接超时*/
            HttpConnectionParams.setConnectionTimeout(params,2000);
            /*请求超时*/
            HttpConnectionParams.setSoTimeout(params,4000);
            //设置HttpClient支持HTTP和HTTPS两种模式
            SchemeRegistery schReg = new SchemeRegistry();
            schReg.register(new Scheme("http",PlainSocketFactory.getSocketFactory(),80));
            schReg.register(new Scheme("https",SSLSocketFactory.getSocketFactory(),443));
            //使用线程安全的链接管理来创建HttpClient
            ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params,schReg);
            customerHttpClient = new DefaultHttpClient(conMgr,params);
        }
        return customerHttpClient;
    }
}

No8:

把HttpClient封装在Application

public class MyApplication extends Application{
    private HttpClient httpClient;
    
    @Override
    public void onCreate(){
        super.onCreate();
        httpClient = this.createHttpClient();
    }
    
    @Override
    public void onLowMemory(){
        super.onLowMemory();
        this.shutdownHttpClient();
    }
    
    @Override
    public void onTerminate(){
        super.onTerminate();
        this.shutdownHttpClient();
    }
    
    //创建HttpClient实例
    private HttpClient createHttpClient(){
        HttpPrarms params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params,HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params,HTTP.DEFAULT_CONTENT_CHARSET);
        HttpProtocolParams.setUseExceptionContinue(params,true);
        
        SchemeRegistry schReg = new SchemeRegistry();
        schReg.register(new Scheme("http",PlainSocketFactory.getSocketFactory(),80));
        schReg.register(new Scheme("https",SSLSocketFactory.getSocketFactory,443));
        
        ClientConnectionManager connMgr = new ThreadSafeClientConnManager(params,schReg);
        
        return new DefaultHttpClient(connMgr,params);
    }
    
    //关闭连接管理器并释放资源
    private void shutdownHttpClient(){
        if(httpClient!=null && httpClient.getConnectionManager()!=null){
            httpClient.getConnectionManager.shutdown();
        }
    }
    
    //对外提供HttpClient实例
    public HttpClient getHttpClient(){
        return httpClient;
    }
}

No9:

IP地址是给每个连接在Internet上的主机分配的一个32bit地址。java.net中处理IP地址的类是InetAddress

String GetHostAddress(String strHostName){
    InetAddress address = null;
    try{
        address = InetAddress.getByName(strHostName);
    }catch(UnknownHostException e){
        System.out.println(e.getMessage());
    }
    return InetAddress.getHostAddress();
}

void GetAllIp(String strHostName){
    InetAddress[] add = null;
    try{
        add = InetAddress.getAllByName(strHostName);
        for(int i = 0;i<addr.lenth;i++){
            System.out.println(addr[i]);
        }
    }catch(UnknownHostException){
        System.out.println(e.getMessage());
    }
}

网络异常是比较常见的现象,所以必须要捕获

No10:

URL类

Void EasyURL(String strURL){
    URL url = new URL(strURL);
    try{
        InputStream html = url.openStream();
        int c;
        do{
            c = html.read();
            cf(c!=-1) System.out.println((char)c);
        }while(c!=-1)
    }catch(IOException e){
        System.out.println(e.getMessage());
    }
}

No11:

套接字Socket

基本思想:客户端建立一个到服务器的链接,一旦链接建立了,客户端就可以往套接字里写入数据,并向服务器发送数据;反过来,服务器读取客户端写入套接字里的数据。

void WebPing(String strUrl){
    try{
        InetAddress addr;
        Socket sock = new Socket(strUrl,80);
        Addr = sock.getInetAddress();
        System.out.println("Connected to"+addr);
        Sock.close();
    }catch(IOException e){
        System.out.println(e.getMessage());
    }
}

No12:

URLConnection

使用场景例如:HTTP数据头的传递。

void SendRequest(String strURL){
    URL url = URL(strURL);
    HttpURLConnection conn = (HttpURLConnection)url.openConnection();
    conn.setDoInput(true);
    conn.setDoOutput(true);
    conn.setRequestProperty("Content-type","application/xxx");
    conn.coonnect();
    System.out.println(Conn.getResponseMessage());
    InputMessage is = Conn.getInputStream();
    int c;
    do{
        c = is.read();
        if(c!=-1) System.out.println((char)c);
    }while(c!=-1)
}

No13:

android网络接口android.net.http来处理HTTP请求,android.net.http是android.net中的一个包,在里面主要包含处理SSL证书的类。

在android.net.http中存在如下4个类:

1)AndroidHttpClient

2)SslCertificate

3)SslCertificate.DName

4)SslError

AndroidHttpClient就是用来处理HTTP请求的。

android.net.*实际上是通过对Apache的HttpClient的封装来实现的一个HTTP编程接口,同时还提供了HTTP请求队列管理,以及HTTP连接池管理,以提高并发请求情况下(如转载网页时)的处理效率,除此之外还有网络状态监听等接口。


以上是关于《精通android网络开发》--HTTP数据通信的主要内容,如果未能解决你的问题,请参考以下文章

《精通android网络开发》--使用Socket实现数据通信

[Android开发从入门到精通]扶松柏下载

Android Jetpack架构组件从入门到精通,完整版在线分享

(转)Android开发书籍推荐:从入门到精通系列学习路线书籍介绍

Android 学习资料入门到精通(PDF集合)共54本

Android NDK 从入门到精通